WellKnownStrings.cs 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  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. using System;
  17. using System.Runtime.CompilerServices;
  18. namespace Grpc.Core.Internal
  19. {
  20. /// <summary>
  21. /// Utility type for identifying "well-known" strings (i.e. headers/keys etc that
  22. /// we expect to see frequently, and don't want to allocate lots of copies of)
  23. /// </summary>
  24. internal static class WellKnownStrings
  25. {
  26. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  27. private static unsafe ulong Coerce64(byte* value)
  28. {
  29. return *(ulong*)value;
  30. }
  31. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  32. private static unsafe uint Coerce32(byte* value)
  33. {
  34. return *(uint*)value;
  35. }
  36. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  37. private static unsafe ushort Coerce16(byte* value)
  38. {
  39. return *(ushort*)value;
  40. }
  41. /// <summary>
  42. /// Test whether the provided byte sequence is recognized as a well-known string; if
  43. /// so, return a shared instance of that string; otherwise, return null
  44. /// </summary>
  45. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  46. public static unsafe string TryIdentify(IntPtr source, int length)
  47. {
  48. return TryIdentify((byte*)source.ToPointer(), length);
  49. }
  50. /// <summary>
  51. /// Test whether the provided byte sequence is recognized as a well-known string; if
  52. /// so, return a shared instance of that string; otherwise, return null
  53. /// </summary>
  54. public static unsafe string TryIdentify(byte* source, int length)
  55. {
  56. // note: the logic here is hard-coded to constants for optimal processing;
  57. // refer to an ASCII/hex converter (and remember to reverse **segments** for little-endian)
  58. if (BitConverter.IsLittleEndian) // this is a JIT intrinsic; branch removal happens on modern runtimes
  59. {
  60. switch (length)
  61. {
  62. case 0: return "";
  63. case 10:
  64. switch(Coerce64(source))
  65. {
  66. case 0x6567612d72657375: return Coerce16(source + 8) == 0x746e ? "user-agent" : null;
  67. }
  68. break;
  69. }
  70. }
  71. else
  72. {
  73. switch (length)
  74. {
  75. case 0: return "";
  76. case 10:
  77. switch (Coerce64(source))
  78. {
  79. case 0x757365722d616765: return Coerce16(source + 8) == 0x6e74 ? "user-agent" : null;
  80. }
  81. break;
  82. }
  83. }
  84. return null;
  85. }
  86. }
  87. }