Created
April 3, 2018 21:36
-
-
Save xinmyname/4a2a033d9211ddb32bccefca7cf3d802 to your computer and use it in GitHub Desktop.
C# Stream Extensions for reading/writing protocol buffers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IO; | |
using Google.Protobuf; | |
namespace ProtoCore | |
{ | |
public static class StreamExtensions | |
{ | |
public static void Write(this Stream stream, IMessage message) | |
{ | |
byte[] messageData = message.ToByteArray(); | |
stream.WriteLength(messageData.Length); | |
stream.Write(messageData, 0, messageData.Length); | |
} | |
public static T Read<T>(this Stream stream) where T : IMessage<T>, new() | |
{ | |
int length = stream.ReadLength(); | |
var messageData = new byte[length]; | |
stream.Read(messageData, 0, length); | |
var parser = new MessageParser<T>(() => new T()); | |
return parser.ParseFrom(messageData, 0, length); | |
} | |
private static void WriteLength(this Stream stream, int length) | |
{ | |
if (length < 64) | |
stream.WriteByte((byte)length); | |
else if (length < 16384) | |
{ | |
var encodedLength = (ushort)(((length & 0xFF) << 8) | (length >> 8) | 0x40); | |
stream.Write(BitConverter.GetBytes(encodedLength), 0, sizeof(ushort)); | |
} | |
else if (length < 1_073_741_824) | |
{ | |
long longLen = length; | |
var encodedLength = (ulong) ( | |
((longLen & 0xFF) << 24) | | |
((longLen & 0xFF00) << 8) | | |
((longLen & 0xFF0000) >> 8) | | |
((longLen & 0xFF000000) >> 24) | 0x80); | |
stream.Write(BitConverter.GetBytes(encodedLength), 0, sizeof(ulong)); | |
} | |
else | |
throw new ArgumentException($"Length ({length}) is too long to be represented in byte stream.", nameof(length)); | |
} | |
private static int ReadLength(this Stream stream) | |
{ | |
int hiByte = stream.ReadByte(); | |
if ((hiByte & 0x80) != 0) | |
{ | |
var lenData = new byte[4]; | |
lenData[3] = (byte) (hiByte & 0x3F); | |
lenData[2] = (byte) stream.ReadByte(); | |
lenData[1] = (byte) stream.ReadByte(); | |
lenData[0] = (byte) stream.ReadByte(); | |
int len = BitConverter.ToInt32(lenData, 0); | |
return len; | |
} | |
if ((hiByte & 0x40) != 0) | |
{ | |
var lenData = new byte[2]; | |
lenData[1] = (byte) (hiByte & 0x3F); | |
lenData[0] = (byte)stream.ReadByte(); | |
int len = BitConverter.ToInt16(lenData, 0); | |
return len; | |
} | |
return hiByte; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment