BinaryRwExtensionMethod.cs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. using System.Buffers;
  2. using System.IO.Pipelines;
  3. namespace PCC.App.BinaryFormatter;
  4. public static class BinaryRwExtensionMethod
  5. {
  6. public static void WriteBlock(this BinaryWriter writer, ReadOnlySpan<byte> data)
  7. {
  8. writer.Write7BitEncodedInt(data.Length);
  9. writer.Write(data);
  10. }
  11. public static void WriteBlock(this PipeWriter writer, byte[] data)
  12. {
  13. writer.Write7BitEncodedInt(data.Length);
  14. writer.Write(data);
  15. }
  16. public static void WriteBlock(this PipeWriter writer, ReadOnlyMemory<byte> data)
  17. {
  18. writer.Write7BitEncodedInt(data.Length);
  19. writer.Write(data.Span);
  20. }
  21. public static void Write(this BinaryWriter writer, DateTimeOffset dateTimeOffset)
  22. {
  23. writer.Write(dateTimeOffset.ToUnixTimeMilliseconds());
  24. }
  25. public static DateTimeOffset ReadDateTimeOffset(this BinaryReader reader)
  26. {
  27. return DateTimeOffset.FromUnixTimeMilliseconds(reader.ReadInt64());
  28. }
  29. /// <summary>
  30. /// 向 PipeWriter 中写入 7 位编码的整数。
  31. /// </summary>
  32. /// <param name="writer">PipeWriter,用于写入数据</param>
  33. /// <param name="value">需要编码的整数</param>
  34. private static void Write7BitEncodedInt(this PipeWriter writer, int value)
  35. {
  36. Span<byte> buffer = stackalloc byte[5]; // 最多需要 5 个字节来编码 int
  37. int index = 0;
  38. // 循环,直到处理完所有 7 位段
  39. while (value >= 0x80)
  40. {
  41. // 写入低 7 位,并将最高位置 1 表示后续还有数据
  42. buffer[index++] = (byte)(value & 0x7F | 0x80);
  43. value >>= 7; // 继续处理剩余部分
  44. }
  45. // 最后一个字节,最高位为 0
  46. buffer[index++] = (byte)(value & 0x7F);
  47. // 将编码后的字节写入 PipeWriter
  48. writer.Write(buffer.Slice(0, index));
  49. }
  50. public static byte[] ReadBlock(this BinaryReader reader) => reader.ReadBytes(reader.Read7BitEncodedInt());
  51. /// <summary>
  52. /// 从 SequenceReader 中读取 7 位编码的整数。
  53. /// </summary>
  54. /// <param name="reader">字节序列读取器</param>
  55. /// <param name="value">解码后的整数值</param>
  56. /// <returns>解码是否成功。返回 true 表示成功,false 表示数据格式无效(溢出),null 表示数据不足。</returns>
  57. public static bool? TryRead7BitEncodedInt(this ref SequenceReader<byte> reader, out int value)
  58. {
  59. value = 0;
  60. var bitsRead = 0;
  61. while (true)
  62. {
  63. if (!reader.TryRead(out byte currentByte))
  64. {
  65. // 数据不足
  66. return null;
  67. }
  68. // 将当前字节的低 7 位加到结果中
  69. value |= (currentByte & 0x7F) << bitsRead;
  70. bitsRead += 7;
  71. // 如果最高位是 0,则结束读取
  72. if ((currentByte & 0x80) == 0)
  73. {
  74. return true;
  75. }
  76. // 防止过大的整数导致溢出
  77. if (bitsRead >= 35)
  78. {
  79. // 数据格式无效,表示溢出
  80. value = 0;
  81. return false;
  82. }
  83. }
  84. }
  85. }