initial commit
This commit is contained in:
@@ -0,0 +1,627 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
public static class BclHelpers
|
||||
{
|
||||
[Flags]
|
||||
public enum NetObjectOptions : byte
|
||||
{
|
||||
None = 0,
|
||||
AsReference = 1,
|
||||
DynamicType = 2,
|
||||
UseConstructor = 4,
|
||||
LateSet = 8
|
||||
}
|
||||
|
||||
private const int FieldTimeSpanValue = 1;
|
||||
|
||||
private const int FieldTimeSpanScale = 2;
|
||||
|
||||
private const int FieldTimeSpanKind = 3;
|
||||
|
||||
internal static readonly DateTime[] EpochOrigin = new DateTime[3]
|
||||
{
|
||||
new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
|
||||
new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc),
|
||||
new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Local)
|
||||
};
|
||||
|
||||
private static readonly DateTime TimestampEpoch = EpochOrigin[1];
|
||||
|
||||
private const int FieldDecimalLow = 1;
|
||||
|
||||
private const int FieldDecimalHigh = 2;
|
||||
|
||||
private const int FieldDecimalSignScale = 3;
|
||||
|
||||
private const int FieldGuidLow = 1;
|
||||
|
||||
private const int FieldGuidHigh = 2;
|
||||
|
||||
private const int FieldExistingObjectKey = 1;
|
||||
|
||||
private const int FieldNewObjectKey = 2;
|
||||
|
||||
private const int FieldExistingTypeKey = 3;
|
||||
|
||||
private const int FieldNewTypeKey = 4;
|
||||
|
||||
private const int FieldTypeName = 8;
|
||||
|
||||
private const int FieldObject = 10;
|
||||
|
||||
public static object GetUninitializedObject(Type type)
|
||||
{
|
||||
return FormatterServices.GetUninitializedObject(type);
|
||||
}
|
||||
|
||||
public static void WriteTimeSpan(TimeSpan timeSpan, ProtoWriter dest)
|
||||
{
|
||||
WriteTimeSpanImpl(timeSpan, dest, DateTimeKind.Unspecified);
|
||||
}
|
||||
|
||||
private static void WriteTimeSpanImpl(TimeSpan timeSpan, ProtoWriter dest, DateTimeKind kind)
|
||||
{
|
||||
if (dest == null)
|
||||
{
|
||||
throw new ArgumentNullException("dest");
|
||||
}
|
||||
switch (dest.WireType)
|
||||
{
|
||||
case WireType.String:
|
||||
case WireType.StartGroup:
|
||||
{
|
||||
long num = timeSpan.Ticks;
|
||||
TimeSpanScale timeSpanScale;
|
||||
if (timeSpan == TimeSpan.MaxValue)
|
||||
{
|
||||
num = 1L;
|
||||
timeSpanScale = TimeSpanScale.MinMax;
|
||||
}
|
||||
else if (timeSpan == TimeSpan.MinValue)
|
||||
{
|
||||
num = -1L;
|
||||
timeSpanScale = TimeSpanScale.MinMax;
|
||||
}
|
||||
else if (num % 864000000000L == 0L)
|
||||
{
|
||||
timeSpanScale = TimeSpanScale.Days;
|
||||
num /= 864000000000L;
|
||||
}
|
||||
else if (num % 36000000000L == 0L)
|
||||
{
|
||||
timeSpanScale = TimeSpanScale.Hours;
|
||||
num /= 36000000000L;
|
||||
}
|
||||
else if (num % 600000000 == 0L)
|
||||
{
|
||||
timeSpanScale = TimeSpanScale.Minutes;
|
||||
num /= 600000000;
|
||||
}
|
||||
else if (num % 10000000 == 0L)
|
||||
{
|
||||
timeSpanScale = TimeSpanScale.Seconds;
|
||||
num /= 10000000;
|
||||
}
|
||||
else if (num % 10000 == 0L)
|
||||
{
|
||||
timeSpanScale = TimeSpanScale.Milliseconds;
|
||||
num /= 10000;
|
||||
}
|
||||
else
|
||||
{
|
||||
timeSpanScale = TimeSpanScale.Ticks;
|
||||
}
|
||||
SubItemToken token = ProtoWriter.StartSubItem(null, dest);
|
||||
if (num != 0L)
|
||||
{
|
||||
ProtoWriter.WriteFieldHeader(1, WireType.SignedVariant, dest);
|
||||
ProtoWriter.WriteInt64(num, dest);
|
||||
}
|
||||
if (timeSpanScale != TimeSpanScale.Days)
|
||||
{
|
||||
ProtoWriter.WriteFieldHeader(2, WireType.Variant, dest);
|
||||
ProtoWriter.WriteInt32((int)timeSpanScale, dest);
|
||||
}
|
||||
if (kind != DateTimeKind.Unspecified)
|
||||
{
|
||||
ProtoWriter.WriteFieldHeader(3, WireType.Variant, dest);
|
||||
ProtoWriter.WriteInt32((int)kind, dest);
|
||||
}
|
||||
ProtoWriter.EndSubItem(token, dest);
|
||||
break;
|
||||
}
|
||||
case WireType.Fixed64:
|
||||
ProtoWriter.WriteInt64(timeSpan.Ticks, dest);
|
||||
break;
|
||||
default:
|
||||
throw new ProtoException("Unexpected wire-type: " + dest.WireType);
|
||||
}
|
||||
}
|
||||
|
||||
public static TimeSpan ReadTimeSpan(ProtoReader source)
|
||||
{
|
||||
DateTimeKind kind;
|
||||
long num = ReadTimeSpanTicks(source, out kind);
|
||||
return num switch
|
||||
{
|
||||
long.MinValue => TimeSpan.MinValue,
|
||||
long.MaxValue => TimeSpan.MaxValue,
|
||||
_ => TimeSpan.FromTicks(num),
|
||||
};
|
||||
}
|
||||
|
||||
public static TimeSpan ReadDuration(ProtoReader source)
|
||||
{
|
||||
long seconds = 0L;
|
||||
int nanos = 0;
|
||||
SubItemToken token = ProtoReader.StartSubItem(source);
|
||||
int num;
|
||||
while ((num = source.ReadFieldHeader()) > 0)
|
||||
{
|
||||
switch (num)
|
||||
{
|
||||
case 1:
|
||||
seconds = source.ReadInt64();
|
||||
break;
|
||||
case 2:
|
||||
nanos = source.ReadInt32();
|
||||
break;
|
||||
default:
|
||||
source.SkipField();
|
||||
break;
|
||||
}
|
||||
}
|
||||
ProtoReader.EndSubItem(token, source);
|
||||
return FromDurationSeconds(seconds, nanos);
|
||||
}
|
||||
|
||||
public static void WriteDuration(TimeSpan value, ProtoWriter dest)
|
||||
{
|
||||
int nanos;
|
||||
long seconds = ToDurationSeconds(value, out nanos);
|
||||
WriteSecondsNanos(seconds, nanos, dest);
|
||||
}
|
||||
|
||||
private static void WriteSecondsNanos(long seconds, int nanos, ProtoWriter dest)
|
||||
{
|
||||
SubItemToken token = ProtoWriter.StartSubItem(null, dest);
|
||||
if (seconds != 0L)
|
||||
{
|
||||
ProtoWriter.WriteFieldHeader(1, WireType.Variant, dest);
|
||||
ProtoWriter.WriteInt64(seconds, dest);
|
||||
}
|
||||
if (nanos != 0)
|
||||
{
|
||||
ProtoWriter.WriteFieldHeader(2, WireType.Variant, dest);
|
||||
ProtoWriter.WriteInt32(nanos, dest);
|
||||
}
|
||||
ProtoWriter.EndSubItem(token, dest);
|
||||
}
|
||||
|
||||
public static DateTime ReadTimestamp(ProtoReader source)
|
||||
{
|
||||
return TimestampEpoch + ReadDuration(source);
|
||||
}
|
||||
|
||||
public static void WriteTimestamp(DateTime value, ProtoWriter dest)
|
||||
{
|
||||
int nanos;
|
||||
long num = ToDurationSeconds(value - TimestampEpoch, out nanos);
|
||||
if (nanos < 0)
|
||||
{
|
||||
num--;
|
||||
nanos += 1000000000;
|
||||
}
|
||||
WriteSecondsNanos(num, nanos, dest);
|
||||
}
|
||||
|
||||
private static TimeSpan FromDurationSeconds(long seconds, int nanos)
|
||||
{
|
||||
checked
|
||||
{
|
||||
long value = seconds * 10000000 + unchecked(checked(unchecked((long)nanos) * 10000L) / 1000000);
|
||||
return TimeSpan.FromTicks(value);
|
||||
}
|
||||
}
|
||||
|
||||
private static long ToDurationSeconds(TimeSpan value, out int nanos)
|
||||
{
|
||||
nanos = (int)(value.Ticks % 10000000 * 1000000 / 10000);
|
||||
return value.Ticks / 10000000;
|
||||
}
|
||||
|
||||
public static DateTime ReadDateTime(ProtoReader source)
|
||||
{
|
||||
DateTimeKind kind;
|
||||
long num = ReadTimeSpanTicks(source, out kind);
|
||||
return num switch
|
||||
{
|
||||
long.MinValue => DateTime.MinValue,
|
||||
long.MaxValue => DateTime.MaxValue,
|
||||
_ => EpochOrigin[(int)kind].AddTicks(num),
|
||||
};
|
||||
}
|
||||
|
||||
public static void WriteDateTime(DateTime value, ProtoWriter dest)
|
||||
{
|
||||
WriteDateTimeImpl(value, dest, includeKind: false);
|
||||
}
|
||||
|
||||
public static void WriteDateTimeWithKind(DateTime value, ProtoWriter dest)
|
||||
{
|
||||
WriteDateTimeImpl(value, dest, includeKind: true);
|
||||
}
|
||||
|
||||
private static void WriteDateTimeImpl(DateTime value, ProtoWriter dest, bool includeKind)
|
||||
{
|
||||
if (dest == null)
|
||||
{
|
||||
throw new ArgumentNullException("dest");
|
||||
}
|
||||
WireType wireType = dest.WireType;
|
||||
TimeSpan timeSpan;
|
||||
if ((uint)(wireType - 2) <= 1u)
|
||||
{
|
||||
if (value == DateTime.MaxValue)
|
||||
{
|
||||
timeSpan = TimeSpan.MaxValue;
|
||||
includeKind = false;
|
||||
}
|
||||
else if (value == DateTime.MinValue)
|
||||
{
|
||||
timeSpan = TimeSpan.MinValue;
|
||||
includeKind = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
timeSpan = value - EpochOrigin[0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
timeSpan = value - EpochOrigin[0];
|
||||
}
|
||||
WriteTimeSpanImpl(timeSpan, dest, includeKind ? value.Kind : DateTimeKind.Unspecified);
|
||||
}
|
||||
|
||||
private static long ReadTimeSpanTicks(ProtoReader source, out DateTimeKind kind)
|
||||
{
|
||||
kind = DateTimeKind.Unspecified;
|
||||
switch (source.WireType)
|
||||
{
|
||||
case WireType.String:
|
||||
case WireType.StartGroup:
|
||||
{
|
||||
SubItemToken token = ProtoReader.StartSubItem(source);
|
||||
TimeSpanScale timeSpanScale = TimeSpanScale.Days;
|
||||
long num = 0L;
|
||||
int num2;
|
||||
while ((num2 = source.ReadFieldHeader()) > 0)
|
||||
{
|
||||
switch (num2)
|
||||
{
|
||||
case 2:
|
||||
timeSpanScale = (TimeSpanScale)source.ReadInt32();
|
||||
break;
|
||||
case 1:
|
||||
source.Assert(WireType.SignedVariant);
|
||||
num = source.ReadInt64();
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
kind = (DateTimeKind)source.ReadInt32();
|
||||
DateTimeKind dateTimeKind = kind;
|
||||
if ((uint)dateTimeKind > 2u)
|
||||
{
|
||||
throw new ProtoException("Invalid date/time kind: " + kind);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
source.SkipField();
|
||||
break;
|
||||
}
|
||||
}
|
||||
ProtoReader.EndSubItem(token, source);
|
||||
return timeSpanScale switch
|
||||
{
|
||||
TimeSpanScale.Days => num * 864000000000L,
|
||||
TimeSpanScale.Hours => num * 36000000000L,
|
||||
TimeSpanScale.Minutes => num * 600000000,
|
||||
TimeSpanScale.Seconds => num * 10000000,
|
||||
TimeSpanScale.Milliseconds => num * 10000,
|
||||
TimeSpanScale.Ticks => num,
|
||||
TimeSpanScale.MinMax => num switch
|
||||
{
|
||||
1L => long.MaxValue,
|
||||
-1L => long.MinValue,
|
||||
_ => throw new ProtoException("Unknown min/max value: " + num),
|
||||
},
|
||||
_ => throw new ProtoException("Unknown timescale: " + timeSpanScale),
|
||||
};
|
||||
}
|
||||
case WireType.Fixed64:
|
||||
return source.ReadInt64();
|
||||
default:
|
||||
throw new ProtoException("Unexpected wire-type: " + source.WireType);
|
||||
}
|
||||
}
|
||||
|
||||
public static decimal ReadDecimal(ProtoReader reader)
|
||||
{
|
||||
ulong num = 0uL;
|
||||
uint num2 = 0u;
|
||||
uint num3 = 0u;
|
||||
SubItemToken token = ProtoReader.StartSubItem(reader);
|
||||
int num4;
|
||||
while ((num4 = reader.ReadFieldHeader()) > 0)
|
||||
{
|
||||
switch (num4)
|
||||
{
|
||||
case 1:
|
||||
num = reader.ReadUInt64();
|
||||
break;
|
||||
case 2:
|
||||
num2 = reader.ReadUInt32();
|
||||
break;
|
||||
case 3:
|
||||
num3 = reader.ReadUInt32();
|
||||
break;
|
||||
default:
|
||||
reader.SkipField();
|
||||
break;
|
||||
}
|
||||
}
|
||||
ProtoReader.EndSubItem(token, reader);
|
||||
int lo = (int)(num & 0xFFFFFFFFu);
|
||||
int mid = (int)((num >> 32) & 0xFFFFFFFFu);
|
||||
int hi = (int)num2;
|
||||
bool isNegative = (num3 & 1) == 1;
|
||||
byte scale = (byte)((num3 & 0x1FE) >> 1);
|
||||
return new decimal(lo, mid, hi, isNegative, scale);
|
||||
}
|
||||
|
||||
public static void WriteDecimal(decimal value, ProtoWriter writer)
|
||||
{
|
||||
int[] bits = decimal.GetBits(value);
|
||||
ulong num = (ulong)((long)bits[1] << 32);
|
||||
ulong num2 = (ulong)(bits[0] & 0xFFFFFFFFu);
|
||||
ulong num3 = num | num2;
|
||||
uint num4 = (uint)bits[2];
|
||||
uint num5 = (uint)(((bits[3] >> 15) & 0x1FE) | ((bits[3] >> 31) & 1));
|
||||
SubItemToken token = ProtoWriter.StartSubItem(null, writer);
|
||||
if (num3 != 0L)
|
||||
{
|
||||
ProtoWriter.WriteFieldHeader(1, WireType.Variant, writer);
|
||||
ProtoWriter.WriteUInt64(num3, writer);
|
||||
}
|
||||
if (num4 != 0)
|
||||
{
|
||||
ProtoWriter.WriteFieldHeader(2, WireType.Variant, writer);
|
||||
ProtoWriter.WriteUInt32(num4, writer);
|
||||
}
|
||||
if (num5 != 0)
|
||||
{
|
||||
ProtoWriter.WriteFieldHeader(3, WireType.Variant, writer);
|
||||
ProtoWriter.WriteUInt32(num5, writer);
|
||||
}
|
||||
ProtoWriter.EndSubItem(token, writer);
|
||||
}
|
||||
|
||||
public static void WriteGuid(Guid value, ProtoWriter dest)
|
||||
{
|
||||
byte[] data = value.ToByteArray();
|
||||
SubItemToken token = ProtoWriter.StartSubItem(null, dest);
|
||||
if (value != Guid.Empty)
|
||||
{
|
||||
ProtoWriter.WriteFieldHeader(1, WireType.Fixed64, dest);
|
||||
ProtoWriter.WriteBytes(data, 0, 8, dest);
|
||||
ProtoWriter.WriteFieldHeader(2, WireType.Fixed64, dest);
|
||||
ProtoWriter.WriteBytes(data, 8, 8, dest);
|
||||
}
|
||||
ProtoWriter.EndSubItem(token, dest);
|
||||
}
|
||||
|
||||
public static Guid ReadGuid(ProtoReader source)
|
||||
{
|
||||
ulong num = 0uL;
|
||||
ulong num2 = 0uL;
|
||||
SubItemToken token = ProtoReader.StartSubItem(source);
|
||||
int num3;
|
||||
while ((num3 = source.ReadFieldHeader()) > 0)
|
||||
{
|
||||
switch (num3)
|
||||
{
|
||||
case 1:
|
||||
num = source.ReadUInt64();
|
||||
break;
|
||||
case 2:
|
||||
num2 = source.ReadUInt64();
|
||||
break;
|
||||
default:
|
||||
source.SkipField();
|
||||
break;
|
||||
}
|
||||
}
|
||||
ProtoReader.EndSubItem(token, source);
|
||||
if (num == 0L && num2 == 0L)
|
||||
{
|
||||
return Guid.Empty;
|
||||
}
|
||||
uint num4 = (uint)(num >> 32);
|
||||
uint a = (uint)num;
|
||||
uint num5 = (uint)(num2 >> 32);
|
||||
uint num6 = (uint)num2;
|
||||
return new Guid((int)a, (short)num4, (short)(num4 >> 16), (byte)num6, (byte)(num6 >> 8), (byte)(num6 >> 16), (byte)(num6 >> 24), (byte)num5, (byte)(num5 >> 8), (byte)(num5 >> 16), (byte)(num5 >> 24));
|
||||
}
|
||||
|
||||
public static object ReadNetObject(object value, ProtoReader source, int key, Type type, NetObjectOptions options)
|
||||
{
|
||||
SubItemToken token = ProtoReader.StartSubItem(source);
|
||||
int num = -1;
|
||||
int num2 = -1;
|
||||
int num3;
|
||||
while ((num3 = source.ReadFieldHeader()) > 0)
|
||||
{
|
||||
switch (num3)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
int key2 = source.ReadInt32();
|
||||
value = source.NetCache.GetKeyedObject(key2);
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
num = source.ReadInt32();
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
int key2 = source.ReadInt32();
|
||||
type = (Type)source.NetCache.GetKeyedObject(key2);
|
||||
key = source.GetTypeKey(ref type);
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
num2 = source.ReadInt32();
|
||||
break;
|
||||
case 8:
|
||||
{
|
||||
string text = source.ReadString();
|
||||
type = source.DeserializeType(text);
|
||||
if ((object)type == null)
|
||||
{
|
||||
throw new ProtoException("Unable to resolve type: " + text + " (you can use the TypeModel.DynamicTypeFormatting event to provide a custom mapping)");
|
||||
}
|
||||
if ((object)type == typeof(string))
|
||||
{
|
||||
key = -1;
|
||||
break;
|
||||
}
|
||||
key = source.GetTypeKey(ref type);
|
||||
if (key >= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
throw new InvalidOperationException("Dynamic type is not a contract-type: " + type.Name);
|
||||
}
|
||||
case 10:
|
||||
{
|
||||
bool flag = (object)type == typeof(string);
|
||||
bool flag2 = value == null;
|
||||
bool flag3 = flag2 && (flag || (options & NetObjectOptions.LateSet) != 0);
|
||||
if (num >= 0 && !flag3)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
source.TrapNextObject(num);
|
||||
}
|
||||
else
|
||||
{
|
||||
source.NetCache.SetKeyedObject(num, value);
|
||||
}
|
||||
if (num2 >= 0)
|
||||
{
|
||||
source.NetCache.SetKeyedObject(num2, type);
|
||||
}
|
||||
}
|
||||
object obj = value;
|
||||
value = ((!flag) ? ProtoReader.ReadTypedObject(obj, key, source, type) : source.ReadString());
|
||||
if (num >= 0)
|
||||
{
|
||||
if (flag2 && !flag3)
|
||||
{
|
||||
obj = source.NetCache.GetKeyedObject(num);
|
||||
}
|
||||
if (flag3)
|
||||
{
|
||||
source.NetCache.SetKeyedObject(num, value);
|
||||
if (num2 >= 0)
|
||||
{
|
||||
source.NetCache.SetKeyedObject(num2, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (num >= 0 && !flag3 && obj != value)
|
||||
{
|
||||
throw new ProtoException("A reference-tracked object changed reference during deserialization");
|
||||
}
|
||||
if (num < 0 && num2 >= 0)
|
||||
{
|
||||
source.NetCache.SetKeyedObject(num2, type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
source.SkipField();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (num >= 0 && (options & NetObjectOptions.AsReference) == 0)
|
||||
{
|
||||
throw new ProtoException("Object key in input stream, but reference-tracking was not expected");
|
||||
}
|
||||
ProtoReader.EndSubItem(token, source);
|
||||
return value;
|
||||
}
|
||||
|
||||
public static void WriteNetObject(object value, ProtoWriter dest, int key, NetObjectOptions options)
|
||||
{
|
||||
if (dest == null)
|
||||
{
|
||||
throw new ArgumentNullException("dest");
|
||||
}
|
||||
bool flag = (options & NetObjectOptions.DynamicType) != 0;
|
||||
bool flag2 = (options & NetObjectOptions.AsReference) != 0;
|
||||
WireType wireType = dest.WireType;
|
||||
SubItemToken token = ProtoWriter.StartSubItem(null, dest);
|
||||
bool flag3 = true;
|
||||
if (flag2)
|
||||
{
|
||||
bool existing;
|
||||
int value2 = dest.NetCache.AddObjectKey(value, out existing);
|
||||
ProtoWriter.WriteFieldHeader(existing ? 1 : 2, WireType.Variant, dest);
|
||||
ProtoWriter.WriteInt32(value2, dest);
|
||||
if (existing)
|
||||
{
|
||||
flag3 = false;
|
||||
}
|
||||
}
|
||||
if (flag3)
|
||||
{
|
||||
if (flag)
|
||||
{
|
||||
Type type = value.GetType();
|
||||
if (!(value is string))
|
||||
{
|
||||
key = dest.GetTypeKey(ref type);
|
||||
if (key < 0)
|
||||
{
|
||||
throw new InvalidOperationException("Dynamic type is not a contract-type: " + type.Name);
|
||||
}
|
||||
}
|
||||
bool existing2;
|
||||
int value3 = dest.NetCache.AddObjectKey(type, out existing2);
|
||||
ProtoWriter.WriteFieldHeader(existing2 ? 3 : 4, WireType.Variant, dest);
|
||||
ProtoWriter.WriteInt32(value3, dest);
|
||||
if (!existing2)
|
||||
{
|
||||
ProtoWriter.WriteFieldHeader(8, WireType.String, dest);
|
||||
ProtoWriter.WriteString(dest.SerializeType(type), dest);
|
||||
}
|
||||
}
|
||||
ProtoWriter.WriteFieldHeader(10, wireType, dest);
|
||||
if (value is string)
|
||||
{
|
||||
ProtoWriter.WriteString((string)value, dest);
|
||||
}
|
||||
else
|
||||
{
|
||||
ProtoWriter.WriteObject(value, key, dest);
|
||||
}
|
||||
}
|
||||
ProtoWriter.EndSubItem(token, dest);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
public sealed class BufferExtension : IExtension, IExtensionResettable
|
||||
{
|
||||
private byte[] buffer;
|
||||
|
||||
void IExtensionResettable.Reset()
|
||||
{
|
||||
buffer = null;
|
||||
}
|
||||
|
||||
int IExtension.GetLength()
|
||||
{
|
||||
if (buffer != null)
|
||||
{
|
||||
return buffer.Length;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Stream IExtension.BeginAppend()
|
||||
{
|
||||
return new MemoryStream();
|
||||
}
|
||||
|
||||
void IExtension.EndAppend(Stream stream, bool commit)
|
||||
{
|
||||
using (stream)
|
||||
{
|
||||
int num;
|
||||
if (commit && (num = (int)stream.Length) > 0)
|
||||
{
|
||||
MemoryStream memoryStream = (MemoryStream)stream;
|
||||
if (buffer == null)
|
||||
{
|
||||
buffer = memoryStream.ToArray();
|
||||
return;
|
||||
}
|
||||
int num2 = buffer.Length;
|
||||
byte[] dst = new byte[num2 + num];
|
||||
Buffer.BlockCopy(buffer, 0, dst, 0, num2);
|
||||
Buffer.BlockCopy(Helpers.GetBuffer(memoryStream), 0, dst, num2, num);
|
||||
buffer = dst;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Stream IExtension.BeginQuery()
|
||||
{
|
||||
if (buffer != null)
|
||||
{
|
||||
return new MemoryStream(buffer);
|
||||
}
|
||||
return Stream.Null;
|
||||
}
|
||||
|
||||
void IExtension.EndQuery(Stream stream)
|
||||
{
|
||||
using (stream)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
using System;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
internal sealed class BufferPool
|
||||
{
|
||||
private class CachedBuffer
|
||||
{
|
||||
private readonly WeakReference _reference;
|
||||
|
||||
public int Size { get; }
|
||||
|
||||
public bool IsAlive => _reference.IsAlive;
|
||||
|
||||
public byte[] Buffer => (byte[])_reference.Target;
|
||||
|
||||
public CachedBuffer(byte[] buffer)
|
||||
{
|
||||
Size = buffer.Length;
|
||||
_reference = new WeakReference(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
private const int POOL_SIZE = 20;
|
||||
|
||||
internal const int BUFFER_LENGTH = 1024;
|
||||
|
||||
private static readonly CachedBuffer[] Pool = new CachedBuffer[20];
|
||||
|
||||
private const int MaxByteArraySize = 2147483591;
|
||||
|
||||
internal static void Flush()
|
||||
{
|
||||
lock (Pool)
|
||||
{
|
||||
for (int i = 0; i < Pool.Length; i++)
|
||||
{
|
||||
Pool[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private BufferPool()
|
||||
{
|
||||
}
|
||||
|
||||
internal static byte[] GetBuffer()
|
||||
{
|
||||
return GetBuffer(1024);
|
||||
}
|
||||
|
||||
internal static byte[] GetBuffer(int minSize)
|
||||
{
|
||||
byte[] cachedBuffer = GetCachedBuffer(minSize);
|
||||
return cachedBuffer ?? new byte[minSize];
|
||||
}
|
||||
|
||||
internal static byte[] GetCachedBuffer(int minSize)
|
||||
{
|
||||
lock (Pool)
|
||||
{
|
||||
int num = -1;
|
||||
byte[] array = null;
|
||||
for (int i = 0; i < Pool.Length; i++)
|
||||
{
|
||||
CachedBuffer cachedBuffer = Pool[i];
|
||||
if (cachedBuffer != null && cachedBuffer.Size >= minSize && (array == null || array.Length >= cachedBuffer.Size))
|
||||
{
|
||||
byte[] buffer = cachedBuffer.Buffer;
|
||||
if (buffer == null)
|
||||
{
|
||||
Pool[i] = null;
|
||||
continue;
|
||||
}
|
||||
array = buffer;
|
||||
num = i;
|
||||
}
|
||||
}
|
||||
if (num >= 0)
|
||||
{
|
||||
Pool[num] = null;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void ResizeAndFlushLeft(ref byte[] buffer, int toFitAtLeastBytes, int copyFromIndex, int copyBytes)
|
||||
{
|
||||
int num = buffer.Length * 2;
|
||||
if (num < 0)
|
||||
{
|
||||
num = 2147483591;
|
||||
}
|
||||
if (num < toFitAtLeastBytes)
|
||||
{
|
||||
num = toFitAtLeastBytes;
|
||||
}
|
||||
if (copyBytes == 0)
|
||||
{
|
||||
ReleaseBufferToPool(ref buffer);
|
||||
}
|
||||
byte[] array = GetCachedBuffer(toFitAtLeastBytes) ?? new byte[num];
|
||||
if (copyBytes > 0)
|
||||
{
|
||||
Buffer.BlockCopy(buffer, copyFromIndex, array, 0, copyBytes);
|
||||
ReleaseBufferToPool(ref buffer);
|
||||
}
|
||||
buffer = array;
|
||||
}
|
||||
|
||||
internal static void ReleaseBufferToPool(ref byte[] buffer)
|
||||
{
|
||||
if (buffer == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
lock (Pool)
|
||||
{
|
||||
int num = 0;
|
||||
int num2 = int.MaxValue;
|
||||
for (int i = 0; i < Pool.Length; i++)
|
||||
{
|
||||
CachedBuffer cachedBuffer = Pool[i];
|
||||
if (cachedBuffer == null || !cachedBuffer.IsAlive)
|
||||
{
|
||||
num = 0;
|
||||
break;
|
||||
}
|
||||
if (cachedBuffer.Size < num2)
|
||||
{
|
||||
num = i;
|
||||
num2 = cachedBuffer.Size;
|
||||
}
|
||||
}
|
||||
Pool[num] = new CachedBuffer(buffer);
|
||||
}
|
||||
buffer = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace ProtoBuf;
|
||||
|
||||
public enum DataFormat
|
||||
{
|
||||
Default,
|
||||
ZigZag,
|
||||
TwosComplement,
|
||||
FixedSize,
|
||||
Group,
|
||||
WellKnown
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
[Serializable]
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public readonly struct DiscriminatedUnion128 : ISerializable
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
private readonly int _discriminator;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly long Int64;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly ulong UInt64;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly int Int32;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly uint UInt32;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly bool Boolean;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly float Single;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly double Double;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly DateTime DateTime;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly TimeSpan TimeSpan;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly Guid Guid;
|
||||
|
||||
[FieldOffset(8)]
|
||||
private readonly long _lo;
|
||||
|
||||
[FieldOffset(16)]
|
||||
private readonly long _hi;
|
||||
|
||||
public int Discriminator => _discriminator;
|
||||
|
||||
unsafe static DiscriminatedUnion128()
|
||||
{
|
||||
if (sizeof(DateTime) > 16)
|
||||
{
|
||||
throw new InvalidOperationException("DateTime was unexpectedly too big for DiscriminatedUnion128");
|
||||
}
|
||||
if (sizeof(TimeSpan) > 16)
|
||||
{
|
||||
throw new InvalidOperationException("TimeSpan was unexpectedly too big for DiscriminatedUnion128");
|
||||
}
|
||||
if (sizeof(Guid) > 16)
|
||||
{
|
||||
throw new InvalidOperationException("Guid was unexpectedly too big for DiscriminatedUnion128");
|
||||
}
|
||||
}
|
||||
|
||||
private DiscriminatedUnion128(int discriminator)
|
||||
{
|
||||
this = default(DiscriminatedUnion128);
|
||||
_discriminator = discriminator;
|
||||
}
|
||||
|
||||
public bool Is(int discriminator)
|
||||
{
|
||||
return _discriminator == discriminator;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion128(int discriminator, long value)
|
||||
: this(discriminator)
|
||||
{
|
||||
Int64 = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion128(int discriminator, int value)
|
||||
: this(discriminator)
|
||||
{
|
||||
Int32 = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion128(int discriminator, ulong value)
|
||||
: this(discriminator)
|
||||
{
|
||||
UInt64 = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion128(int discriminator, uint value)
|
||||
: this(discriminator)
|
||||
{
|
||||
UInt32 = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion128(int discriminator, float value)
|
||||
: this(discriminator)
|
||||
{
|
||||
Single = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion128(int discriminator, double value)
|
||||
: this(discriminator)
|
||||
{
|
||||
Double = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion128(int discriminator, bool value)
|
||||
: this(discriminator)
|
||||
{
|
||||
Boolean = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion128(int discriminator, DateTime? value)
|
||||
: this(value.HasValue ? discriminator : 0)
|
||||
{
|
||||
DateTime = value.GetValueOrDefault();
|
||||
}
|
||||
|
||||
public DiscriminatedUnion128(int discriminator, TimeSpan? value)
|
||||
: this(value.HasValue ? discriminator : 0)
|
||||
{
|
||||
TimeSpan = value.GetValueOrDefault();
|
||||
}
|
||||
|
||||
public DiscriminatedUnion128(int discriminator, Guid? value)
|
||||
: this(value.HasValue ? discriminator : 0)
|
||||
{
|
||||
Guid = value.GetValueOrDefault();
|
||||
}
|
||||
|
||||
public static void Reset(ref DiscriminatedUnion128 value, int discriminator)
|
||||
{
|
||||
if (value.Discriminator == discriminator)
|
||||
{
|
||||
value = default(DiscriminatedUnion128);
|
||||
}
|
||||
}
|
||||
|
||||
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
if (_discriminator != 0)
|
||||
{
|
||||
info.AddValue("d", _discriminator);
|
||||
}
|
||||
if (_lo != 0L)
|
||||
{
|
||||
info.AddValue("l", _lo);
|
||||
}
|
||||
if (_hi != 0L)
|
||||
{
|
||||
info.AddValue("h", _hi);
|
||||
}
|
||||
}
|
||||
|
||||
private DiscriminatedUnion128(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
this = default(DiscriminatedUnion128);
|
||||
SerializationInfoEnumerator enumerator = info.GetEnumerator();
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
SerializationEntry current = enumerator.Current;
|
||||
switch (current.Name)
|
||||
{
|
||||
case "d":
|
||||
_discriminator = (int)current.Value;
|
||||
break;
|
||||
case "l":
|
||||
_lo = (long)current.Value;
|
||||
break;
|
||||
case "h":
|
||||
_hi = (long)current.Value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
[Serializable]
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public readonly struct DiscriminatedUnion128Object : ISerializable
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
private readonly int _discriminator;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly long Int64;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly ulong UInt64;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly int Int32;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly uint UInt32;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly bool Boolean;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly float Single;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly double Double;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly DateTime DateTime;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly TimeSpan TimeSpan;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly Guid Guid;
|
||||
|
||||
[FieldOffset(24)]
|
||||
public readonly object Object;
|
||||
|
||||
[FieldOffset(8)]
|
||||
private readonly long _lo;
|
||||
|
||||
[FieldOffset(16)]
|
||||
private readonly long _hi;
|
||||
|
||||
public int Discriminator => _discriminator;
|
||||
|
||||
unsafe static DiscriminatedUnion128Object()
|
||||
{
|
||||
if (sizeof(DateTime) > 16)
|
||||
{
|
||||
throw new InvalidOperationException("DateTime was unexpectedly too big for DiscriminatedUnion128Object");
|
||||
}
|
||||
if (sizeof(TimeSpan) > 16)
|
||||
{
|
||||
throw new InvalidOperationException("TimeSpan was unexpectedly too big for DiscriminatedUnion128Object");
|
||||
}
|
||||
if (sizeof(Guid) > 16)
|
||||
{
|
||||
throw new InvalidOperationException("Guid was unexpectedly too big for DiscriminatedUnion128Object");
|
||||
}
|
||||
}
|
||||
|
||||
private DiscriminatedUnion128Object(int discriminator)
|
||||
{
|
||||
this = default(DiscriminatedUnion128Object);
|
||||
_discriminator = discriminator;
|
||||
}
|
||||
|
||||
public bool Is(int discriminator)
|
||||
{
|
||||
return _discriminator == discriminator;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion128Object(int discriminator, long value)
|
||||
: this(discriminator)
|
||||
{
|
||||
Int64 = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion128Object(int discriminator, int value)
|
||||
: this(discriminator)
|
||||
{
|
||||
Int32 = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion128Object(int discriminator, ulong value)
|
||||
: this(discriminator)
|
||||
{
|
||||
UInt64 = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion128Object(int discriminator, uint value)
|
||||
: this(discriminator)
|
||||
{
|
||||
UInt32 = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion128Object(int discriminator, float value)
|
||||
: this(discriminator)
|
||||
{
|
||||
Single = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion128Object(int discriminator, double value)
|
||||
: this(discriminator)
|
||||
{
|
||||
Double = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion128Object(int discriminator, bool value)
|
||||
: this(discriminator)
|
||||
{
|
||||
Boolean = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion128Object(int discriminator, object value)
|
||||
: this((value != null) ? discriminator : 0)
|
||||
{
|
||||
Object = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion128Object(int discriminator, DateTime? value)
|
||||
: this(value.HasValue ? discriminator : 0)
|
||||
{
|
||||
DateTime = value.GetValueOrDefault();
|
||||
}
|
||||
|
||||
public DiscriminatedUnion128Object(int discriminator, TimeSpan? value)
|
||||
: this(value.HasValue ? discriminator : 0)
|
||||
{
|
||||
TimeSpan = value.GetValueOrDefault();
|
||||
}
|
||||
|
||||
public DiscriminatedUnion128Object(int discriminator, Guid? value)
|
||||
: this(value.HasValue ? discriminator : 0)
|
||||
{
|
||||
Guid = value.GetValueOrDefault();
|
||||
}
|
||||
|
||||
public static void Reset(ref DiscriminatedUnion128Object value, int discriminator)
|
||||
{
|
||||
if (value.Discriminator == discriminator)
|
||||
{
|
||||
value = default(DiscriminatedUnion128Object);
|
||||
}
|
||||
}
|
||||
|
||||
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
if (_discriminator != 0)
|
||||
{
|
||||
info.AddValue("d", _discriminator);
|
||||
}
|
||||
if (_lo != 0L)
|
||||
{
|
||||
info.AddValue("l", _lo);
|
||||
}
|
||||
if (_hi != 0L)
|
||||
{
|
||||
info.AddValue("h", _hi);
|
||||
}
|
||||
if (Object != null)
|
||||
{
|
||||
info.AddValue("o", Object);
|
||||
}
|
||||
}
|
||||
|
||||
private DiscriminatedUnion128Object(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
this = default(DiscriminatedUnion128Object);
|
||||
SerializationInfoEnumerator enumerator = info.GetEnumerator();
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
SerializationEntry current = enumerator.Current;
|
||||
switch (current.Name)
|
||||
{
|
||||
case "d":
|
||||
_discriminator = (int)current.Value;
|
||||
break;
|
||||
case "l":
|
||||
_lo = (long)current.Value;
|
||||
break;
|
||||
case "h":
|
||||
_hi = (long)current.Value;
|
||||
break;
|
||||
case "o":
|
||||
Object = current.Value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
[Serializable]
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public readonly struct DiscriminatedUnion32 : ISerializable
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
private readonly int _discriminator;
|
||||
|
||||
[FieldOffset(4)]
|
||||
public readonly int Int32;
|
||||
|
||||
[FieldOffset(4)]
|
||||
public readonly uint UInt32;
|
||||
|
||||
[FieldOffset(4)]
|
||||
public readonly bool Boolean;
|
||||
|
||||
[FieldOffset(4)]
|
||||
public readonly float Single;
|
||||
|
||||
public int Discriminator => _discriminator;
|
||||
|
||||
private DiscriminatedUnion32(int discriminator)
|
||||
{
|
||||
this = default(DiscriminatedUnion32);
|
||||
_discriminator = discriminator;
|
||||
}
|
||||
|
||||
public bool Is(int discriminator)
|
||||
{
|
||||
return _discriminator == discriminator;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion32(int discriminator, int value)
|
||||
: this(discriminator)
|
||||
{
|
||||
Int32 = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion32(int discriminator, uint value)
|
||||
: this(discriminator)
|
||||
{
|
||||
UInt32 = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion32(int discriminator, float value)
|
||||
: this(discriminator)
|
||||
{
|
||||
Single = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion32(int discriminator, bool value)
|
||||
: this(discriminator)
|
||||
{
|
||||
Boolean = value;
|
||||
}
|
||||
|
||||
public static void Reset(ref DiscriminatedUnion32 value, int discriminator)
|
||||
{
|
||||
if (value.Discriminator == discriminator)
|
||||
{
|
||||
value = default(DiscriminatedUnion32);
|
||||
}
|
||||
}
|
||||
|
||||
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
if (_discriminator != 0)
|
||||
{
|
||||
info.AddValue("d", _discriminator);
|
||||
}
|
||||
if (Int32 != 0)
|
||||
{
|
||||
info.AddValue("i", Int32);
|
||||
}
|
||||
}
|
||||
|
||||
private DiscriminatedUnion32(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
this = default(DiscriminatedUnion32);
|
||||
SerializationInfoEnumerator enumerator = info.GetEnumerator();
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
SerializationEntry current = enumerator.Current;
|
||||
string name = current.Name;
|
||||
if (!(name == "d"))
|
||||
{
|
||||
if (name == "i")
|
||||
{
|
||||
Int32 = (int)current.Value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_discriminator = (int)current.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
[Serializable]
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public readonly struct DiscriminatedUnion32Object : ISerializable
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
private readonly int _discriminator;
|
||||
|
||||
[FieldOffset(4)]
|
||||
public readonly int Int32;
|
||||
|
||||
[FieldOffset(4)]
|
||||
public readonly uint UInt32;
|
||||
|
||||
[FieldOffset(4)]
|
||||
public readonly bool Boolean;
|
||||
|
||||
[FieldOffset(4)]
|
||||
public readonly float Single;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly object Object;
|
||||
|
||||
public int Discriminator => _discriminator;
|
||||
|
||||
private DiscriminatedUnion32Object(int discriminator)
|
||||
{
|
||||
this = default(DiscriminatedUnion32Object);
|
||||
_discriminator = discriminator;
|
||||
}
|
||||
|
||||
public bool Is(int discriminator)
|
||||
{
|
||||
return _discriminator == discriminator;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion32Object(int discriminator, int value)
|
||||
: this(discriminator)
|
||||
{
|
||||
Int32 = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion32Object(int discriminator, uint value)
|
||||
: this(discriminator)
|
||||
{
|
||||
UInt32 = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion32Object(int discriminator, float value)
|
||||
: this(discriminator)
|
||||
{
|
||||
Single = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion32Object(int discriminator, bool value)
|
||||
: this(discriminator)
|
||||
{
|
||||
Boolean = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion32Object(int discriminator, object value)
|
||||
: this((value != null) ? discriminator : 0)
|
||||
{
|
||||
Object = value;
|
||||
}
|
||||
|
||||
public static void Reset(ref DiscriminatedUnion32Object value, int discriminator)
|
||||
{
|
||||
if (value.Discriminator == discriminator)
|
||||
{
|
||||
value = default(DiscriminatedUnion32Object);
|
||||
}
|
||||
}
|
||||
|
||||
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
if (_discriminator != 0)
|
||||
{
|
||||
info.AddValue("d", _discriminator);
|
||||
}
|
||||
if (Int32 != 0)
|
||||
{
|
||||
info.AddValue("i", Int32);
|
||||
}
|
||||
if (Object != null)
|
||||
{
|
||||
info.AddValue("o", Object);
|
||||
}
|
||||
}
|
||||
|
||||
private DiscriminatedUnion32Object(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
this = default(DiscriminatedUnion32Object);
|
||||
SerializationInfoEnumerator enumerator = info.GetEnumerator();
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
SerializationEntry current = enumerator.Current;
|
||||
switch (current.Name)
|
||||
{
|
||||
case "d":
|
||||
_discriminator = (int)current.Value;
|
||||
break;
|
||||
case "i":
|
||||
Int32 = (int)current.Value;
|
||||
break;
|
||||
case "o":
|
||||
Object = current.Value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
[Serializable]
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public readonly struct DiscriminatedUnion64 : ISerializable
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
private readonly int _discriminator;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly long Int64;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly ulong UInt64;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly int Int32;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly uint UInt32;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly bool Boolean;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly float Single;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly double Double;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly DateTime DateTime;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly TimeSpan TimeSpan;
|
||||
|
||||
public int Discriminator => _discriminator;
|
||||
|
||||
unsafe static DiscriminatedUnion64()
|
||||
{
|
||||
if (sizeof(DateTime) > 8)
|
||||
{
|
||||
throw new InvalidOperationException("DateTime was unexpectedly too big for DiscriminatedUnion64");
|
||||
}
|
||||
if (sizeof(TimeSpan) > 8)
|
||||
{
|
||||
throw new InvalidOperationException("TimeSpan was unexpectedly too big for DiscriminatedUnion64");
|
||||
}
|
||||
}
|
||||
|
||||
private DiscriminatedUnion64(int discriminator)
|
||||
{
|
||||
this = default(DiscriminatedUnion64);
|
||||
_discriminator = discriminator;
|
||||
}
|
||||
|
||||
public bool Is(int discriminator)
|
||||
{
|
||||
return _discriminator == discriminator;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion64(int discriminator, long value)
|
||||
: this(discriminator)
|
||||
{
|
||||
Int64 = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion64(int discriminator, int value)
|
||||
: this(discriminator)
|
||||
{
|
||||
Int32 = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion64(int discriminator, ulong value)
|
||||
: this(discriminator)
|
||||
{
|
||||
UInt64 = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion64(int discriminator, uint value)
|
||||
: this(discriminator)
|
||||
{
|
||||
UInt32 = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion64(int discriminator, float value)
|
||||
: this(discriminator)
|
||||
{
|
||||
Single = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion64(int discriminator, double value)
|
||||
: this(discriminator)
|
||||
{
|
||||
Double = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion64(int discriminator, bool value)
|
||||
: this(discriminator)
|
||||
{
|
||||
Boolean = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion64(int discriminator, DateTime? value)
|
||||
: this(value.HasValue ? discriminator : 0)
|
||||
{
|
||||
DateTime = value.GetValueOrDefault();
|
||||
}
|
||||
|
||||
public DiscriminatedUnion64(int discriminator, TimeSpan? value)
|
||||
: this(value.HasValue ? discriminator : 0)
|
||||
{
|
||||
TimeSpan = value.GetValueOrDefault();
|
||||
}
|
||||
|
||||
public static void Reset(ref DiscriminatedUnion64 value, int discriminator)
|
||||
{
|
||||
if (value.Discriminator == discriminator)
|
||||
{
|
||||
value = default(DiscriminatedUnion64);
|
||||
}
|
||||
}
|
||||
|
||||
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
if (_discriminator != 0)
|
||||
{
|
||||
info.AddValue("d", _discriminator);
|
||||
}
|
||||
if (Int64 != 0L)
|
||||
{
|
||||
info.AddValue("i", Int64);
|
||||
}
|
||||
}
|
||||
|
||||
private DiscriminatedUnion64(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
this = default(DiscriminatedUnion64);
|
||||
SerializationInfoEnumerator enumerator = info.GetEnumerator();
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
SerializationEntry current = enumerator.Current;
|
||||
string name = current.Name;
|
||||
if (!(name == "d"))
|
||||
{
|
||||
if (name == "i")
|
||||
{
|
||||
Int64 = (long)current.Value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_discriminator = (int)current.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
[Serializable]
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public readonly struct DiscriminatedUnion64Object : ISerializable
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
private readonly int _discriminator;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly long Int64;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly ulong UInt64;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly int Int32;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly uint UInt32;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly bool Boolean;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly float Single;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly double Double;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly DateTime DateTime;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public readonly TimeSpan TimeSpan;
|
||||
|
||||
[FieldOffset(16)]
|
||||
public readonly object Object;
|
||||
|
||||
public int Discriminator => _discriminator;
|
||||
|
||||
unsafe static DiscriminatedUnion64Object()
|
||||
{
|
||||
if (sizeof(DateTime) > 8)
|
||||
{
|
||||
throw new InvalidOperationException("DateTime was unexpectedly too big for DiscriminatedUnion64Object");
|
||||
}
|
||||
if (sizeof(TimeSpan) > 8)
|
||||
{
|
||||
throw new InvalidOperationException("TimeSpan was unexpectedly too big for DiscriminatedUnion64Object");
|
||||
}
|
||||
}
|
||||
|
||||
private DiscriminatedUnion64Object(int discriminator)
|
||||
{
|
||||
this = default(DiscriminatedUnion64Object);
|
||||
_discriminator = discriminator;
|
||||
}
|
||||
|
||||
public bool Is(int discriminator)
|
||||
{
|
||||
return _discriminator == discriminator;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion64Object(int discriminator, long value)
|
||||
: this(discriminator)
|
||||
{
|
||||
Int64 = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion64Object(int discriminator, int value)
|
||||
: this(discriminator)
|
||||
{
|
||||
Int32 = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion64Object(int discriminator, ulong value)
|
||||
: this(discriminator)
|
||||
{
|
||||
UInt64 = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion64Object(int discriminator, uint value)
|
||||
: this(discriminator)
|
||||
{
|
||||
UInt32 = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion64Object(int discriminator, float value)
|
||||
: this(discriminator)
|
||||
{
|
||||
Single = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion64Object(int discriminator, double value)
|
||||
: this(discriminator)
|
||||
{
|
||||
Double = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion64Object(int discriminator, bool value)
|
||||
: this(discriminator)
|
||||
{
|
||||
Boolean = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion64Object(int discriminator, object value)
|
||||
: this((value != null) ? discriminator : 0)
|
||||
{
|
||||
Object = value;
|
||||
}
|
||||
|
||||
public DiscriminatedUnion64Object(int discriminator, DateTime? value)
|
||||
: this(value.HasValue ? discriminator : 0)
|
||||
{
|
||||
DateTime = value.GetValueOrDefault();
|
||||
}
|
||||
|
||||
public DiscriminatedUnion64Object(int discriminator, TimeSpan? value)
|
||||
: this(value.HasValue ? discriminator : 0)
|
||||
{
|
||||
TimeSpan = value.GetValueOrDefault();
|
||||
}
|
||||
|
||||
public static void Reset(ref DiscriminatedUnion64Object value, int discriminator)
|
||||
{
|
||||
if (value.Discriminator == discriminator)
|
||||
{
|
||||
value = default(DiscriminatedUnion64Object);
|
||||
}
|
||||
}
|
||||
|
||||
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
if (_discriminator != 0)
|
||||
{
|
||||
info.AddValue("d", _discriminator);
|
||||
}
|
||||
if (Int64 != 0L)
|
||||
{
|
||||
info.AddValue("i", Int64);
|
||||
}
|
||||
if (Object != null)
|
||||
{
|
||||
info.AddValue("o", Object);
|
||||
}
|
||||
}
|
||||
|
||||
private DiscriminatedUnion64Object(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
this = default(DiscriminatedUnion64Object);
|
||||
SerializationInfoEnumerator enumerator = info.GetEnumerator();
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
SerializationEntry current = enumerator.Current;
|
||||
switch (current.Name)
|
||||
{
|
||||
case "d":
|
||||
_discriminator = (int)current.Value;
|
||||
break;
|
||||
case "i":
|
||||
Int64 = (long)current.Value;
|
||||
break;
|
||||
case "o":
|
||||
Object = current.Value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
[Serializable]
|
||||
public readonly struct DiscriminatedUnionObject : ISerializable
|
||||
{
|
||||
public readonly object Object;
|
||||
|
||||
public int Discriminator { get; }
|
||||
|
||||
public bool Is(int discriminator)
|
||||
{
|
||||
return Discriminator == discriminator;
|
||||
}
|
||||
|
||||
public DiscriminatedUnionObject(int discriminator, object value)
|
||||
{
|
||||
Discriminator = discriminator;
|
||||
Object = value;
|
||||
}
|
||||
|
||||
public static void Reset(ref DiscriminatedUnionObject value, int discriminator)
|
||||
{
|
||||
if (value.Discriminator == discriminator)
|
||||
{
|
||||
value = default(DiscriminatedUnionObject);
|
||||
}
|
||||
}
|
||||
|
||||
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
if (Discriminator != 0)
|
||||
{
|
||||
info.AddValue("d", Discriminator);
|
||||
}
|
||||
if (Object != null)
|
||||
{
|
||||
info.AddValue("o", Object);
|
||||
}
|
||||
}
|
||||
|
||||
private DiscriminatedUnionObject(SerializationInfo info, StreamingContext context)
|
||||
{
|
||||
this = default(DiscriminatedUnionObject);
|
||||
SerializationInfoEnumerator enumerator = info.GetEnumerator();
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
SerializationEntry current = enumerator.Current;
|
||||
string name = current.Name;
|
||||
if (!(name == "d"))
|
||||
{
|
||||
if (name == "o")
|
||||
{
|
||||
Object = current.Value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Discriminator = (int)current.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using ProtoBuf.Meta;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
public abstract class Extensible : IExtensible
|
||||
{
|
||||
private IExtension extensionObject;
|
||||
|
||||
IExtension IExtensible.GetExtensionObject(bool createIfMissing)
|
||||
{
|
||||
return GetExtensionObject(createIfMissing);
|
||||
}
|
||||
|
||||
protected virtual IExtension GetExtensionObject(bool createIfMissing)
|
||||
{
|
||||
return GetExtensionObject(ref extensionObject, createIfMissing);
|
||||
}
|
||||
|
||||
public static IExtension GetExtensionObject(ref IExtension extensionObject, bool createIfMissing)
|
||||
{
|
||||
if (createIfMissing && extensionObject == null)
|
||||
{
|
||||
extensionObject = new BufferExtension();
|
||||
}
|
||||
return extensionObject;
|
||||
}
|
||||
|
||||
public static void AppendValue<TValue>(IExtensible instance, int tag, TValue value)
|
||||
{
|
||||
AppendValue(instance, tag, DataFormat.Default, value);
|
||||
}
|
||||
|
||||
public static void AppendValue<TValue>(IExtensible instance, int tag, DataFormat format, TValue value)
|
||||
{
|
||||
ExtensibleUtil.AppendExtendValue(RuntimeTypeModel.Default, instance, tag, format, value);
|
||||
}
|
||||
|
||||
public static TValue GetValue<TValue>(IExtensible instance, int tag)
|
||||
{
|
||||
return GetValue<TValue>(instance, tag, DataFormat.Default);
|
||||
}
|
||||
|
||||
public static TValue GetValue<TValue>(IExtensible instance, int tag, DataFormat format)
|
||||
{
|
||||
TryGetValue<TValue>(instance, tag, format, out var value);
|
||||
return value;
|
||||
}
|
||||
|
||||
public static bool TryGetValue<TValue>(IExtensible instance, int tag, out TValue value)
|
||||
{
|
||||
return TryGetValue<TValue>(instance, tag, DataFormat.Default, out value);
|
||||
}
|
||||
|
||||
public static bool TryGetValue<TValue>(IExtensible instance, int tag, DataFormat format, out TValue value)
|
||||
{
|
||||
return TryGetValue<TValue>(instance, tag, format, allowDefinedTag: false, out value);
|
||||
}
|
||||
|
||||
public static bool TryGetValue<TValue>(IExtensible instance, int tag, DataFormat format, bool allowDefinedTag, out TValue value)
|
||||
{
|
||||
value = default(TValue);
|
||||
bool result = false;
|
||||
foreach (TValue extendedValue in ExtensibleUtil.GetExtendedValues<TValue>(instance, tag, format, singleton: true, allowDefinedTag))
|
||||
{
|
||||
value = extendedValue;
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static IEnumerable<TValue> GetValues<TValue>(IExtensible instance, int tag)
|
||||
{
|
||||
return ExtensibleUtil.GetExtendedValues<TValue>(instance, tag, DataFormat.Default, singleton: false, allowDefinedTag: false);
|
||||
}
|
||||
|
||||
public static IEnumerable<TValue> GetValues<TValue>(IExtensible instance, int tag, DataFormat format)
|
||||
{
|
||||
return ExtensibleUtil.GetExtendedValues<TValue>(instance, tag, format, singleton: false, allowDefinedTag: false);
|
||||
}
|
||||
|
||||
public static bool TryGetValue(TypeModel model, Type type, IExtensible instance, int tag, DataFormat format, bool allowDefinedTag, out object value)
|
||||
{
|
||||
value = null;
|
||||
bool result = false;
|
||||
foreach (object extendedValue in ExtensibleUtil.GetExtendedValues(model, type, instance, tag, format, singleton: true, allowDefinedTag))
|
||||
{
|
||||
value = extendedValue;
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static IEnumerable GetValues(TypeModel model, Type type, IExtensible instance, int tag, DataFormat format)
|
||||
{
|
||||
return ExtensibleUtil.GetExtendedValues(model, type, instance, tag, format, singleton: false, allowDefinedTag: false);
|
||||
}
|
||||
|
||||
public static void AppendValue(TypeModel model, IExtensible instance, int tag, DataFormat format, object value)
|
||||
{
|
||||
ExtensibleUtil.AppendExtendValue(model, instance, tag, format, value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using ProtoBuf.Meta;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
internal static class ExtensibleUtil
|
||||
{
|
||||
internal static IEnumerable<TValue> GetExtendedValues<TValue>(IExtensible instance, int tag, DataFormat format, bool singleton, bool allowDefinedTag)
|
||||
{
|
||||
foreach (TValue extendedValue in GetExtendedValues(RuntimeTypeModel.Default, typeof(TValue), instance, tag, format, singleton, allowDefinedTag))
|
||||
{
|
||||
yield return extendedValue;
|
||||
}
|
||||
}
|
||||
|
||||
internal static IEnumerable GetExtendedValues(TypeModel model, Type type, IExtensible instance, int tag, DataFormat format, bool singleton, bool allowDefinedTag)
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
throw new ArgumentNullException("instance");
|
||||
}
|
||||
if (tag <= 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("tag");
|
||||
}
|
||||
IExtension extn = instance.GetExtensionObject(createIfMissing: false);
|
||||
if (extn == null)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
Stream stream = extn.BeginQuery();
|
||||
object value = null;
|
||||
ProtoReader reader = null;
|
||||
try
|
||||
{
|
||||
SerializationContext context = new SerializationContext();
|
||||
reader = ProtoReader.Create(stream, model, context, -1L);
|
||||
while (model.TryDeserializeAuxiliaryType(reader, format, tag, type, ref value, skipOtherFields: true, asListItem: true, autoCreate: false, insideList: false, null) && value != null)
|
||||
{
|
||||
if (!singleton)
|
||||
{
|
||||
yield return value;
|
||||
value = null;
|
||||
}
|
||||
}
|
||||
if (singleton && value != null)
|
||||
{
|
||||
yield return value;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
ProtoReader.Recycle(reader);
|
||||
extn.EndQuery(stream);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void AppendExtendValue(TypeModel model, IExtensible instance, int tag, DataFormat format, object value)
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
throw new ArgumentNullException("instance");
|
||||
}
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentNullException("value");
|
||||
}
|
||||
IExtension extensionObject = instance.GetExtensionObject(createIfMissing: true);
|
||||
if (extensionObject == null)
|
||||
{
|
||||
throw new InvalidOperationException("No extension object available; appended data would be lost.");
|
||||
}
|
||||
bool commit = false;
|
||||
Stream stream = extensionObject.BeginAppend();
|
||||
try
|
||||
{
|
||||
using (ProtoWriter protoWriter = ProtoWriter.Create(stream, model))
|
||||
{
|
||||
model.TrySerializeAuxiliaryType(protoWriter, null, format, tag, value, isInsideList: false, null);
|
||||
protoWriter.Close();
|
||||
}
|
||||
commit = true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
extensionObject.EndAppend(stream, commit);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,267 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
internal sealed class Helpers
|
||||
{
|
||||
public static readonly Type[] EmptyTypes = Type.EmptyTypes;
|
||||
|
||||
private Helpers()
|
||||
{
|
||||
}
|
||||
|
||||
public static StringBuilder AppendLine(StringBuilder builder)
|
||||
{
|
||||
return builder.AppendLine();
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
public static void DebugWriteLine(string message, object obj)
|
||||
{
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
public static void DebugWriteLine(string message)
|
||||
{
|
||||
}
|
||||
|
||||
[Conditional("TRACE")]
|
||||
public static void TraceWriteLine(string message)
|
||||
{
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
public static void DebugAssert(bool condition, string message)
|
||||
{
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
public static void DebugAssert(bool condition, string message, params object[] args)
|
||||
{
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
public static void DebugAssert(bool condition)
|
||||
{
|
||||
}
|
||||
|
||||
public static void Sort(int[] keys, object[] values)
|
||||
{
|
||||
bool flag;
|
||||
do
|
||||
{
|
||||
flag = false;
|
||||
for (int i = 1; i < keys.Length; i++)
|
||||
{
|
||||
if (keys[i - 1] > keys[i])
|
||||
{
|
||||
int num = keys[i];
|
||||
keys[i] = keys[i - 1];
|
||||
keys[i - 1] = num;
|
||||
object obj = values[i];
|
||||
values[i] = values[i - 1];
|
||||
values[i - 1] = obj;
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (flag);
|
||||
}
|
||||
|
||||
internal static MethodInfo GetInstanceMethod(Type declaringType, string name)
|
||||
{
|
||||
return declaringType.GetMethod(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
internal static MethodInfo GetStaticMethod(Type declaringType, string name)
|
||||
{
|
||||
return declaringType.GetMethod(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
internal static MethodInfo GetStaticMethod(Type declaringType, string name, Type[] parameterTypes)
|
||||
{
|
||||
return declaringType.GetMethod(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, parameterTypes, null);
|
||||
}
|
||||
|
||||
internal static MethodInfo GetInstanceMethod(Type declaringType, string name, Type[] types)
|
||||
{
|
||||
if (types == null)
|
||||
{
|
||||
types = EmptyTypes;
|
||||
}
|
||||
return declaringType.GetMethod(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, types, null);
|
||||
}
|
||||
|
||||
internal static bool IsSubclassOf(Type type, Type baseClass)
|
||||
{
|
||||
return type.IsSubclassOf(baseClass);
|
||||
}
|
||||
|
||||
public static ProtoTypeCode GetTypeCode(Type type)
|
||||
{
|
||||
TypeCode typeCode = Type.GetTypeCode(type);
|
||||
switch (typeCode)
|
||||
{
|
||||
case TypeCode.Empty:
|
||||
case TypeCode.Boolean:
|
||||
case TypeCode.Char:
|
||||
case TypeCode.SByte:
|
||||
case TypeCode.Byte:
|
||||
case TypeCode.Int16:
|
||||
case TypeCode.UInt16:
|
||||
case TypeCode.Int32:
|
||||
case TypeCode.UInt32:
|
||||
case TypeCode.Int64:
|
||||
case TypeCode.UInt64:
|
||||
case TypeCode.Single:
|
||||
case TypeCode.Double:
|
||||
case TypeCode.Decimal:
|
||||
case TypeCode.DateTime:
|
||||
case TypeCode.String:
|
||||
return (ProtoTypeCode)typeCode;
|
||||
default:
|
||||
if ((object)type == typeof(TimeSpan))
|
||||
{
|
||||
return ProtoTypeCode.TimeSpan;
|
||||
}
|
||||
if ((object)type == typeof(Guid))
|
||||
{
|
||||
return ProtoTypeCode.Guid;
|
||||
}
|
||||
if ((object)type == typeof(Uri))
|
||||
{
|
||||
return ProtoTypeCode.Uri;
|
||||
}
|
||||
if ((object)type == typeof(byte[]))
|
||||
{
|
||||
return ProtoTypeCode.ByteArray;
|
||||
}
|
||||
if ((object)type == typeof(Type))
|
||||
{
|
||||
return ProtoTypeCode.Type;
|
||||
}
|
||||
return ProtoTypeCode.Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
internal static Type GetUnderlyingType(Type type)
|
||||
{
|
||||
return Nullable.GetUnderlyingType(type);
|
||||
}
|
||||
|
||||
internal static bool IsValueType(Type type)
|
||||
{
|
||||
return type.IsValueType;
|
||||
}
|
||||
|
||||
internal static bool IsSealed(Type type)
|
||||
{
|
||||
return type.IsSealed;
|
||||
}
|
||||
|
||||
internal static bool IsClass(Type type)
|
||||
{
|
||||
return type.IsClass;
|
||||
}
|
||||
|
||||
internal static bool IsEnum(Type type)
|
||||
{
|
||||
return type.IsEnum;
|
||||
}
|
||||
|
||||
internal static MethodInfo GetGetMethod(PropertyInfo property, bool nonPublic, bool allowInternal)
|
||||
{
|
||||
if ((object)property == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
MethodInfo methodInfo = property.GetGetMethod(nonPublic);
|
||||
if ((object)methodInfo == null && !nonPublic && allowInternal)
|
||||
{
|
||||
methodInfo = property.GetGetMethod(nonPublic: true);
|
||||
if ((object)methodInfo == null && !methodInfo.IsAssembly && !methodInfo.IsFamilyOrAssembly)
|
||||
{
|
||||
methodInfo = null;
|
||||
}
|
||||
}
|
||||
return methodInfo;
|
||||
}
|
||||
|
||||
internal static MethodInfo GetSetMethod(PropertyInfo property, bool nonPublic, bool allowInternal)
|
||||
{
|
||||
if ((object)property == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
MethodInfo methodInfo = property.GetSetMethod(nonPublic);
|
||||
if ((object)methodInfo == null && !nonPublic && allowInternal)
|
||||
{
|
||||
methodInfo = property.GetGetMethod(nonPublic: true);
|
||||
if ((object)methodInfo == null && !methodInfo.IsAssembly && !methodInfo.IsFamilyOrAssembly)
|
||||
{
|
||||
methodInfo = null;
|
||||
}
|
||||
}
|
||||
return methodInfo;
|
||||
}
|
||||
|
||||
internal static ConstructorInfo GetConstructor(Type type, Type[] parameterTypes, bool nonPublic)
|
||||
{
|
||||
return type.GetConstructor(nonPublic ? (BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) : (BindingFlags.Instance | BindingFlags.Public), null, parameterTypes, null);
|
||||
}
|
||||
|
||||
internal static ConstructorInfo[] GetConstructors(Type type, bool nonPublic)
|
||||
{
|
||||
return type.GetConstructors(nonPublic ? (BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) : (BindingFlags.Instance | BindingFlags.Public));
|
||||
}
|
||||
|
||||
internal static PropertyInfo GetProperty(Type type, string name, bool nonPublic)
|
||||
{
|
||||
return type.GetProperty(name, nonPublic ? (BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) : (BindingFlags.Instance | BindingFlags.Public));
|
||||
}
|
||||
|
||||
internal static object ParseEnum(Type type, string value)
|
||||
{
|
||||
return Enum.Parse(type, value, ignoreCase: true);
|
||||
}
|
||||
|
||||
internal static MemberInfo[] GetInstanceFieldsAndProperties(Type type, bool publicOnly)
|
||||
{
|
||||
BindingFlags bindingAttr = (publicOnly ? (BindingFlags.Instance | BindingFlags.Public) : (BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic));
|
||||
PropertyInfo[] properties = type.GetProperties(bindingAttr);
|
||||
FieldInfo[] fields = type.GetFields(bindingAttr);
|
||||
MemberInfo[] array = new MemberInfo[fields.Length + properties.Length];
|
||||
properties.CopyTo(array, 0);
|
||||
fields.CopyTo(array, properties.Length);
|
||||
return array;
|
||||
}
|
||||
|
||||
internal static Type GetMemberType(MemberInfo member)
|
||||
{
|
||||
return member.MemberType switch
|
||||
{
|
||||
MemberTypes.Field => ((FieldInfo)member).FieldType,
|
||||
MemberTypes.Property => ((PropertyInfo)member).PropertyType,
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
||||
internal static bool IsAssignableFrom(Type target, Type type)
|
||||
{
|
||||
return target.IsAssignableFrom(type);
|
||||
}
|
||||
|
||||
internal static Assembly GetAssembly(Type type)
|
||||
{
|
||||
return type.Assembly;
|
||||
}
|
||||
|
||||
internal static byte[] GetBuffer(MemoryStream ms)
|
||||
{
|
||||
return ms.GetBuffer();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace ProtoBuf;
|
||||
|
||||
public interface IExtensible
|
||||
{
|
||||
IExtension GetExtensionObject(bool createIfMissing);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using System.IO;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
public interface IExtension
|
||||
{
|
||||
Stream BeginAppend();
|
||||
|
||||
void EndAppend(Stream stream, bool commit);
|
||||
|
||||
Stream BeginQuery();
|
||||
|
||||
void EndQuery(Stream stream);
|
||||
|
||||
int GetLength();
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace ProtoBuf;
|
||||
|
||||
public interface IExtensionResettable : IExtension
|
||||
{
|
||||
void Reset();
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace ProtoBuf;
|
||||
|
||||
public interface IMeasuredProtoOutput<TOutput> : IProtoOutput<TOutput>
|
||||
{
|
||||
MeasureState<T> Measure<T>(T value, object userState = null);
|
||||
|
||||
void Serialize<T>(MeasureState<T> measured, TOutput destination);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace ProtoBuf;
|
||||
|
||||
public interface IProtoInput<TInput>
|
||||
{
|
||||
T Deserialize<T>(TInput source, T value = default(T), object userState = null);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace ProtoBuf;
|
||||
|
||||
public interface IProtoOutput<TOutput>
|
||||
{
|
||||
void Serialize<T>(TOutput destination, T value, object userState = null);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace ProtoBuf;
|
||||
|
||||
public enum ImplicitFields
|
||||
{
|
||||
None,
|
||||
AllPublic,
|
||||
AllFields
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Size = 1)]
|
||||
public struct MeasureState<T> : IDisposable
|
||||
{
|
||||
public long Length
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
[Flags]
|
||||
public enum MemberSerializationOptions
|
||||
{
|
||||
None = 0,
|
||||
Packed = 1,
|
||||
Required = 2,
|
||||
AsReference = 4,
|
||||
DynamicType = 8,
|
||||
OverwriteList = 0x10,
|
||||
AsReferenceHasValue = 0x20
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using ProtoBuf.Meta;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
internal sealed class NetObjectCache
|
||||
{
|
||||
private sealed class ReferenceComparer : IEqualityComparer<object>
|
||||
{
|
||||
public static readonly ReferenceComparer Default = new ReferenceComparer();
|
||||
|
||||
private ReferenceComparer()
|
||||
{
|
||||
}
|
||||
|
||||
bool IEqualityComparer<object>.Equals(object x, object y)
|
||||
{
|
||||
return x == y;
|
||||
}
|
||||
|
||||
int IEqualityComparer<object>.GetHashCode(object obj)
|
||||
{
|
||||
return RuntimeHelpers.GetHashCode(obj);
|
||||
}
|
||||
}
|
||||
|
||||
internal const int Root = 0;
|
||||
|
||||
private MutableList underlyingList;
|
||||
|
||||
private object rootObject;
|
||||
|
||||
private int trapStartIndex;
|
||||
|
||||
private Dictionary<string, int> stringKeys;
|
||||
|
||||
private Dictionary<object, int> objectKeys;
|
||||
|
||||
private MutableList List => underlyingList ?? (underlyingList = new MutableList());
|
||||
|
||||
internal object GetKeyedObject(int key)
|
||||
{
|
||||
if (key-- == 0)
|
||||
{
|
||||
if (rootObject == null)
|
||||
{
|
||||
throw new ProtoException("No root object assigned");
|
||||
}
|
||||
return rootObject;
|
||||
}
|
||||
BasicList list = List;
|
||||
if (key < 0 || key >= list.Count)
|
||||
{
|
||||
throw new ProtoException("Internal error; a missing key occurred");
|
||||
}
|
||||
object obj = list[key];
|
||||
if (obj == null)
|
||||
{
|
||||
throw new ProtoException("A deferred key does not have a value yet");
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
internal void SetKeyedObject(int key, object value)
|
||||
{
|
||||
if (key-- == 0)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentNullException("value");
|
||||
}
|
||||
if (rootObject != null && rootObject != value)
|
||||
{
|
||||
throw new ProtoException("The root object cannot be reassigned");
|
||||
}
|
||||
rootObject = value;
|
||||
return;
|
||||
}
|
||||
MutableList list = List;
|
||||
if (key < list.Count)
|
||||
{
|
||||
object obj = list[key];
|
||||
if (obj == null)
|
||||
{
|
||||
list[key] = value;
|
||||
}
|
||||
else if (obj != value)
|
||||
{
|
||||
throw new ProtoException("Reference-tracked objects cannot change reference");
|
||||
}
|
||||
}
|
||||
else if (key != list.Add(value))
|
||||
{
|
||||
throw new ProtoException("Internal error; a key mismatch occurred");
|
||||
}
|
||||
}
|
||||
|
||||
internal int AddObjectKey(object value, out bool existing)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentNullException("value");
|
||||
}
|
||||
if (value == rootObject)
|
||||
{
|
||||
existing = true;
|
||||
return 0;
|
||||
}
|
||||
string text = value as string;
|
||||
BasicList list = List;
|
||||
int value2;
|
||||
if (text == null)
|
||||
{
|
||||
if (objectKeys == null)
|
||||
{
|
||||
objectKeys = new Dictionary<object, int>(ReferenceComparer.Default);
|
||||
value2 = -1;
|
||||
}
|
||||
else if (!objectKeys.TryGetValue(value, out value2))
|
||||
{
|
||||
value2 = -1;
|
||||
}
|
||||
}
|
||||
else if (stringKeys == null)
|
||||
{
|
||||
stringKeys = new Dictionary<string, int>();
|
||||
value2 = -1;
|
||||
}
|
||||
else if (!stringKeys.TryGetValue(text, out value2))
|
||||
{
|
||||
value2 = -1;
|
||||
}
|
||||
if (!(existing = value2 >= 0))
|
||||
{
|
||||
value2 = list.Add(value);
|
||||
if (text == null)
|
||||
{
|
||||
objectKeys.Add(value, value2);
|
||||
}
|
||||
else
|
||||
{
|
||||
stringKeys.Add(text, value2);
|
||||
}
|
||||
}
|
||||
return value2 + 1;
|
||||
}
|
||||
|
||||
internal void RegisterTrappedObject(object value)
|
||||
{
|
||||
if (rootObject == null)
|
||||
{
|
||||
rootObject = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (underlyingList == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = trapStartIndex; i < underlyingList.Count; i++)
|
||||
{
|
||||
trapStartIndex = i + 1;
|
||||
if (underlyingList[i] == null)
|
||||
{
|
||||
underlyingList[i] = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void Clear()
|
||||
{
|
||||
trapStartIndex = 0;
|
||||
rootObject = null;
|
||||
if (underlyingList != null)
|
||||
{
|
||||
underlyingList.Clear();
|
||||
}
|
||||
if (stringKeys != null)
|
||||
{
|
||||
stringKeys.Clear();
|
||||
}
|
||||
if (objectKeys != null)
|
||||
{
|
||||
objectKeys.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace ProtoBuf;
|
||||
|
||||
public enum PrefixStyle
|
||||
{
|
||||
None,
|
||||
Base128,
|
||||
Fixed32,
|
||||
Fixed32BigEndian
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
|
||||
[ImmutableObject(true)]
|
||||
public sealed class ProtoAfterDeserializationAttribute : Attribute
|
||||
{
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
|
||||
[ImmutableObject(true)]
|
||||
public sealed class ProtoAfterSerializationAttribute : Attribute
|
||||
{
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
|
||||
[ImmutableObject(true)]
|
||||
public sealed class ProtoBeforeDeserializationAttribute : Attribute
|
||||
{
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
|
||||
[ImmutableObject(true)]
|
||||
public sealed class ProtoBeforeSerializationAttribute : Attribute
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
using System;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Interface, AllowMultiple = false, Inherited = false)]
|
||||
public sealed class ProtoContractAttribute : Attribute
|
||||
{
|
||||
private int implicitFirstTag;
|
||||
|
||||
private ushort flags;
|
||||
|
||||
private const ushort OPTIONS_InferTagFromName = 1;
|
||||
|
||||
private const ushort OPTIONS_InferTagFromNameHasValue = 2;
|
||||
|
||||
private const ushort OPTIONS_UseProtoMembersOnly = 4;
|
||||
|
||||
private const ushort OPTIONS_SkipConstructor = 8;
|
||||
|
||||
private const ushort OPTIONS_IgnoreListHandling = 16;
|
||||
|
||||
private const ushort OPTIONS_AsReferenceDefault = 32;
|
||||
|
||||
private const ushort OPTIONS_EnumPassthru = 64;
|
||||
|
||||
private const ushort OPTIONS_EnumPassthruHasValue = 128;
|
||||
|
||||
private const ushort OPTIONS_IsGroup = 256;
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public int ImplicitFirstTag
|
||||
{
|
||||
get
|
||||
{
|
||||
return implicitFirstTag;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value < 1)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("ImplicitFirstTag");
|
||||
}
|
||||
implicitFirstTag = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool UseProtoMembersOnly
|
||||
{
|
||||
get
|
||||
{
|
||||
return HasFlag(4);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetFlag(4, value);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IgnoreListHandling
|
||||
{
|
||||
get
|
||||
{
|
||||
return HasFlag(16);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetFlag(16, value);
|
||||
}
|
||||
}
|
||||
|
||||
public ImplicitFields ImplicitFields { get; set; }
|
||||
|
||||
public bool InferTagFromName
|
||||
{
|
||||
get
|
||||
{
|
||||
return HasFlag(1);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetFlag(1, value);
|
||||
SetFlag(2, value: true);
|
||||
}
|
||||
}
|
||||
|
||||
internal bool InferTagFromNameHasValue => HasFlag(2);
|
||||
|
||||
public int DataMemberOffset { get; set; }
|
||||
|
||||
public bool SkipConstructor
|
||||
{
|
||||
get
|
||||
{
|
||||
return HasFlag(8);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetFlag(8, value);
|
||||
}
|
||||
}
|
||||
|
||||
public bool AsReferenceDefault
|
||||
{
|
||||
get
|
||||
{
|
||||
return HasFlag(32);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetFlag(32, value);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsGroup
|
||||
{
|
||||
get
|
||||
{
|
||||
return HasFlag(256);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetFlag(256, value);
|
||||
}
|
||||
}
|
||||
|
||||
public bool EnumPassthru
|
||||
{
|
||||
get
|
||||
{
|
||||
return HasFlag(64);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetFlag(64, value);
|
||||
SetFlag(128, value: true);
|
||||
}
|
||||
}
|
||||
|
||||
public Type Surrogate { get; set; }
|
||||
|
||||
internal bool EnumPassthruHasValue => HasFlag(128);
|
||||
|
||||
private bool HasFlag(ushort flag)
|
||||
{
|
||||
return (flags & flag) == flag;
|
||||
}
|
||||
|
||||
private void SetFlag(ushort flag, bool value)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
flags |= flag;
|
||||
}
|
||||
else
|
||||
{
|
||||
flags = (ushort)(flags & ~flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using System;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
|
||||
public class ProtoConverterAttribute : Attribute
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
|
||||
public sealed class ProtoEnumAttribute : Attribute
|
||||
{
|
||||
private bool hasValue;
|
||||
|
||||
private int enumValue;
|
||||
|
||||
public int Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return enumValue;
|
||||
}
|
||||
set
|
||||
{
|
||||
enumValue = value;
|
||||
hasValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public bool HasValue()
|
||||
{
|
||||
return hasValue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
[Serializable]
|
||||
public class ProtoException : Exception
|
||||
{
|
||||
public ProtoException()
|
||||
{
|
||||
}
|
||||
|
||||
public ProtoException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public ProtoException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
protected ProtoException(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using System;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
|
||||
public class ProtoIgnoreAttribute : Attribute
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using ProtoBuf.Meta;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true, Inherited = false)]
|
||||
public sealed class ProtoIncludeAttribute : Attribute
|
||||
{
|
||||
public int Tag { get; }
|
||||
|
||||
public string KnownTypeName { get; }
|
||||
|
||||
public Type KnownType => TypeModel.ResolveKnownType(KnownTypeName, null, null);
|
||||
|
||||
[DefaultValue(DataFormat.Default)]
|
||||
public DataFormat DataFormat { get; set; }
|
||||
|
||||
public ProtoIncludeAttribute(int tag, Type knownType)
|
||||
: this(tag, ((object)knownType == null) ? "" : knownType.AssemblyQualifiedName)
|
||||
{
|
||||
}
|
||||
|
||||
public ProtoIncludeAttribute(int tag, string knownTypeName)
|
||||
{
|
||||
if (tag <= 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("tag", "Tags must be positive integers");
|
||||
}
|
||||
if (string.IsNullOrEmpty(knownTypeName))
|
||||
{
|
||||
throw new ArgumentNullException("knownTypeName", "Known type cannot be blank");
|
||||
}
|
||||
Tag = tag;
|
||||
KnownTypeName = knownTypeName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
|
||||
public class ProtoMapAttribute : Attribute
|
||||
{
|
||||
public DataFormat KeyFormat { get; set; }
|
||||
|
||||
public DataFormat ValueFormat { get; set; }
|
||||
|
||||
public bool DisableMap { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
|
||||
public class ProtoMemberAttribute : Attribute, IComparable, IComparable<ProtoMemberAttribute>
|
||||
{
|
||||
internal MemberInfo Member;
|
||||
|
||||
internal MemberInfo BackingMember;
|
||||
|
||||
internal bool TagIsPinned;
|
||||
|
||||
private string name;
|
||||
|
||||
private DataFormat dataFormat;
|
||||
|
||||
private int tag;
|
||||
|
||||
private MemberSerializationOptions options;
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return name;
|
||||
}
|
||||
set
|
||||
{
|
||||
name = value;
|
||||
}
|
||||
}
|
||||
|
||||
public DataFormat DataFormat
|
||||
{
|
||||
get
|
||||
{
|
||||
return dataFormat;
|
||||
}
|
||||
set
|
||||
{
|
||||
dataFormat = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int Tag => tag;
|
||||
|
||||
public bool IsRequired
|
||||
{
|
||||
get
|
||||
{
|
||||
return (options & MemberSerializationOptions.Required) == MemberSerializationOptions.Required;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
options |= MemberSerializationOptions.Required;
|
||||
}
|
||||
else
|
||||
{
|
||||
options &= ~MemberSerializationOptions.Required;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsPacked
|
||||
{
|
||||
get
|
||||
{
|
||||
return (options & MemberSerializationOptions.Packed) == MemberSerializationOptions.Packed;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
options |= MemberSerializationOptions.Packed;
|
||||
}
|
||||
else
|
||||
{
|
||||
options &= ~MemberSerializationOptions.Packed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool OverwriteList
|
||||
{
|
||||
get
|
||||
{
|
||||
return (options & MemberSerializationOptions.OverwriteList) == MemberSerializationOptions.OverwriteList;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
options |= MemberSerializationOptions.OverwriteList;
|
||||
}
|
||||
else
|
||||
{
|
||||
options &= ~MemberSerializationOptions.OverwriteList;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool AsReference
|
||||
{
|
||||
get
|
||||
{
|
||||
return (options & MemberSerializationOptions.AsReference) == MemberSerializationOptions.AsReference;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
options |= MemberSerializationOptions.AsReference;
|
||||
}
|
||||
else
|
||||
{
|
||||
options &= ~MemberSerializationOptions.AsReference;
|
||||
}
|
||||
options |= MemberSerializationOptions.AsReferenceHasValue;
|
||||
}
|
||||
}
|
||||
|
||||
internal bool AsReferenceHasValue
|
||||
{
|
||||
get
|
||||
{
|
||||
return (options & MemberSerializationOptions.AsReferenceHasValue) == MemberSerializationOptions.AsReferenceHasValue;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
options |= MemberSerializationOptions.AsReferenceHasValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
options &= ~MemberSerializationOptions.AsReferenceHasValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool DynamicType
|
||||
{
|
||||
get
|
||||
{
|
||||
return (options & MemberSerializationOptions.DynamicType) == MemberSerializationOptions.DynamicType;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
options |= MemberSerializationOptions.DynamicType;
|
||||
}
|
||||
else
|
||||
{
|
||||
options &= ~MemberSerializationOptions.DynamicType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public MemberSerializationOptions Options
|
||||
{
|
||||
get
|
||||
{
|
||||
return options;
|
||||
}
|
||||
set
|
||||
{
|
||||
options = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int CompareTo(object other)
|
||||
{
|
||||
return CompareTo(other as ProtoMemberAttribute);
|
||||
}
|
||||
|
||||
public int CompareTo(ProtoMemberAttribute other)
|
||||
{
|
||||
if (other == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (this == other)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int num = tag.CompareTo(other.tag);
|
||||
if (num == 0)
|
||||
{
|
||||
num = string.CompareOrdinal(name, other.name);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
public ProtoMemberAttribute(int tag)
|
||||
: this(tag, forced: false)
|
||||
{
|
||||
}
|
||||
|
||||
internal ProtoMemberAttribute(int tag, bool forced)
|
||||
{
|
||||
if (tag <= 0 && !forced)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("tag");
|
||||
}
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
internal void Rebase(int tag)
|
||||
{
|
||||
this.tag = tag;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
|
||||
public sealed class ProtoPartialIgnoreAttribute : ProtoIgnoreAttribute
|
||||
{
|
||||
public string MemberName { get; }
|
||||
|
||||
public ProtoPartialIgnoreAttribute(string memberName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(memberName))
|
||||
{
|
||||
throw new ArgumentNullException("memberName");
|
||||
}
|
||||
MemberName = memberName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
|
||||
public sealed class ProtoPartialMemberAttribute : ProtoMemberAttribute
|
||||
{
|
||||
public string MemberName { get; private set; }
|
||||
|
||||
public ProtoPartialMemberAttribute(int tag, string memberName)
|
||||
: base(tag)
|
||||
{
|
||||
if (string.IsNullOrEmpty(memberName))
|
||||
{
|
||||
throw new ArgumentNullException("memberName");
|
||||
}
|
||||
MemberName = memberName;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,27 @@
|
||||
namespace ProtoBuf;
|
||||
|
||||
internal enum ProtoTypeCode
|
||||
{
|
||||
Empty = 0,
|
||||
Unknown = 1,
|
||||
Boolean = 3,
|
||||
Char = 4,
|
||||
SByte = 5,
|
||||
Byte = 6,
|
||||
Int16 = 7,
|
||||
UInt16 = 8,
|
||||
Int32 = 9,
|
||||
UInt32 = 10,
|
||||
Int64 = 11,
|
||||
UInt64 = 12,
|
||||
Single = 13,
|
||||
Double = 14,
|
||||
Decimal = 15,
|
||||
DateTime = 16,
|
||||
String = 18,
|
||||
TimeSpan = 100,
|
||||
ByteArray = 101,
|
||||
Guid = 102,
|
||||
Uri = 103,
|
||||
Type = 104
|
||||
}
|
||||
@@ -0,0 +1,953 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using ProtoBuf.Meta;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
public sealed class ProtoWriter : IDisposable
|
||||
{
|
||||
private Stream dest;
|
||||
|
||||
private TypeModel model;
|
||||
|
||||
private readonly NetObjectCache netCache = new NetObjectCache();
|
||||
|
||||
private int fieldNumber;
|
||||
|
||||
private int flushLock;
|
||||
|
||||
private WireType wireType;
|
||||
|
||||
private int depth;
|
||||
|
||||
private const int RecursionCheckDepth = 25;
|
||||
|
||||
private MutableList recursionStack;
|
||||
|
||||
private readonly SerializationContext context;
|
||||
|
||||
private byte[] ioBuffer;
|
||||
|
||||
private int ioIndex;
|
||||
|
||||
private long position64;
|
||||
|
||||
private static readonly UTF8Encoding encoding = new UTF8Encoding();
|
||||
|
||||
private int packedFieldNumber;
|
||||
|
||||
internal NetObjectCache NetCache => netCache;
|
||||
|
||||
internal WireType WireType => wireType;
|
||||
|
||||
public SerializationContext Context => context;
|
||||
|
||||
public TypeModel Model => model;
|
||||
|
||||
public static void WriteObject(object value, int key, ProtoWriter writer)
|
||||
{
|
||||
if (writer == null)
|
||||
{
|
||||
throw new ArgumentNullException("writer");
|
||||
}
|
||||
if (writer.model == null)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot serialize sub-objects unless a model is provided");
|
||||
}
|
||||
SubItemToken token = StartSubItem(value, writer);
|
||||
if (key >= 0)
|
||||
{
|
||||
writer.model.Serialize(key, value, writer);
|
||||
}
|
||||
else if (writer.model == null || !writer.model.TrySerializeAuxiliaryType(writer, value.GetType(), DataFormat.Default, 1, value, isInsideList: false, null))
|
||||
{
|
||||
TypeModel.ThrowUnexpectedType(value.GetType());
|
||||
}
|
||||
EndSubItem(token, writer);
|
||||
}
|
||||
|
||||
public static void WriteRecursionSafeObject(object value, int key, ProtoWriter writer)
|
||||
{
|
||||
if (writer == null)
|
||||
{
|
||||
throw new ArgumentNullException("writer");
|
||||
}
|
||||
if (writer.model == null)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot serialize sub-objects unless a model is provided");
|
||||
}
|
||||
SubItemToken token = StartSubItem(null, writer);
|
||||
writer.model.Serialize(key, value, writer);
|
||||
EndSubItem(token, writer);
|
||||
}
|
||||
|
||||
internal static void WriteObject(object value, int key, ProtoWriter writer, PrefixStyle style, int fieldNumber)
|
||||
{
|
||||
if (writer.model == null)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot serialize sub-objects unless a model is provided");
|
||||
}
|
||||
if (writer.wireType != WireType.None)
|
||||
{
|
||||
throw CreateException(writer);
|
||||
}
|
||||
switch (style)
|
||||
{
|
||||
case PrefixStyle.Base128:
|
||||
writer.wireType = WireType.String;
|
||||
writer.fieldNumber = fieldNumber;
|
||||
if (fieldNumber > 0)
|
||||
{
|
||||
WriteHeaderCore(fieldNumber, WireType.String, writer);
|
||||
}
|
||||
break;
|
||||
case PrefixStyle.Fixed32:
|
||||
case PrefixStyle.Fixed32BigEndian:
|
||||
writer.fieldNumber = 0;
|
||||
writer.wireType = WireType.Fixed32;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("style");
|
||||
}
|
||||
SubItemToken token = StartSubItem(value, writer, allowFixed: true);
|
||||
if (key < 0)
|
||||
{
|
||||
if (!writer.model.TrySerializeAuxiliaryType(writer, value.GetType(), DataFormat.Default, 1, value, isInsideList: false, null))
|
||||
{
|
||||
TypeModel.ThrowUnexpectedType(value.GetType());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.model.Serialize(key, value, writer);
|
||||
}
|
||||
EndSubItem(token, writer, style);
|
||||
}
|
||||
|
||||
internal int GetTypeKey(ref Type type)
|
||||
{
|
||||
return model.GetKey(ref type);
|
||||
}
|
||||
|
||||
public static void WriteFieldHeader(int fieldNumber, WireType wireType, ProtoWriter writer)
|
||||
{
|
||||
if (writer == null)
|
||||
{
|
||||
throw new ArgumentNullException("writer");
|
||||
}
|
||||
if (writer.wireType != WireType.None)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot write a " + wireType.ToString() + " header until the " + writer.wireType.ToString() + " data has been written");
|
||||
}
|
||||
if (fieldNumber < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("fieldNumber");
|
||||
}
|
||||
if (writer.packedFieldNumber == 0)
|
||||
{
|
||||
writer.fieldNumber = fieldNumber;
|
||||
writer.wireType = wireType;
|
||||
WriteHeaderCore(fieldNumber, wireType, writer);
|
||||
return;
|
||||
}
|
||||
if (writer.packedFieldNumber == fieldNumber)
|
||||
{
|
||||
if ((uint)wireType > 1u && wireType != WireType.Fixed32 && wireType != WireType.SignedVariant)
|
||||
{
|
||||
throw new InvalidOperationException("Wire-type cannot be encoded as packed: " + wireType);
|
||||
}
|
||||
writer.fieldNumber = fieldNumber;
|
||||
writer.wireType = wireType;
|
||||
return;
|
||||
}
|
||||
throw new InvalidOperationException("Field mismatch during packed encoding; expected " + writer.packedFieldNumber + " but received " + fieldNumber);
|
||||
}
|
||||
|
||||
internal static void WriteHeaderCore(int fieldNumber, WireType wireType, ProtoWriter writer)
|
||||
{
|
||||
uint value = (uint)(fieldNumber << 3) | (uint)(wireType & (WireType)7);
|
||||
WriteUInt32Variant(value, writer);
|
||||
}
|
||||
|
||||
public static void WriteBytes(byte[] data, ProtoWriter writer)
|
||||
{
|
||||
if (data == null)
|
||||
{
|
||||
throw new ArgumentNullException("data");
|
||||
}
|
||||
WriteBytes(data, 0, data.Length, writer);
|
||||
}
|
||||
|
||||
public static void WriteBytes(byte[] data, int offset, int length, ProtoWriter writer)
|
||||
{
|
||||
if (data == null)
|
||||
{
|
||||
throw new ArgumentNullException("data");
|
||||
}
|
||||
if (writer == null)
|
||||
{
|
||||
throw new ArgumentNullException("writer");
|
||||
}
|
||||
switch (writer.wireType)
|
||||
{
|
||||
case WireType.Fixed32:
|
||||
if (length != 4)
|
||||
{
|
||||
throw new ArgumentException("length");
|
||||
}
|
||||
break;
|
||||
case WireType.Fixed64:
|
||||
if (length != 8)
|
||||
{
|
||||
throw new ArgumentException("length");
|
||||
}
|
||||
break;
|
||||
case WireType.String:
|
||||
WriteUInt32Variant((uint)length, writer);
|
||||
writer.wireType = WireType.None;
|
||||
if (length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (writer.flushLock == 0 && length > writer.ioBuffer.Length)
|
||||
{
|
||||
Flush(writer);
|
||||
writer.dest.Write(data, offset, length);
|
||||
writer.position64 += length;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw CreateException(writer);
|
||||
}
|
||||
DemandSpace(length, writer);
|
||||
Buffer.BlockCopy(data, offset, writer.ioBuffer, writer.ioIndex, length);
|
||||
IncrementedAndReset(length, writer);
|
||||
}
|
||||
|
||||
private static void CopyRawFromStream(Stream source, ProtoWriter writer)
|
||||
{
|
||||
byte[] array = writer.ioBuffer;
|
||||
int num = array.Length - writer.ioIndex;
|
||||
int num2 = 1;
|
||||
while (num > 0 && (num2 = source.Read(array, writer.ioIndex, num)) > 0)
|
||||
{
|
||||
writer.ioIndex += num2;
|
||||
writer.position64 += num2;
|
||||
num -= num2;
|
||||
}
|
||||
if (num2 <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (writer.flushLock == 0)
|
||||
{
|
||||
Flush(writer);
|
||||
while ((num2 = source.Read(array, 0, array.Length)) > 0)
|
||||
{
|
||||
writer.dest.Write(array, 0, num2);
|
||||
writer.position64 += num2;
|
||||
}
|
||||
return;
|
||||
}
|
||||
while (true)
|
||||
{
|
||||
DemandSpace(128, writer);
|
||||
if ((num2 = source.Read(writer.ioBuffer, writer.ioIndex, writer.ioBuffer.Length - writer.ioIndex)) > 0)
|
||||
{
|
||||
writer.position64 += num2;
|
||||
writer.ioIndex += num2;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void IncrementedAndReset(int length, ProtoWriter writer)
|
||||
{
|
||||
writer.ioIndex += length;
|
||||
writer.position64 += length;
|
||||
writer.wireType = WireType.None;
|
||||
}
|
||||
|
||||
public static SubItemToken StartSubItem(object instance, ProtoWriter writer)
|
||||
{
|
||||
return StartSubItem(instance, writer, allowFixed: false);
|
||||
}
|
||||
|
||||
private void CheckRecursionStackAndPush(object instance)
|
||||
{
|
||||
int num;
|
||||
if (recursionStack == null)
|
||||
{
|
||||
recursionStack = new MutableList();
|
||||
}
|
||||
else if (instance != null && (num = recursionStack.IndexOfReference(instance)) >= 0)
|
||||
{
|
||||
throw new ProtoException("Possible recursion detected (offset: " + (recursionStack.Count - num) + " level(s)): " + instance.ToString());
|
||||
}
|
||||
recursionStack.Add(instance);
|
||||
}
|
||||
|
||||
private void PopRecursionStack()
|
||||
{
|
||||
recursionStack.RemoveLast();
|
||||
}
|
||||
|
||||
private static SubItemToken StartSubItem(object instance, ProtoWriter writer, bool allowFixed)
|
||||
{
|
||||
if (writer == null)
|
||||
{
|
||||
throw new ArgumentNullException("writer");
|
||||
}
|
||||
if (++writer.depth > 25)
|
||||
{
|
||||
writer.CheckRecursionStackAndPush(instance);
|
||||
}
|
||||
if (writer.packedFieldNumber != 0)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot begin a sub-item while performing packed encoding");
|
||||
}
|
||||
switch (writer.wireType)
|
||||
{
|
||||
case WireType.StartGroup:
|
||||
writer.wireType = WireType.None;
|
||||
return new SubItemToken((long)(-writer.fieldNumber));
|
||||
case WireType.String:
|
||||
writer.wireType = WireType.None;
|
||||
DemandSpace(32, writer);
|
||||
writer.flushLock++;
|
||||
writer.position64++;
|
||||
return new SubItemToken((long)writer.ioIndex++);
|
||||
case WireType.Fixed32:
|
||||
{
|
||||
if (!allowFixed)
|
||||
{
|
||||
throw CreateException(writer);
|
||||
}
|
||||
DemandSpace(32, writer);
|
||||
writer.flushLock++;
|
||||
SubItemToken result = new SubItemToken((long)writer.ioIndex);
|
||||
IncrementedAndReset(4, writer);
|
||||
return result;
|
||||
}
|
||||
default:
|
||||
throw CreateException(writer);
|
||||
}
|
||||
}
|
||||
|
||||
public static void EndSubItem(SubItemToken token, ProtoWriter writer)
|
||||
{
|
||||
EndSubItem(token, writer, PrefixStyle.Base128);
|
||||
}
|
||||
|
||||
private static void EndSubItem(SubItemToken token, ProtoWriter writer, PrefixStyle style)
|
||||
{
|
||||
if (writer == null)
|
||||
{
|
||||
throw new ArgumentNullException("writer");
|
||||
}
|
||||
if (writer.wireType != WireType.None)
|
||||
{
|
||||
throw CreateException(writer);
|
||||
}
|
||||
int num = (int)token.value64;
|
||||
if (writer.depth <= 0)
|
||||
{
|
||||
throw CreateException(writer);
|
||||
}
|
||||
if (writer.depth-- > 25)
|
||||
{
|
||||
writer.PopRecursionStack();
|
||||
}
|
||||
writer.packedFieldNumber = 0;
|
||||
if (num < 0)
|
||||
{
|
||||
WriteHeaderCore(-num, WireType.EndGroup, writer);
|
||||
writer.wireType = WireType.None;
|
||||
return;
|
||||
}
|
||||
switch (style)
|
||||
{
|
||||
case PrefixStyle.Fixed32:
|
||||
{
|
||||
int num2 = writer.ioIndex - num - 4;
|
||||
WriteInt32ToBuffer(num2, writer.ioBuffer, num);
|
||||
break;
|
||||
}
|
||||
case PrefixStyle.Fixed32BigEndian:
|
||||
{
|
||||
int num2 = writer.ioIndex - num - 4;
|
||||
byte[] array2 = writer.ioBuffer;
|
||||
WriteInt32ToBuffer(num2, array2, num);
|
||||
byte b = array2[num];
|
||||
array2[num] = array2[num + 3];
|
||||
array2[num + 3] = b;
|
||||
b = array2[num + 1];
|
||||
array2[num + 1] = array2[num + 2];
|
||||
array2[num + 2] = b;
|
||||
break;
|
||||
}
|
||||
case PrefixStyle.Base128:
|
||||
{
|
||||
int num2 = writer.ioIndex - num - 1;
|
||||
int num3 = 0;
|
||||
uint num4 = (uint)num2;
|
||||
while ((num4 >>= 7) != 0)
|
||||
{
|
||||
num3++;
|
||||
}
|
||||
if (num3 == 0)
|
||||
{
|
||||
writer.ioBuffer[num] = (byte)(num2 & 0x7F);
|
||||
break;
|
||||
}
|
||||
DemandSpace(num3, writer);
|
||||
byte[] array = writer.ioBuffer;
|
||||
Buffer.BlockCopy(array, num + 1, array, num + 1 + num3, num2);
|
||||
num4 = (uint)num2;
|
||||
do
|
||||
{
|
||||
array[num++] = (byte)((num4 & 0x7F) | 0x80);
|
||||
}
|
||||
while ((num4 >>= 7) != 0);
|
||||
array[num - 1] = (byte)(array[num - 1] & -129);
|
||||
writer.position64 += num3;
|
||||
writer.ioIndex += num3;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("style");
|
||||
}
|
||||
if (--writer.flushLock == 0 && writer.ioIndex >= 1024)
|
||||
{
|
||||
Flush(writer);
|
||||
}
|
||||
}
|
||||
|
||||
public static ProtoWriter Create(Stream dest, TypeModel model, SerializationContext context = null)
|
||||
{
|
||||
return new ProtoWriter(dest, model, context);
|
||||
}
|
||||
|
||||
[Obsolete("Please use ProtoWriter.Create; this API may be removed in a future version", false)]
|
||||
public ProtoWriter(Stream dest, TypeModel model, SerializationContext context)
|
||||
{
|
||||
if (dest == null)
|
||||
{
|
||||
throw new ArgumentNullException("dest");
|
||||
}
|
||||
if (!dest.CanWrite)
|
||||
{
|
||||
throw new ArgumentException("Cannot write to stream", "dest");
|
||||
}
|
||||
this.dest = dest;
|
||||
ioBuffer = BufferPool.GetBuffer();
|
||||
this.model = model;
|
||||
wireType = WireType.None;
|
||||
if (context == null)
|
||||
{
|
||||
context = SerializationContext.Default;
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Freeze();
|
||||
}
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
private void Dispose()
|
||||
{
|
||||
if (dest != null)
|
||||
{
|
||||
Flush(this);
|
||||
dest = null;
|
||||
}
|
||||
model = null;
|
||||
BufferPool.ReleaseBufferToPool(ref ioBuffer);
|
||||
}
|
||||
|
||||
internal static long GetLongPosition(ProtoWriter writer)
|
||||
{
|
||||
return writer.position64;
|
||||
}
|
||||
|
||||
internal static int GetPosition(ProtoWriter writer)
|
||||
{
|
||||
return checked((int)writer.position64);
|
||||
}
|
||||
|
||||
private static void DemandSpace(int required, ProtoWriter writer)
|
||||
{
|
||||
if (writer.ioBuffer.Length - writer.ioIndex < required)
|
||||
{
|
||||
TryFlushOrResize(required, writer);
|
||||
}
|
||||
}
|
||||
|
||||
private static void TryFlushOrResize(int required, ProtoWriter writer)
|
||||
{
|
||||
if (writer.flushLock == 0)
|
||||
{
|
||||
Flush(writer);
|
||||
if (writer.ioBuffer.Length - writer.ioIndex >= required)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
BufferPool.ResizeAndFlushLeft(ref writer.ioBuffer, required + writer.ioIndex, 0, writer.ioIndex);
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
if (depth != 0 || flushLock != 0)
|
||||
{
|
||||
throw new InvalidOperationException("Unable to close stream in an incomplete state");
|
||||
}
|
||||
Dispose();
|
||||
}
|
||||
|
||||
internal void CheckDepthFlushlock()
|
||||
{
|
||||
if (depth != 0 || flushLock != 0)
|
||||
{
|
||||
throw new InvalidOperationException("The writer is in an incomplete state");
|
||||
}
|
||||
}
|
||||
|
||||
internal static void Flush(ProtoWriter writer)
|
||||
{
|
||||
if (writer.flushLock == 0 && writer.ioIndex != 0)
|
||||
{
|
||||
writer.dest.Write(writer.ioBuffer, 0, writer.ioIndex);
|
||||
writer.ioIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private static void WriteUInt32Variant(uint value, ProtoWriter writer)
|
||||
{
|
||||
DemandSpace(5, writer);
|
||||
int num = 0;
|
||||
do
|
||||
{
|
||||
writer.ioBuffer[writer.ioIndex++] = (byte)((value & 0x7F) | 0x80);
|
||||
num++;
|
||||
}
|
||||
while ((value >>= 7) != 0);
|
||||
writer.ioBuffer[writer.ioIndex - 1] &= 127;
|
||||
writer.position64 += num;
|
||||
}
|
||||
|
||||
internal static uint Zig(int value)
|
||||
{
|
||||
return (uint)((value << 1) ^ (value >> 31));
|
||||
}
|
||||
|
||||
internal static ulong Zig(long value)
|
||||
{
|
||||
return (ulong)((value << 1) ^ (value >> 63));
|
||||
}
|
||||
|
||||
private static void WriteUInt64Variant(ulong value, ProtoWriter writer)
|
||||
{
|
||||
DemandSpace(10, writer);
|
||||
int num = 0;
|
||||
do
|
||||
{
|
||||
writer.ioBuffer[writer.ioIndex++] = (byte)((value & 0x7F) | 0x80);
|
||||
num++;
|
||||
}
|
||||
while ((value >>= 7) != 0L);
|
||||
writer.ioBuffer[writer.ioIndex - 1] &= 127;
|
||||
writer.position64 += num;
|
||||
}
|
||||
|
||||
public static void WriteString(string value, ProtoWriter writer)
|
||||
{
|
||||
if (writer == null)
|
||||
{
|
||||
throw new ArgumentNullException("writer");
|
||||
}
|
||||
if (writer.wireType != WireType.String)
|
||||
{
|
||||
throw CreateException(writer);
|
||||
}
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentNullException("value");
|
||||
}
|
||||
if (value.Length == 0)
|
||||
{
|
||||
WriteUInt32Variant(0u, writer);
|
||||
writer.wireType = WireType.None;
|
||||
return;
|
||||
}
|
||||
int byteCount = encoding.GetByteCount(value);
|
||||
WriteUInt32Variant((uint)byteCount, writer);
|
||||
DemandSpace(byteCount, writer);
|
||||
int bytes = encoding.GetBytes(value, 0, value.Length, writer.ioBuffer, writer.ioIndex);
|
||||
IncrementedAndReset(bytes, writer);
|
||||
}
|
||||
|
||||
public static void WriteUInt64(ulong value, ProtoWriter writer)
|
||||
{
|
||||
if (writer == null)
|
||||
{
|
||||
throw new ArgumentNullException("writer");
|
||||
}
|
||||
switch (writer.wireType)
|
||||
{
|
||||
case WireType.Fixed64:
|
||||
WriteInt64((long)value, writer);
|
||||
break;
|
||||
case WireType.Variant:
|
||||
WriteUInt64Variant(value, writer);
|
||||
writer.wireType = WireType.None;
|
||||
break;
|
||||
case WireType.Fixed32:
|
||||
WriteUInt32(checked((uint)value), writer);
|
||||
break;
|
||||
default:
|
||||
throw CreateException(writer);
|
||||
}
|
||||
}
|
||||
|
||||
public static void WriteInt64(long value, ProtoWriter writer)
|
||||
{
|
||||
if (writer == null)
|
||||
{
|
||||
throw new ArgumentNullException("writer");
|
||||
}
|
||||
switch (writer.wireType)
|
||||
{
|
||||
case WireType.Fixed64:
|
||||
{
|
||||
DemandSpace(8, writer);
|
||||
byte[] array = writer.ioBuffer;
|
||||
int num = writer.ioIndex;
|
||||
array[num] = (byte)value;
|
||||
array[num + 1] = (byte)(value >> 8);
|
||||
array[num + 2] = (byte)(value >> 16);
|
||||
array[num + 3] = (byte)(value >> 24);
|
||||
array[num + 4] = (byte)(value >> 32);
|
||||
array[num + 5] = (byte)(value >> 40);
|
||||
array[num + 6] = (byte)(value >> 48);
|
||||
array[num + 7] = (byte)(value >> 56);
|
||||
IncrementedAndReset(8, writer);
|
||||
break;
|
||||
}
|
||||
case WireType.SignedVariant:
|
||||
WriteUInt64Variant(Zig(value), writer);
|
||||
writer.wireType = WireType.None;
|
||||
break;
|
||||
case WireType.Variant:
|
||||
{
|
||||
if (value >= 0)
|
||||
{
|
||||
WriteUInt64Variant((ulong)value, writer);
|
||||
writer.wireType = WireType.None;
|
||||
break;
|
||||
}
|
||||
DemandSpace(10, writer);
|
||||
byte[] array = writer.ioBuffer;
|
||||
int num = writer.ioIndex;
|
||||
array[num] = (byte)(value | 0x80);
|
||||
array[num + 1] = (byte)((int)(value >> 7) | 0x80);
|
||||
array[num + 2] = (byte)((int)(value >> 14) | 0x80);
|
||||
array[num + 3] = (byte)((int)(value >> 21) | 0x80);
|
||||
array[num + 4] = (byte)((int)(value >> 28) | 0x80);
|
||||
array[num + 5] = (byte)((int)(value >> 35) | 0x80);
|
||||
array[num + 6] = (byte)((int)(value >> 42) | 0x80);
|
||||
array[num + 7] = (byte)((int)(value >> 49) | 0x80);
|
||||
array[num + 8] = (byte)((int)(value >> 56) | 0x80);
|
||||
array[num + 9] = 1;
|
||||
IncrementedAndReset(10, writer);
|
||||
break;
|
||||
}
|
||||
case WireType.Fixed32:
|
||||
WriteInt32(checked((int)value), writer);
|
||||
break;
|
||||
default:
|
||||
throw CreateException(writer);
|
||||
}
|
||||
}
|
||||
|
||||
public static void WriteUInt32(uint value, ProtoWriter writer)
|
||||
{
|
||||
if (writer == null)
|
||||
{
|
||||
throw new ArgumentNullException("writer");
|
||||
}
|
||||
switch (writer.wireType)
|
||||
{
|
||||
case WireType.Fixed32:
|
||||
WriteInt32((int)value, writer);
|
||||
break;
|
||||
case WireType.Fixed64:
|
||||
WriteInt64((int)value, writer);
|
||||
break;
|
||||
case WireType.Variant:
|
||||
WriteUInt32Variant(value, writer);
|
||||
writer.wireType = WireType.None;
|
||||
break;
|
||||
default:
|
||||
throw CreateException(writer);
|
||||
}
|
||||
}
|
||||
|
||||
public static void WriteInt16(short value, ProtoWriter writer)
|
||||
{
|
||||
WriteInt32(value, writer);
|
||||
}
|
||||
|
||||
public static void WriteUInt16(ushort value, ProtoWriter writer)
|
||||
{
|
||||
WriteUInt32(value, writer);
|
||||
}
|
||||
|
||||
public static void WriteByte(byte value, ProtoWriter writer)
|
||||
{
|
||||
WriteUInt32(value, writer);
|
||||
}
|
||||
|
||||
public static void WriteSByte(sbyte value, ProtoWriter writer)
|
||||
{
|
||||
WriteInt32(value, writer);
|
||||
}
|
||||
|
||||
private static void WriteInt32ToBuffer(int value, byte[] buffer, int index)
|
||||
{
|
||||
buffer[index] = (byte)value;
|
||||
buffer[index + 1] = (byte)(value >> 8);
|
||||
buffer[index + 2] = (byte)(value >> 16);
|
||||
buffer[index + 3] = (byte)(value >> 24);
|
||||
}
|
||||
|
||||
public static void WriteInt32(int value, ProtoWriter writer)
|
||||
{
|
||||
if (writer == null)
|
||||
{
|
||||
throw new ArgumentNullException("writer");
|
||||
}
|
||||
switch (writer.wireType)
|
||||
{
|
||||
case WireType.Fixed32:
|
||||
DemandSpace(4, writer);
|
||||
WriteInt32ToBuffer(value, writer.ioBuffer, writer.ioIndex);
|
||||
IncrementedAndReset(4, writer);
|
||||
break;
|
||||
case WireType.Fixed64:
|
||||
{
|
||||
DemandSpace(8, writer);
|
||||
byte[] array = writer.ioBuffer;
|
||||
int num = writer.ioIndex;
|
||||
array[num] = (byte)value;
|
||||
array[num + 1] = (byte)(value >> 8);
|
||||
array[num + 2] = (byte)(value >> 16);
|
||||
array[num + 3] = (byte)(value >> 24);
|
||||
array[num + 4] = (array[num + 5] = (array[num + 6] = (array[num + 7] = 0)));
|
||||
IncrementedAndReset(8, writer);
|
||||
break;
|
||||
}
|
||||
case WireType.SignedVariant:
|
||||
WriteUInt32Variant(Zig(value), writer);
|
||||
writer.wireType = WireType.None;
|
||||
break;
|
||||
case WireType.Variant:
|
||||
{
|
||||
if (value >= 0)
|
||||
{
|
||||
WriteUInt32Variant((uint)value, writer);
|
||||
writer.wireType = WireType.None;
|
||||
break;
|
||||
}
|
||||
DemandSpace(10, writer);
|
||||
byte[] array = writer.ioBuffer;
|
||||
int num = writer.ioIndex;
|
||||
array[num] = (byte)(value | 0x80);
|
||||
array[num + 1] = (byte)((value >> 7) | 0x80);
|
||||
array[num + 2] = (byte)((value >> 14) | 0x80);
|
||||
array[num + 3] = (byte)((value >> 21) | 0x80);
|
||||
array[num + 4] = (byte)((value >> 28) | 0x80);
|
||||
byte[] array2 = array;
|
||||
int num2 = num + 5;
|
||||
byte[] array3 = array;
|
||||
int num3 = num + 6;
|
||||
byte[] array4 = array;
|
||||
int num4 = num + 7;
|
||||
byte b;
|
||||
array[num + 8] = (b = byte.MaxValue);
|
||||
array2[num2] = (array3[num3] = (array4[num4] = b));
|
||||
array[num + 9] = 1;
|
||||
IncrementedAndReset(10, writer);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw CreateException(writer);
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe static void WriteDouble(double value, ProtoWriter writer)
|
||||
{
|
||||
if (writer == null)
|
||||
{
|
||||
throw new ArgumentNullException("writer");
|
||||
}
|
||||
switch (writer.wireType)
|
||||
{
|
||||
case WireType.Fixed32:
|
||||
{
|
||||
float num = (float)value;
|
||||
if (float.IsInfinity(num) && !double.IsInfinity(value))
|
||||
{
|
||||
throw new OverflowException();
|
||||
}
|
||||
WriteSingle(num, writer);
|
||||
break;
|
||||
}
|
||||
case WireType.Fixed64:
|
||||
WriteInt64(*(long*)(&value), writer);
|
||||
break;
|
||||
default:
|
||||
throw CreateException(writer);
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe static void WriteSingle(float value, ProtoWriter writer)
|
||||
{
|
||||
if (writer == null)
|
||||
{
|
||||
throw new ArgumentNullException("writer");
|
||||
}
|
||||
switch (writer.wireType)
|
||||
{
|
||||
case WireType.Fixed32:
|
||||
WriteInt32(*(int*)(&value), writer);
|
||||
break;
|
||||
case WireType.Fixed64:
|
||||
WriteDouble(value, writer);
|
||||
break;
|
||||
default:
|
||||
throw CreateException(writer);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ThrowEnumException(ProtoWriter writer, object enumValue)
|
||||
{
|
||||
if (writer == null)
|
||||
{
|
||||
throw new ArgumentNullException("writer");
|
||||
}
|
||||
string text = ((enumValue == null) ? "<null>" : (enumValue.GetType().FullName + "." + enumValue.ToString()));
|
||||
throw new ProtoException("No wire-value is mapped to the enum " + text + " at position " + writer.position64);
|
||||
}
|
||||
|
||||
internal static Exception CreateException(ProtoWriter writer)
|
||||
{
|
||||
if (writer == null)
|
||||
{
|
||||
throw new ArgumentNullException("writer");
|
||||
}
|
||||
return new ProtoException("Invalid serialization operation with wire-type " + writer.wireType.ToString() + " at position " + writer.position64);
|
||||
}
|
||||
|
||||
public static void WriteBoolean(bool value, ProtoWriter writer)
|
||||
{
|
||||
WriteUInt32(value ? 1u : 0u, writer);
|
||||
}
|
||||
|
||||
public static void AppendExtensionData(IExtensible instance, ProtoWriter writer)
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
throw new ArgumentNullException("instance");
|
||||
}
|
||||
if (writer == null)
|
||||
{
|
||||
throw new ArgumentNullException("writer");
|
||||
}
|
||||
if (writer.wireType != WireType.None)
|
||||
{
|
||||
throw CreateException(writer);
|
||||
}
|
||||
IExtension extensionObject = instance.GetExtensionObject(createIfMissing: false);
|
||||
if (extensionObject != null)
|
||||
{
|
||||
Stream stream = extensionObject.BeginQuery();
|
||||
try
|
||||
{
|
||||
CopyRawFromStream(stream, writer);
|
||||
}
|
||||
finally
|
||||
{
|
||||
extensionObject.EndQuery(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetPackedField(int fieldNumber, ProtoWriter writer)
|
||||
{
|
||||
if (fieldNumber <= 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("fieldNumber");
|
||||
}
|
||||
if (writer == null)
|
||||
{
|
||||
throw new ArgumentNullException("writer");
|
||||
}
|
||||
writer.packedFieldNumber = fieldNumber;
|
||||
}
|
||||
|
||||
public static void ClearPackedField(int fieldNumber, ProtoWriter writer)
|
||||
{
|
||||
if (fieldNumber != writer.packedFieldNumber)
|
||||
{
|
||||
throw new InvalidOperationException("Field mismatch during packed encoding; expected " + writer.packedFieldNumber + " but received " + fieldNumber);
|
||||
}
|
||||
writer.packedFieldNumber = 0;
|
||||
}
|
||||
|
||||
public static void WritePackedPrefix(int elementCount, WireType wireType, ProtoWriter writer)
|
||||
{
|
||||
if (writer.WireType != WireType.String)
|
||||
{
|
||||
throw new InvalidOperationException("Invalid wire-type: " + writer.WireType);
|
||||
}
|
||||
if (elementCount < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("elementCount");
|
||||
}
|
||||
WriteUInt64Variant(wireType switch
|
||||
{
|
||||
WireType.Fixed32 => (ulong)((long)elementCount << 2),
|
||||
WireType.Fixed64 => (ulong)((long)elementCount << 3),
|
||||
_ => throw new ArgumentOutOfRangeException("wireType", "Invalid wire-type: " + wireType),
|
||||
}, writer);
|
||||
writer.wireType = WireType.None;
|
||||
}
|
||||
|
||||
internal string SerializeType(Type type)
|
||||
{
|
||||
return TypeModel.SerializeType(model, type);
|
||||
}
|
||||
|
||||
public void SetRootObject(object value)
|
||||
{
|
||||
NetCache.SetKeyedObject(0, value);
|
||||
}
|
||||
|
||||
public static void WriteType(Type value, ProtoWriter writer)
|
||||
{
|
||||
if (writer == null)
|
||||
{
|
||||
throw new ArgumentNullException("writer");
|
||||
}
|
||||
WriteString(writer.SerializeType(value), writer);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
public sealed class SerializationContext
|
||||
{
|
||||
private bool frozen;
|
||||
|
||||
private object context;
|
||||
|
||||
private static readonly SerializationContext @default;
|
||||
|
||||
private StreamingContextStates state = StreamingContextStates.Persistence;
|
||||
|
||||
public object Context
|
||||
{
|
||||
get
|
||||
{
|
||||
return context;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (context != value)
|
||||
{
|
||||
ThrowIfFrozen();
|
||||
context = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static SerializationContext Default => @default;
|
||||
|
||||
public StreamingContextStates State
|
||||
{
|
||||
get
|
||||
{
|
||||
return state;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (state != value)
|
||||
{
|
||||
ThrowIfFrozen();
|
||||
state = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void Freeze()
|
||||
{
|
||||
frozen = true;
|
||||
}
|
||||
|
||||
private void ThrowIfFrozen()
|
||||
{
|
||||
if (frozen)
|
||||
{
|
||||
throw new InvalidOperationException("The serialization-context cannot be changed once it is in use");
|
||||
}
|
||||
}
|
||||
|
||||
static SerializationContext()
|
||||
{
|
||||
@default = new SerializationContext();
|
||||
@default.Freeze();
|
||||
}
|
||||
|
||||
public static implicit operator StreamingContext(SerializationContext ctx)
|
||||
{
|
||||
if (ctx == null)
|
||||
{
|
||||
return new StreamingContext(StreamingContextStates.Persistence);
|
||||
}
|
||||
return new StreamingContext(ctx.state, ctx.context);
|
||||
}
|
||||
|
||||
public static implicit operator SerializationContext(StreamingContext ctx)
|
||||
{
|
||||
SerializationContext serializationContext = new SerializationContext();
|
||||
serializationContext.Context = ctx.Context;
|
||||
serializationContext.State = ctx.State;
|
||||
return serializationContext;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,306 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
using ProtoBuf.Meta;
|
||||
|
||||
namespace ProtoBuf;
|
||||
|
||||
public static class Serializer
|
||||
{
|
||||
public static class NonGeneric
|
||||
{
|
||||
public static object DeepClone(object instance)
|
||||
{
|
||||
if (instance != null)
|
||||
{
|
||||
return RuntimeTypeModel.Default.DeepClone(instance);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void Serialize(Stream dest, object instance)
|
||||
{
|
||||
if (instance != null)
|
||||
{
|
||||
RuntimeTypeModel.Default.Serialize(dest, instance);
|
||||
}
|
||||
}
|
||||
|
||||
public static object Deserialize(Type type, Stream source)
|
||||
{
|
||||
return RuntimeTypeModel.Default.Deserialize(source, null, type);
|
||||
}
|
||||
|
||||
public static object Merge(Stream source, object instance)
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
throw new ArgumentNullException("instance");
|
||||
}
|
||||
return RuntimeTypeModel.Default.Deserialize(source, instance, instance.GetType(), null);
|
||||
}
|
||||
|
||||
public static void SerializeWithLengthPrefix(Stream destination, object instance, PrefixStyle style, int fieldNumber)
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
throw new ArgumentNullException("instance");
|
||||
}
|
||||
RuntimeTypeModel runtimeTypeModel = RuntimeTypeModel.Default;
|
||||
runtimeTypeModel.SerializeWithLengthPrefix(destination, instance, runtimeTypeModel.MapType(instance.GetType()), style, fieldNumber);
|
||||
}
|
||||
|
||||
public static bool TryDeserializeWithLengthPrefix(Stream source, PrefixStyle style, TypeResolver resolver, out object value)
|
||||
{
|
||||
value = RuntimeTypeModel.Default.DeserializeWithLengthPrefix(source, null, null, style, 0, resolver);
|
||||
return value != null;
|
||||
}
|
||||
|
||||
public static bool CanSerialize(Type type)
|
||||
{
|
||||
return RuntimeTypeModel.Default.IsDefined(type);
|
||||
}
|
||||
|
||||
public static void PrepareSerializer(Type t)
|
||||
{
|
||||
RuntimeTypeModel runtimeTypeModel = RuntimeTypeModel.Default;
|
||||
runtimeTypeModel[runtimeTypeModel.MapType(t)].CompileInPlace();
|
||||
}
|
||||
}
|
||||
|
||||
public static class GlobalOptions
|
||||
{
|
||||
[Obsolete("Please use RuntimeTypeModel.Default.InferTagFromNameDefault instead (or on a per-model basis)", false)]
|
||||
public static bool InferTagFromName
|
||||
{
|
||||
get
|
||||
{
|
||||
return RuntimeTypeModel.Default.InferTagFromNameDefault;
|
||||
}
|
||||
set
|
||||
{
|
||||
RuntimeTypeModel.Default.InferTagFromNameDefault = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public delegate Type TypeResolver(int fieldNumber);
|
||||
|
||||
private const string ProtoBinaryField = "proto";
|
||||
|
||||
public const int ListItemTag = 1;
|
||||
|
||||
public static string GetProto<T>()
|
||||
{
|
||||
return GetProto<T>(ProtoSyntax.Proto2);
|
||||
}
|
||||
|
||||
public static string GetProto<T>(ProtoSyntax syntax)
|
||||
{
|
||||
return RuntimeTypeModel.Default.GetSchema(RuntimeTypeModel.Default.MapType(typeof(T)), syntax);
|
||||
}
|
||||
|
||||
public static T DeepClone<T>(T instance)
|
||||
{
|
||||
if (instance != null)
|
||||
{
|
||||
return (T)RuntimeTypeModel.Default.DeepClone(instance);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static T Merge<T>(Stream source, T instance)
|
||||
{
|
||||
return (T)RuntimeTypeModel.Default.Deserialize(source, instance, typeof(T));
|
||||
}
|
||||
|
||||
public static T Deserialize<T>(Stream source)
|
||||
{
|
||||
return (T)RuntimeTypeModel.Default.Deserialize(source, null, typeof(T));
|
||||
}
|
||||
|
||||
public static object Deserialize(Type type, Stream source)
|
||||
{
|
||||
return RuntimeTypeModel.Default.Deserialize(source, null, type);
|
||||
}
|
||||
|
||||
public static void Serialize<T>(Stream destination, T instance)
|
||||
{
|
||||
if (instance != null)
|
||||
{
|
||||
RuntimeTypeModel.Default.Serialize(destination, instance);
|
||||
}
|
||||
}
|
||||
|
||||
public static TTo ChangeType<TFrom, TTo>(TFrom instance)
|
||||
{
|
||||
using MemoryStream memoryStream = new MemoryStream();
|
||||
Serialize((Stream)memoryStream, instance);
|
||||
memoryStream.Position = 0L;
|
||||
return Deserialize<TTo>(memoryStream);
|
||||
}
|
||||
|
||||
public static void Serialize<T>(SerializationInfo info, T instance) where T : class, ISerializable
|
||||
{
|
||||
Serialize(info, new StreamingContext(StreamingContextStates.Persistence), instance);
|
||||
}
|
||||
|
||||
public static void Serialize<T>(SerializationInfo info, StreamingContext context, T instance) where T : class, ISerializable
|
||||
{
|
||||
if (info == null)
|
||||
{
|
||||
throw new ArgumentNullException("info");
|
||||
}
|
||||
if (instance == null)
|
||||
{
|
||||
throw new ArgumentNullException("instance");
|
||||
}
|
||||
if ((object)instance.GetType() != typeof(T))
|
||||
{
|
||||
throw new ArgumentException("Incorrect type", "instance");
|
||||
}
|
||||
using MemoryStream memoryStream = new MemoryStream();
|
||||
RuntimeTypeModel.Default.Serialize(memoryStream, instance, context);
|
||||
info.AddValue("proto", memoryStream.ToArray());
|
||||
}
|
||||
|
||||
public static void Serialize<T>(XmlWriter writer, T instance) where T : IXmlSerializable
|
||||
{
|
||||
if (writer == null)
|
||||
{
|
||||
throw new ArgumentNullException("writer");
|
||||
}
|
||||
if (instance == null)
|
||||
{
|
||||
throw new ArgumentNullException("instance");
|
||||
}
|
||||
using MemoryStream memoryStream = new MemoryStream();
|
||||
Serialize((Stream)memoryStream, instance);
|
||||
writer.WriteBase64(Helpers.GetBuffer(memoryStream), 0, (int)memoryStream.Length);
|
||||
}
|
||||
|
||||
public static void Merge<T>(XmlReader reader, T instance) where T : IXmlSerializable
|
||||
{
|
||||
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_004b: Invalid comparison between Unknown and I4
|
||||
if (reader == null)
|
||||
{
|
||||
throw new ArgumentNullException("reader");
|
||||
}
|
||||
if (instance == null)
|
||||
{
|
||||
throw new ArgumentNullException("instance");
|
||||
}
|
||||
byte[] array = new byte[4096];
|
||||
using MemoryStream memoryStream = new MemoryStream();
|
||||
int depth = reader.Depth;
|
||||
while (reader.Read() && reader.Depth > depth)
|
||||
{
|
||||
if ((int)reader.NodeType == 3)
|
||||
{
|
||||
int count;
|
||||
while ((count = reader.ReadContentAsBase64(array, 0, 4096)) > 0)
|
||||
{
|
||||
memoryStream.Write(array, 0, count);
|
||||
}
|
||||
if (reader.Depth <= depth)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
memoryStream.Position = 0L;
|
||||
Merge((Stream)memoryStream, instance);
|
||||
}
|
||||
|
||||
public static void Merge<T>(SerializationInfo info, T instance) where T : class, ISerializable
|
||||
{
|
||||
Merge(info, new StreamingContext(StreamingContextStates.Persistence), instance);
|
||||
}
|
||||
|
||||
public static void Merge<T>(SerializationInfo info, StreamingContext context, T instance) where T : class, ISerializable
|
||||
{
|
||||
if (info == null)
|
||||
{
|
||||
throw new ArgumentNullException("info");
|
||||
}
|
||||
if (instance == null)
|
||||
{
|
||||
throw new ArgumentNullException("instance");
|
||||
}
|
||||
if ((object)instance.GetType() != typeof(T))
|
||||
{
|
||||
throw new ArgumentException("Incorrect type", "instance");
|
||||
}
|
||||
byte[] buffer = (byte[])info.GetValue("proto", typeof(byte[]));
|
||||
using MemoryStream source = new MemoryStream(buffer);
|
||||
T val = (T)RuntimeTypeModel.Default.Deserialize(source, instance, typeof(T), context);
|
||||
if (val != instance)
|
||||
{
|
||||
throw new ProtoException("Deserialization changed the instance; cannot succeed.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void PrepareSerializer<T>()
|
||||
{
|
||||
NonGeneric.PrepareSerializer(typeof(T));
|
||||
}
|
||||
|
||||
public static IFormatter CreateFormatter<T>()
|
||||
{
|
||||
return RuntimeTypeModel.Default.CreateFormatter(typeof(T));
|
||||
}
|
||||
|
||||
public static IEnumerable<T> DeserializeItems<T>(Stream source, PrefixStyle style, int fieldNumber)
|
||||
{
|
||||
return RuntimeTypeModel.Default.DeserializeItems<T>(source, style, fieldNumber);
|
||||
}
|
||||
|
||||
public static T DeserializeWithLengthPrefix<T>(Stream source, PrefixStyle style)
|
||||
{
|
||||
return DeserializeWithLengthPrefix<T>(source, style, 0);
|
||||
}
|
||||
|
||||
public static T DeserializeWithLengthPrefix<T>(Stream source, PrefixStyle style, int fieldNumber)
|
||||
{
|
||||
RuntimeTypeModel runtimeTypeModel = RuntimeTypeModel.Default;
|
||||
return (T)runtimeTypeModel.DeserializeWithLengthPrefix(source, null, runtimeTypeModel.MapType(typeof(T)), style, fieldNumber);
|
||||
}
|
||||
|
||||
public static T MergeWithLengthPrefix<T>(Stream source, T instance, PrefixStyle style)
|
||||
{
|
||||
RuntimeTypeModel runtimeTypeModel = RuntimeTypeModel.Default;
|
||||
return (T)runtimeTypeModel.DeserializeWithLengthPrefix(source, instance, runtimeTypeModel.MapType(typeof(T)), style, 0);
|
||||
}
|
||||
|
||||
public static void SerializeWithLengthPrefix<T>(Stream destination, T instance, PrefixStyle style)
|
||||
{
|
||||
SerializeWithLengthPrefix(destination, instance, style, 0);
|
||||
}
|
||||
|
||||
public static void SerializeWithLengthPrefix<T>(Stream destination, T instance, PrefixStyle style, int fieldNumber)
|
||||
{
|
||||
RuntimeTypeModel runtimeTypeModel = RuntimeTypeModel.Default;
|
||||
runtimeTypeModel.SerializeWithLengthPrefix(destination, instance, runtimeTypeModel.MapType(typeof(T)), style, fieldNumber);
|
||||
}
|
||||
|
||||
public static bool TryReadLengthPrefix(Stream source, PrefixStyle style, out int length)
|
||||
{
|
||||
length = ProtoReader.ReadLengthPrefix(source, expectHeader: false, style, out var _, out var bytesRead);
|
||||
return bytesRead > 0;
|
||||
}
|
||||
|
||||
public static bool TryReadLengthPrefix(byte[] buffer, int index, int count, PrefixStyle style, out int length)
|
||||
{
|
||||
using Stream source = new MemoryStream(buffer, index, count);
|
||||
return TryReadLengthPrefix(source, style, out length);
|
||||
}
|
||||
|
||||
public static void FlushPool()
|
||||
{
|
||||
BufferPool.Flush();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace ProtoBuf;
|
||||
|
||||
public readonly struct SubItemToken
|
||||
{
|
||||
internal readonly long value64;
|
||||
|
||||
internal SubItemToken(int value)
|
||||
{
|
||||
value64 = value;
|
||||
}
|
||||
|
||||
internal SubItemToken(long value)
|
||||
{
|
||||
value64 = value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace ProtoBuf;
|
||||
|
||||
internal enum TimeSpanScale
|
||||
{
|
||||
Days = 0,
|
||||
Hours = 1,
|
||||
Minutes = 2,
|
||||
Seconds = 3,
|
||||
Milliseconds = 4,
|
||||
Ticks = 5,
|
||||
MinMax = 15
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace ProtoBuf;
|
||||
|
||||
public enum WireType
|
||||
{
|
||||
None = -1,
|
||||
Variant = 0,
|
||||
Fixed64 = 1,
|
||||
String = 2,
|
||||
StartGroup = 3,
|
||||
EndGroup = 4,
|
||||
Fixed32 = 5,
|
||||
SignedVariant = 8
|
||||
}
|
||||
Reference in New Issue
Block a user