• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #region Copyright notice and license
2 // Copyright 2019 The gRPC Authors
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 #endregion
16 
17 using System;
18 using System.Runtime.CompilerServices;
19 
20 namespace Grpc.Core.Internal
21 {
22     /// <summary>
23     /// Utility type for identifying "well-known" strings (i.e. headers/keys etc that
24     /// we expect to see frequently, and don't want to allocate lots of copies of)
25     /// </summary>
26     internal static class WellKnownStrings
27     {
28         [MethodImpl(MethodImplOptions.AggressiveInlining)]
Coerce64(byte* value)29         private static unsafe ulong Coerce64(byte* value)
30         {
31             return *(ulong*)value;
32         }
33         [MethodImpl(MethodImplOptions.AggressiveInlining)]
Coerce32(byte* value)34         private static unsafe uint Coerce32(byte* value)
35         {
36             return *(uint*)value;
37         }
38         [MethodImpl(MethodImplOptions.AggressiveInlining)]
Coerce16(byte* value)39         private static unsafe ushort Coerce16(byte* value)
40         {
41             return *(ushort*)value;
42         }
43 
44 
45         /// <summary>
46         /// Test whether the provided byte sequence is recognized as a well-known string; if
47         /// so, return a shared instance of that string; otherwise, return null
48         /// </summary>
49         [MethodImpl(MethodImplOptions.AggressiveInlining)]
TryIdentify(IntPtr source, int length)50         public static unsafe string TryIdentify(IntPtr source, int length)
51         {
52             return TryIdentify((byte*)source.ToPointer(), length);
53         }
54 
55         /// <summary>
56         /// Test whether the provided byte sequence is recognized as a well-known string; if
57         /// so, return a shared instance of that string; otherwise, return null
58         /// </summary>
TryIdentify(byte* source, int length)59         public static unsafe string TryIdentify(byte* source, int length)
60         {
61             // note: the logic here is hard-coded to constants for optimal processing;
62             // refer to an ASCII/hex converter (and remember to reverse **segments** for little-endian)
63             if (BitConverter.IsLittleEndian) // this is a JIT intrinsic; branch removal happens on modern runtimes
64             {
65                 switch (length)
66                 {
67                     case 0: return "";
68                     case 10:
69                         switch(Coerce64(source))
70                         {
71                             case 0x6567612d72657375: return Coerce16(source + 8) == 0x746e ? "user-agent" : null;
72                         }
73                         break;
74                 }
75             }
76             else
77             {
78                 switch (length)
79                 {
80                     case 0: return "";
81                     case 10:
82                         switch (Coerce64(source))
83                         {
84                             case 0x757365722d616765: return Coerce16(source + 8) == 0x6e74 ? "user-agent" : null;
85                         }
86                         break;
87                 }
88             }
89             return null;
90         }
91     }
92 }
93