123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- using XGame.Framework.Network.Protobuf;
- using System.Collections.Generic;
- namespace XGame.Framework.Network
- {
- public static class ProtobufUtils
- {
- /// <summary>
- /// 为了优化性能,返回的字节流头部预留10个字节给外部使用,外部可以把头部信息写入到这10个预留的位置中
- /// 实际是8个字节用于头部,2个字节在body存body长度,因此与proto无关的字节数为前10字节
- /// </summary>
- private const int HeadOffset = 10;
- public static readonly CodedOutputStream CodedOutput = new CodedOutputStream();
- public static readonly CodedInputStream CodedInput = new CodedInputStream();
- public static BytesWrapper CreateBytesWrapper(IMsgParser parsor)
- {
- CodedOutput.Buffer = SessionBufferPool.Acquire();
- CodedOutput.Reset(HeadOffset);
- parsor.WriteTo(CodedOutput);
- return BytesWrapperPool.Acquire(CodedOutput.Buffer, HeadOffset, (int)CodedOutput.Position - HeadOffset);
- }
- public static void ParseFrom(byte[] bytes, int offset, int size, IMsgParser parser)
- {
- CodedInput.Reset(bytes, offset, size);
- parser.MergeFrom(CodedInput);
- CodedInput.CheckReadEndOfStreamTag();
- }
- public static void WriteTo<T>(CodedOutputStream output, FieldCodec<T> codec, List<T> ls)
- {
- if (ls == null || ls.Count == 0)
- return;
- var writer = codec.ValueWriter;
- var tag = codec.Tag;
- if (codec.PackedRepeatedField)
- {
- uint size = (uint)CalculatePackedDataSize(codec, ls);
- output.WriteTag(tag);
- output.WriteRawVarint32(size);
- for (int i = 0, count = ls.Count; i < count; i++)
- {
- writer(output, ls[i]);
- }
- }
- else
- {
- for (int i = 0, count = ls.Count; i < count; i++)
- {
- output.WriteTag(tag);
- writer(output, ls[i]);
- }
- }
- }
- private static int CalculatePackedDataSize<T>(FieldCodec<T> codec, List<T> ls)
- {
- int fixedSize = codec.FixedSize;
- if (fixedSize == 0)
- {
- var calculator = codec.ValueSizeCalculator;
- int tmp = 0;
- for (int i = 0, count = ls.Count; i < count; i++)
- {
- tmp += calculator(ls[i]);
- }
- return tmp;
- }
- else
- {
- return fixedSize * ls.Count;
- }
- }
- public static void AddEntriesFrom<T>(CodedInputStream input, FieldCodec<T> codec,
- List<T> ls)
- {
- uint tag = input.LastTag;
- var reader = codec.ValueReader;
- if (FieldCodec<T>.IsPackedRepeatedField(tag))
- {
- int length = input.ReadLength();
- if (length > 0)
- {
- int oldLimit = input.PushLimit(length);
- while (!input.ReachedLimit)
- {
- ls.Add(reader(input));
- }
- input.PopLimit(oldLimit);
- }
- }
- else
- {
- do
- {
- ls.Add(reader(input));
- } while (input.MaybeConsumeTag(tag));
- }
- }
- public static int CalculateSize<T>(FieldCodec<T> codec, List<T> ls)
- {
- if (ls == null)
- {
- return 0;
- }
- int count = ls.Count;
- if (ls.Count == 0)
- {
- return 0;
- }
- uint tag = codec.Tag;
- if (codec.PackedRepeatedField)
- {
- int dataSize = CalculatePackedDataSize(codec, ls);
- return CodedOutputStream.ComputeRawVarint32Size(tag) +
- CodedOutputStream.ComputeLengthSize(dataSize) +
- dataSize;
- }
- else
- {
- var sizeCalculator = codec.ValueSizeCalculator;
- int size = count * CodedOutputStream.ComputeRawVarint32Size(tag);
- for (int i = 0; i < count; i++)
- {
- size += sizeCalculator(ls[i]);
- }
- return size;
- }
- }
- public static void AddEntriesFrom<TKey, TValue>(CodedInputStream input, MapFieldCodec<TKey, TValue> codec, Dictionary<TKey, TValue> map)
- {
- var adapter = new MapFieldCodec<TKey, TValue>.MessageAdapter(codec);
- do
- {
- adapter.Reset();
- input.ReadMessage(adapter);
- map.Add(adapter.Key, adapter.Value);
- } while (input.MaybeConsumeTag(codec.MapTag));
- }
- public static void WriteTo<TKey, TValue>(CodedOutputStream output, MapFieldCodec<TKey, TValue> codec, Dictionary<TKey, TValue> map)
- {
- var message = new MapFieldCodec<TKey, TValue>.MessageAdapter(codec);
- foreach (var entry in map)
- {
- message.Key = entry.Key;
- message.Value = entry.Value;
- output.WriteTag(codec.MapTag);
- output.WriteMessage(message);
- }
- }
- public static int CalculateSize<TKey, TValue>(MapFieldCodec<TKey, TValue> codec, Dictionary<TKey, TValue> map)
- {
- var message = new MapFieldCodec<TKey, TValue>.MessageAdapter(codec);
- int size = 0;
- foreach (var entry in map)
- {
- message.Key = entry.Key;
- message.Value = entry.Value;
- size += CodedOutputStream.ComputeRawVarint32Size(codec.MapTag);
- size += CodedOutputStream.ComputeMessageSize(message);
- }
- return size;
- }
- }
- }
|