Initial Client/Server Communication

#1
Followed the MagicOnion quickstart guide, borrowing code from the chat sample app to get something working
This commit is contained in:
hyperion51 2020-02-26 17:48:40 +00:00
commit a0c8dbee72
493 changed files with 57790 additions and 3 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f92b8946eec0ab476a689a0dfa8c2498
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,52 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Linq.Expressions;
namespace MessagePack.Formatters
{
/// <summary>
/// Provides general helpers for creating collections (including dictionaries).
/// </summary>
/// <typeparam name="TCollection">The concrete type of collection to create.</typeparam>
/// <typeparam name="TEqualityComparer">The type of equality comparer that we would hope to pass into the collection's constructor.</typeparam>
internal static class CollectionHelpers<TCollection, TEqualityComparer>
where TCollection : new()
{
/// <summary>
/// The delegate that will create the collection, if the typical (int count, IEqualityComparer{T} equalityComparer) constructor was found.
/// </summary>
private static Func<int, TEqualityComparer, TCollection> collectionCreator;
/// <summary>
/// Initializes static members of the <see cref="CollectionHelpers{TCollection, TEqualityComparer}"/> class.
/// </summary>
/// <remarks>
/// Initializes a delegate that is optimized to create a collection of a given size and using the given equality comparer, if possible.
/// </remarks>
static CollectionHelpers()
{
var ctor = typeof(TCollection).GetConstructor(new Type[] { typeof(int), typeof(TEqualityComparer) });
if (ctor != null)
{
ParameterExpression param1 = Expression.Parameter(typeof(int), "count");
ParameterExpression param2 = Expression.Parameter(typeof(TEqualityComparer), "equalityComparer");
NewExpression body = Expression.New(ctor, param1, param2);
collectionCreator = Expression.Lambda<Func<int, TEqualityComparer, TCollection>>(body, param1, param2).Compile();
}
}
/// <summary>
/// Initializes a new instance of the <typeparamref name="TCollection"/> collection.
/// </summary>
/// <param name="count">The number of elements the collection should be prepared to receive.</param>
/// <param name="equalityComparer">The equality comparer to initialize the collection with.</param>
/// <returns>The newly initialized collection.</returns>
/// <remarks>
/// Use of the <paramref name="count"/> and <paramref name="equalityComparer"/> are a best effort.
/// If we can't find a constructor on the collection in the expected shape, we'll just instantiate the collection with its default constructor.
/// </remarks>
internal static TCollection CreateHashCollection(int count, TEqualityComparer equalityComparer) => collectionCreator != null ? collectionCreator.Invoke(count, equalityComparer) : new TCollection();
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 25f9fe82ddb369c8f9600901293b80f8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,70 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
#pragma warning disable SA1649 // File name should match first type name
namespace MessagePack.Formatters
{
/// <summary>
/// Serialize by .NET native DateTime binary format.
/// </summary>
public sealed class NativeDateTimeFormatter : IMessagePackFormatter<DateTime>
{
public static readonly NativeDateTimeFormatter Instance = new NativeDateTimeFormatter();
public void Serialize(ref MessagePackWriter writer, DateTime value, MessagePackSerializerOptions options)
{
var dateData = value.ToBinary();
writer.Write(dateData);
}
public DateTime Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
var dateData = reader.ReadInt64();
return DateTime.FromBinary(dateData);
}
}
public sealed class NativeDateTimeArrayFormatter : IMessagePackFormatter<DateTime[]>
{
public static readonly NativeDateTimeArrayFormatter Instance = new NativeDateTimeArrayFormatter();
public void Serialize(ref MessagePackWriter writer, DateTime[] value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
}
else
{
writer.WriteArrayHeader(value.Length);
for (int i = 0; i < value.Length; i++)
{
writer.Write(value[i].ToBinary());
}
}
}
public DateTime[] Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return null;
}
else
{
var len = reader.ReadArrayHeader();
var array = new DateTime[len];
for (int i = 0; i < array.Length; i++)
{
var dateData = reader.ReadInt64();
array[i] = DateTime.FromBinary(dateData);
}
return array;
}
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e28b94bd9483c36efae78067f97c65cb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,280 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Reflection;
#pragma warning disable SA1649 // File name should match first type name
namespace MessagePack.Formatters
{
// unfortunately, can't use IDictionary<KVP> because supports IReadOnlyDictionary.
public abstract class DictionaryFormatterBase<TKey, TValue, TIntermediate, TEnumerator, TDictionary> : IMessagePackFormatter<TDictionary>
where TDictionary : IEnumerable<KeyValuePair<TKey, TValue>>
where TEnumerator : IEnumerator<KeyValuePair<TKey, TValue>>
{
public void Serialize(ref MessagePackWriter writer, TDictionary value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
}
else
{
IFormatterResolver resolver = options.Resolver;
IMessagePackFormatter<TKey> keyFormatter = resolver.GetFormatterWithVerify<TKey>();
IMessagePackFormatter<TValue> valueFormatter = resolver.GetFormatterWithVerify<TValue>();
int count;
{
var col = value as ICollection<KeyValuePair<TKey, TValue>>;
if (col != null)
{
count = col.Count;
}
else
{
var col2 = value as IReadOnlyCollection<KeyValuePair<TKey, TValue>>;
if (col2 != null)
{
count = col2.Count;
}
else
{
throw new MessagePackSerializationException("DictionaryFormatterBase's TDictionary supports only ICollection<KVP> or IReadOnlyCollection<KVP>");
}
}
}
writer.WriteMapHeader(count);
TEnumerator e = this.GetSourceEnumerator(value);
try
{
while (e.MoveNext())
{
writer.CancellationToken.ThrowIfCancellationRequested();
KeyValuePair<TKey, TValue> item = e.Current;
keyFormatter.Serialize(ref writer, item.Key, options);
valueFormatter.Serialize(ref writer, item.Value, options);
}
}
finally
{
e.Dispose();
}
}
}
public TDictionary Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return default(TDictionary);
}
else
{
IFormatterResolver resolver = options.Resolver;
IMessagePackFormatter<TKey> keyFormatter = resolver.GetFormatterWithVerify<TKey>();
IMessagePackFormatter<TValue> valueFormatter = resolver.GetFormatterWithVerify<TValue>();
var len = reader.ReadMapHeader();
TIntermediate dict = this.Create(len, options);
options.Security.DepthStep(ref reader);
try
{
for (int i = 0; i < len; i++)
{
reader.CancellationToken.ThrowIfCancellationRequested();
TKey key = keyFormatter.Deserialize(ref reader, options);
TValue value = valueFormatter.Deserialize(ref reader, options);
this.Add(dict, i, key, value, options);
}
}
finally
{
reader.Depth--;
}
return this.Complete(dict);
}
}
// abstraction for serialize
// Some collections can use struct iterator, this is optimization path
protected abstract TEnumerator GetSourceEnumerator(TDictionary source);
// abstraction for deserialize
protected abstract TIntermediate Create(int count, MessagePackSerializerOptions options);
protected abstract void Add(TIntermediate collection, int index, TKey key, TValue value, MessagePackSerializerOptions options);
protected abstract TDictionary Complete(TIntermediate intermediateCollection);
}
public abstract class DictionaryFormatterBase<TKey, TValue, TIntermediate, TDictionary> : DictionaryFormatterBase<TKey, TValue, TIntermediate, IEnumerator<KeyValuePair<TKey, TValue>>, TDictionary>
where TDictionary : IEnumerable<KeyValuePair<TKey, TValue>>
{
protected override IEnumerator<KeyValuePair<TKey, TValue>> GetSourceEnumerator(TDictionary source)
{
return source.GetEnumerator();
}
}
public abstract class DictionaryFormatterBase<TKey, TValue, TDictionary> : DictionaryFormatterBase<TKey, TValue, TDictionary, TDictionary>
where TDictionary : IDictionary<TKey, TValue>
{
protected override TDictionary Complete(TDictionary intermediateCollection)
{
return intermediateCollection;
}
}
public sealed class DictionaryFormatter<TKey, TValue> : DictionaryFormatterBase<TKey, TValue, Dictionary<TKey, TValue>, Dictionary<TKey, TValue>.Enumerator, Dictionary<TKey, TValue>>
{
protected override void Add(Dictionary<TKey, TValue> collection, int index, TKey key, TValue value, MessagePackSerializerOptions options)
{
collection.Add(key, value);
}
protected override Dictionary<TKey, TValue> Complete(Dictionary<TKey, TValue> intermediateCollection)
{
return intermediateCollection;
}
protected override Dictionary<TKey, TValue> Create(int count, MessagePackSerializerOptions options)
{
return new Dictionary<TKey, TValue>(count, options.Security.GetEqualityComparer<TKey>());
}
protected override Dictionary<TKey, TValue>.Enumerator GetSourceEnumerator(Dictionary<TKey, TValue> source)
{
return source.GetEnumerator();
}
}
public sealed class GenericDictionaryFormatter<TKey, TValue, TDictionary> : DictionaryFormatterBase<TKey, TValue, TDictionary>
where TDictionary : IDictionary<TKey, TValue>, new()
{
protected override void Add(TDictionary collection, int index, TKey key, TValue value, MessagePackSerializerOptions options)
{
collection.Add(key, value);
}
protected override TDictionary Create(int count, MessagePackSerializerOptions options)
{
return CollectionHelpers<TDictionary, IEqualityComparer<TKey>>.CreateHashCollection(count, options.Security.GetEqualityComparer<TKey>());
}
}
public sealed class InterfaceDictionaryFormatter<TKey, TValue> : DictionaryFormatterBase<TKey, TValue, Dictionary<TKey, TValue>, IDictionary<TKey, TValue>>
{
protected override void Add(Dictionary<TKey, TValue> collection, int index, TKey key, TValue value, MessagePackSerializerOptions options)
{
collection.Add(key, value);
}
protected override Dictionary<TKey, TValue> Create(int count, MessagePackSerializerOptions options)
{
return new Dictionary<TKey, TValue>(count, options.Security.GetEqualityComparer<TKey>());
}
protected override IDictionary<TKey, TValue> Complete(Dictionary<TKey, TValue> intermediateCollection)
{
return intermediateCollection;
}
}
public sealed class SortedListFormatter<TKey, TValue> : DictionaryFormatterBase<TKey, TValue, SortedList<TKey, TValue>>
{
protected override void Add(SortedList<TKey, TValue> collection, int index, TKey key, TValue value, MessagePackSerializerOptions options)
{
collection.Add(key, value);
}
protected override SortedList<TKey, TValue> Create(int count, MessagePackSerializerOptions options)
{
return new SortedList<TKey, TValue>(count);
}
}
public sealed class SortedDictionaryFormatter<TKey, TValue> : DictionaryFormatterBase<TKey, TValue, SortedDictionary<TKey, TValue>, SortedDictionary<TKey, TValue>.Enumerator, SortedDictionary<TKey, TValue>>
{
protected override void Add(SortedDictionary<TKey, TValue> collection, int index, TKey key, TValue value, MessagePackSerializerOptions options)
{
collection.Add(key, value);
}
protected override SortedDictionary<TKey, TValue> Complete(SortedDictionary<TKey, TValue> intermediateCollection)
{
return intermediateCollection;
}
protected override SortedDictionary<TKey, TValue> Create(int count, MessagePackSerializerOptions options)
{
return new SortedDictionary<TKey, TValue>();
}
protected override SortedDictionary<TKey, TValue>.Enumerator GetSourceEnumerator(SortedDictionary<TKey, TValue> source)
{
return source.GetEnumerator();
}
}
public sealed class ReadOnlyDictionaryFormatter<TKey, TValue> : DictionaryFormatterBase<TKey, TValue, Dictionary<TKey, TValue>, ReadOnlyDictionary<TKey, TValue>>
{
protected override void Add(Dictionary<TKey, TValue> collection, int index, TKey key, TValue value, MessagePackSerializerOptions options)
{
collection.Add(key, value);
}
protected override ReadOnlyDictionary<TKey, TValue> Complete(Dictionary<TKey, TValue> intermediateCollection)
{
return new ReadOnlyDictionary<TKey, TValue>(intermediateCollection);
}
protected override Dictionary<TKey, TValue> Create(int count, MessagePackSerializerOptions options)
{
return new Dictionary<TKey, TValue>(count, options.Security.GetEqualityComparer<TKey>());
}
}
public sealed class InterfaceReadOnlyDictionaryFormatter<TKey, TValue> : DictionaryFormatterBase<TKey, TValue, Dictionary<TKey, TValue>, IReadOnlyDictionary<TKey, TValue>>
{
protected override void Add(Dictionary<TKey, TValue> collection, int index, TKey key, TValue value, MessagePackSerializerOptions options)
{
collection.Add(key, value);
}
protected override IReadOnlyDictionary<TKey, TValue> Complete(Dictionary<TKey, TValue> intermediateCollection)
{
return intermediateCollection;
}
protected override Dictionary<TKey, TValue> Create(int count, MessagePackSerializerOptions options)
{
return new Dictionary<TKey, TValue>(count, options.Security.GetEqualityComparer<TKey>());
}
}
public sealed class ConcurrentDictionaryFormatter<TKey, TValue> : DictionaryFormatterBase<TKey, TValue, System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue>>
{
protected override void Add(ConcurrentDictionary<TKey, TValue> collection, int index, TKey key, TValue value, MessagePackSerializerOptions options)
{
collection.TryAdd(key, value);
}
protected override ConcurrentDictionary<TKey, TValue> Create(int count, MessagePackSerializerOptions options)
{
// concurrent dictionary can't access defaultConcurrecyLevel so does not use count overload.
return new ConcurrentDictionary<TKey, TValue>(options.Security.GetEqualityComparer<TKey>());
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3f0984a238b11bd2c97eb781371bb121
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,82 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Linq.Expressions;
using System.Reflection;
namespace MessagePack.Formatters
{
/// <summary>
/// This formatter can serialize any value whose static type is <see cref="object"/>
/// for which another resolver can provide a formatter for the runtime type.
/// Its deserialization is limited to forwarding all calls to the <see cref="PrimitiveObjectFormatter"/>.
/// </summary>
public sealed class DynamicObjectTypeFallbackFormatter : IMessagePackFormatter<object>
{
public static readonly IMessagePackFormatter<object> Instance = new DynamicObjectTypeFallbackFormatter();
private delegate void SerializeMethod(object dynamicFormatter, ref MessagePackWriter writer, object value, MessagePackSerializerOptions options);
private static readonly Internal.ThreadsafeTypeKeyHashTable<SerializeMethod> SerializerDelegates = new Internal.ThreadsafeTypeKeyHashTable<SerializeMethod>();
private DynamicObjectTypeFallbackFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, object value, MessagePackSerializerOptions options)
{
if (value is null)
{
writer.WriteNil();
return;
}
Type type = value.GetType();
TypeInfo ti = type.GetTypeInfo();
if (type == typeof(object))
{
// serialize to empty map
writer.WriteMapHeader(0);
return;
}
object formatter = options.Resolver.GetFormatterDynamicWithVerify(type);
if (!SerializerDelegates.TryGetValue(type, out SerializeMethod serializerDelegate))
{
lock (SerializerDelegates)
{
if (!SerializerDelegates.TryGetValue(type, out serializerDelegate))
{
Type formatterType = typeof(IMessagePackFormatter<>).MakeGenericType(type);
ParameterExpression param0 = Expression.Parameter(typeof(object), "formatter");
ParameterExpression param1 = Expression.Parameter(typeof(MessagePackWriter).MakeByRefType(), "writer");
ParameterExpression param2 = Expression.Parameter(typeof(object), "value");
ParameterExpression param3 = Expression.Parameter(typeof(MessagePackSerializerOptions), "options");
MethodInfo serializeMethodInfo = formatterType.GetRuntimeMethod("Serialize", new[] { typeof(MessagePackWriter).MakeByRefType(), type, typeof(MessagePackSerializerOptions) });
MethodCallExpression body = Expression.Call(
Expression.Convert(param0, formatterType),
serializeMethodInfo,
param1,
ti.IsValueType ? Expression.Unbox(param2, type) : Expression.Convert(param2, type),
param3);
serializerDelegate = Expression.Lambda<SerializeMethod>(body, param0, param1, param2, param3).Compile();
SerializerDelegates.TryAdd(type, serializerDelegate);
}
}
}
serializerDelegate(formatter, ref writer, value, options);
}
public object Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
return PrimitiveObjectFormatter.Instance.Deserialize(ref reader, options);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bc47abc7cd51279d9ac40fe1da6ffa1d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,128 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Serialization;
namespace MessagePack.Formatters
{
// Note:This implementation is 'not' fastest, should more improve.
public sealed class EnumAsStringFormatter<T> : IMessagePackFormatter<T>
{
private readonly IReadOnlyDictionary<string, T> nameValueMapping;
private readonly IReadOnlyDictionary<T, string> valueNameMapping;
private readonly IReadOnlyDictionary<string, string> clrToSerializationName;
private readonly IReadOnlyDictionary<string, string> serializationToClrName;
private readonly bool enumMemberOverridesPresent;
private readonly bool isFlags;
public EnumAsStringFormatter()
{
this.isFlags = typeof(T).GetCustomAttribute<FlagsAttribute>() is object;
var fields = typeof(T).GetFields(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Static);
var nameValueMapping = new Dictionary<string, T>(fields.Length);
var valueNameMapping = new Dictionary<T, string>();
Dictionary<string, string> clrToSerializationName = null;
Dictionary<string, string> serializationToClrName = null;
foreach (FieldInfo enumValueMember in fields)
{
string name = enumValueMember.Name;
T value = (T)enumValueMember.GetValue(null);
// Consider the case where the serialized form of the enum value is overridden via an attribute.
var attribute = enumValueMember.GetCustomAttribute<EnumMemberAttribute>();
if (attribute?.IsValueSetExplicitly ?? false)
{
clrToSerializationName = clrToSerializationName ?? new Dictionary<string, string>();
serializationToClrName = serializationToClrName ?? new Dictionary<string, string>();
clrToSerializationName.Add(name, attribute.Value);
serializationToClrName.Add(attribute.Value, name);
name = attribute.Value;
this.enumMemberOverridesPresent = true;
}
nameValueMapping[name] = value;
valueNameMapping[value] = name;
}
this.nameValueMapping = nameValueMapping;
this.valueNameMapping = valueNameMapping;
this.clrToSerializationName = clrToSerializationName;
this.serializationToClrName = serializationToClrName;
}
public void Serialize(ref MessagePackWriter writer, T value, MessagePackSerializerOptions options)
{
// Enum.ToString() is slow, so avoid it when we can.
if (!this.valueNameMapping.TryGetValue(value, out string valueString))
{
// fallback for flags, values with no name, etc
valueString = this.GetSerializedNames(value.ToString());
}
writer.Write(valueString);
}
public T Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
string name = reader.ReadString();
// Avoid Enum.Parse when we can because it is too slow.
if (!this.nameValueMapping.TryGetValue(name, out T value))
{
value = (T)Enum.Parse(typeof(T), this.GetClrNames(name));
}
return value;
}
private string GetClrNames(string serializedNames)
{
if (this.enumMemberOverridesPresent && this.isFlags && serializedNames.IndexOf(", ", StringComparison.Ordinal) >= 0)
{
return Translate(serializedNames, this.serializationToClrName);
}
// We don't need to consider the trivial case of no commas because our caller would have found that in the lookup table and not called us.
return serializedNames;
}
private string GetSerializedNames(string clrNames)
{
if (this.enumMemberOverridesPresent && this.isFlags && clrNames.IndexOf(", ", StringComparison.Ordinal) >= 0)
{
return Translate(clrNames, this.clrToSerializationName);
}
// We don't need to consider the trivial case of no commas because our caller would have found that in the lookup table and not called us.
return clrNames;
}
private static string Translate(string items, IReadOnlyDictionary<string, string> mapping)
{
string[] elements = items.Split(',');
for (int i = 0; i < elements.Length; i++)
{
// Trim the leading space if there is one (due to the delimiter being ", ").
if (i > 0 && elements[i].Length > 0 && elements[i][0] == ' ')
{
elements[i] = elements[i].Substring(1);
}
if (mapping.TryGetValue(elements[i], out string substituteValue))
{
elements[i] = substituteValue;
}
}
return string.Join(", ", elements);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f7cdc1e759af9873989648baa08f0350
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,73 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Runtime.CompilerServices;
namespace MessagePack.Formatters
{
public sealed class GenericEnumFormatter<T> : IMessagePackFormatter<T>
where T : Enum
{
private delegate void EnumSerialize(ref MessagePackWriter writer, ref T value);
private delegate T EnumDeserialize(ref MessagePackReader reader);
private readonly EnumSerialize serializer;
private readonly EnumDeserialize deserializer;
public GenericEnumFormatter()
{
var underlyingType = typeof(T).GetEnumUnderlyingType();
switch (Type.GetTypeCode(underlyingType))
{
#pragma warning disable SA1107 // Avoid multiple statements on same line.
case TypeCode.Byte:
serializer = (ref MessagePackWriter writer, ref T value) => writer.Write(Unsafe.As<T, Byte>(ref value));
deserializer = (ref MessagePackReader reader) => { var v = reader.ReadByte(); return Unsafe.As<Byte, T>(ref v); };
break;
case TypeCode.Int16:
serializer = (ref MessagePackWriter writer, ref T value) => writer.Write(Unsafe.As<T, Int16>(ref value));
deserializer = (ref MessagePackReader reader) => { var v = reader.ReadInt16(); return Unsafe.As<Int16, T>(ref v); };
break;
case TypeCode.Int32:
serializer = (ref MessagePackWriter writer, ref T value) => writer.Write(Unsafe.As<T, Int32>(ref value));
deserializer = (ref MessagePackReader reader) => { var v = reader.ReadInt32(); return Unsafe.As<Int32, T>(ref v); };
break;
case TypeCode.Int64:
serializer = (ref MessagePackWriter writer, ref T value) => writer.Write(Unsafe.As<T, Int64>(ref value));
deserializer = (ref MessagePackReader reader) => { var v = reader.ReadInt64(); return Unsafe.As<Int64, T>(ref v); };
break;
case TypeCode.SByte:
serializer = (ref MessagePackWriter writer, ref T value) => writer.Write(Unsafe.As<T, SByte>(ref value));
deserializer = (ref MessagePackReader reader) => { var v = reader.ReadSByte(); return Unsafe.As<SByte, T>(ref v); };
break;
case TypeCode.UInt16:
serializer = (ref MessagePackWriter writer, ref T value) => writer.Write(Unsafe.As<T, UInt16>(ref value));
deserializer = (ref MessagePackReader reader) => { var v = reader.ReadUInt16(); return Unsafe.As<UInt16, T>(ref v); };
break;
case TypeCode.UInt32:
serializer = (ref MessagePackWriter writer, ref T value) => writer.Write(Unsafe.As<T, UInt32>(ref value));
deserializer = (ref MessagePackReader reader) => { var v = reader.ReadUInt32(); return Unsafe.As<UInt32, T>(ref v); };
break;
case TypeCode.UInt64:
serializer = (ref MessagePackWriter writer, ref T value) => writer.Write(Unsafe.As<T, UInt64>(ref value));
deserializer = (ref MessagePackReader reader) => { var v = reader.ReadUInt64(); return Unsafe.As<UInt64, T>(ref v); };
break;
default:
break;
#pragma warning restore SA1107 // Avoid multiple statements on same line.
}
}
public void Serialize(ref MessagePackWriter writer, T value, MessagePackSerializerOptions options)
{
serializer(ref writer, ref value);
}
public T Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
return deserializer(ref reader);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7f3275d9a9f3275ec9cc43d6859964fe
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,42 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Buffers;
using System.ComponentModel;
namespace MessagePack.Formatters
{
#pragma warning disable SA1649 // File name should match first type name
/// <summary>
/// A base interface for <see cref="IMessagePackFormatter{T}"/> so that all generic implementations
/// can be detected by a common base type.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public interface IMessagePackFormatter
{
}
#pragma warning restore SA1649 // File name should match first type name
/// <summary>
/// The contract for serialization of some specific type.
/// </summary>
/// <typeparam name="T">The type to be serialized or deserialized.</typeparam>
public interface IMessagePackFormatter<T> : IMessagePackFormatter
{
/// <summary>
/// Serializes a value.
/// </summary>
/// <param name="writer">The writer to use when serializing the value.</param>
/// <param name="value">The value to be serialized.</param>
/// <param name="options">The serialization settings to use, including the resolver to use to obtain formatters for types that make up the composite type <typeparamref name="T"/>.</param>
void Serialize(ref MessagePackWriter writer, T value, MessagePackSerializerOptions options);
/// <summary>
/// Deserializes a value.
/// </summary>
/// <param name="reader">The reader to deserialize from.</param>
/// <param name="options">The serialization settings to use, including the resolver to use to obtain formatters for types that make up the composite type <typeparamref name="T"/>.</param>
/// <returns>The deserialized value.</returns>
T Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options);
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cd75a2bcccf20dfb6824d447ec99a1fa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,21 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Buffers;
namespace MessagePack.Formatters
{
public sealed class IgnoreFormatter<T> : IMessagePackFormatter<T>
{
public void Serialize(ref MessagePackWriter writer, T value, MessagePackSerializerOptions options)
{
writer.WriteNil();
}
public T Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
reader.Skip();
return default(T);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 64fa7163708478803a466c61cdb596d6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,293 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Text;
#pragma warning disable SA1649 // File name should match first type name
namespace MessagePack.Formatters
{
/* multi dimensional array serialize to [i, j, [seq]] */
public sealed class TwoDimensionalArrayFormatter<T> : IMessagePackFormatter<T[,]>
{
private const int ArrayLength = 3;
public void Serialize(ref MessagePackWriter writer, T[,] value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
}
else
{
var i = value.GetLength(0);
var j = value.GetLength(1);
IMessagePackFormatter<T> formatter = options.Resolver.GetFormatterWithVerify<T>();
writer.WriteArrayHeader(ArrayLength);
writer.Write(i);
writer.Write(j);
writer.WriteArrayHeader(value.Length);
foreach (T item in value)
{
writer.CancellationToken.ThrowIfCancellationRequested();
formatter.Serialize(ref writer, item, options);
}
}
}
public T[,] Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return null;
}
else
{
IMessagePackFormatter<T> formatter = options.Resolver.GetFormatterWithVerify<T>();
var len = reader.ReadArrayHeader();
if (len != ArrayLength)
{
throw new MessagePackSerializationException("Invalid T[,] format");
}
var iLength = reader.ReadInt32();
var jLength = reader.ReadInt32();
var maxLen = reader.ReadArrayHeader();
var array = new T[iLength, jLength];
var i = 0;
var j = -1;
options.Security.DepthStep(ref reader);
try
{
for (int loop = 0; loop < maxLen; loop++)
{
reader.CancellationToken.ThrowIfCancellationRequested();
if (j < jLength - 1)
{
j++;
}
else
{
j = 0;
i++;
}
array[i, j] = formatter.Deserialize(ref reader, options);
}
}
finally
{
reader.Depth--;
}
return array;
}
}
}
public sealed class ThreeDimensionalArrayFormatter<T> : IMessagePackFormatter<T[,,]>
{
private const int ArrayLength = 4;
public void Serialize(ref MessagePackWriter writer, T[,,] value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
}
else
{
var i = value.GetLength(0);
var j = value.GetLength(1);
var k = value.GetLength(2);
IMessagePackFormatter<T> formatter = options.Resolver.GetFormatterWithVerify<T>();
writer.WriteArrayHeader(ArrayLength);
writer.Write(i);
writer.Write(j);
writer.Write(k);
writer.WriteArrayHeader(value.Length);
foreach (T item in value)
{
writer.CancellationToken.ThrowIfCancellationRequested();
formatter.Serialize(ref writer, item, options);
}
}
}
public T[,,] Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return null;
}
else
{
IMessagePackFormatter<T> formatter = options.Resolver.GetFormatterWithVerify<T>();
var len = reader.ReadArrayHeader();
if (len != ArrayLength)
{
throw new MessagePackSerializationException("Invalid T[,,] format");
}
var iLength = reader.ReadInt32();
var jLength = reader.ReadInt32();
var kLength = reader.ReadInt32();
var maxLen = reader.ReadArrayHeader();
var array = new T[iLength, jLength, kLength];
var i = 0;
var j = 0;
var k = -1;
options.Security.DepthStep(ref reader);
try
{
for (int loop = 0; loop < maxLen; loop++)
{
reader.CancellationToken.ThrowIfCancellationRequested();
if (k < kLength - 1)
{
k++;
}
else if (j < jLength - 1)
{
k = 0;
j++;
}
else
{
k = 0;
j = 0;
i++;
}
array[i, j, k] = formatter.Deserialize(ref reader, options);
}
}
finally
{
reader.Depth--;
}
return array;
}
}
}
public sealed class FourDimensionalArrayFormatter<T> : IMessagePackFormatter<T[,,,]>
{
private const int ArrayLength = 5;
public void Serialize(ref MessagePackWriter writer, T[,,,] value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
}
else
{
var i = value.GetLength(0);
var j = value.GetLength(1);
var k = value.GetLength(2);
var l = value.GetLength(3);
IMessagePackFormatter<T> formatter = options.Resolver.GetFormatterWithVerify<T>();
writer.WriteArrayHeader(ArrayLength);
writer.Write(i);
writer.Write(j);
writer.Write(k);
writer.Write(l);
writer.WriteArrayHeader(value.Length);
foreach (T item in value)
{
writer.CancellationToken.ThrowIfCancellationRequested();
formatter.Serialize(ref writer, item, options);
}
}
}
public T[,,,] Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return null;
}
else
{
IMessagePackFormatter<T> formatter = options.Resolver.GetFormatterWithVerify<T>();
var len = reader.ReadArrayHeader();
if (len != ArrayLength)
{
throw new MessagePackSerializationException("Invalid T[,,,] format");
}
var iLength = reader.ReadInt32();
var jLength = reader.ReadInt32();
var kLength = reader.ReadInt32();
var lLength = reader.ReadInt32();
var maxLen = reader.ReadArrayHeader();
var array = new T[iLength, jLength, kLength, lLength];
var i = 0;
var j = 0;
var k = 0;
var l = -1;
options.Security.DepthStep(ref reader);
try
{
for (int loop = 0; loop < maxLen; loop++)
{
reader.CancellationToken.ThrowIfCancellationRequested();
if (l < lLength - 1)
{
l++;
}
else if (k < kLength - 1)
{
l = 0;
k++;
}
else if (j < jLength - 1)
{
l = 0;
k = 0;
j++;
}
else
{
l = 0;
k = 0;
j = 0;
i++;
}
array[i, j, k, l] = formatter.Deserialize(ref reader, options);
}
}
finally
{
reader.Depth--;
}
return array;
}
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8a4af86ee0f0a74de9e88b1fe8c9826d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,44 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace MessagePack.Formatters
{
public class NilFormatter : IMessagePackFormatter<Nil>
{
public static readonly IMessagePackFormatter<Nil> Instance = new NilFormatter();
private NilFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, Nil value, MessagePackSerializerOptions options)
{
writer.WriteNil();
}
public Nil Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
return reader.ReadNil();
}
}
// NullableNil is same as Nil.
public class NullableNilFormatter : IMessagePackFormatter<Nil?>
{
public static readonly IMessagePackFormatter<Nil?> Instance = new NullableNilFormatter();
private NullableNilFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, Nil? value, MessagePackSerializerOptions options)
{
writer.WriteNil();
}
public Nil? Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
return reader.ReadNil();
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 708c91d45dcbf19469504ec78aa2abee
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,73 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Buffers;
#pragma warning disable SA1649 // File name should match first type name
namespace MessagePack.Formatters
{
public sealed class NullableFormatter<T> : IMessagePackFormatter<T?>
where T : struct
{
public void Serialize(ref MessagePackWriter writer, T? value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
}
else
{
options.Resolver.GetFormatterWithVerify<T>().Serialize(ref writer, value.Value, options);
}
}
public T? Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.IsNil)
{
reader.ReadNil();
return null;
}
else
{
return options.Resolver.GetFormatterWithVerify<T>().Deserialize(ref reader, options);
}
}
}
public sealed class StaticNullableFormatter<T> : IMessagePackFormatter<T?>
where T : struct
{
private readonly IMessagePackFormatter<T> underlyingFormatter;
public StaticNullableFormatter(IMessagePackFormatter<T> underlyingFormatter)
{
this.underlyingFormatter = underlyingFormatter;
}
public void Serialize(ref MessagePackWriter writer, T? value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
}
else
{
this.underlyingFormatter.Serialize(ref writer, value.Value, options);
}
}
public T? Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return null;
}
else
{
return this.underlyingFormatter.Deserialize(ref reader, options);
}
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 88e906d65ee7d29d3ae1fb5865b8f6ab
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,337 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Reflection;
namespace MessagePack.Formatters
{
public sealed class PrimitiveObjectFormatter : IMessagePackFormatter<object>
{
public static readonly IMessagePackFormatter<object> Instance = new PrimitiveObjectFormatter();
private static readonly Dictionary<Type, int> TypeToJumpCode = new Dictionary<Type, int>()
{
// When adding types whose size exceeds 32-bits, add support in MessagePackSecurity.GetHashCollisionResistantEqualityComparer<T>()
{ typeof(Boolean), 0 },
{ typeof(Char), 1 },
{ typeof(SByte), 2 },
{ typeof(Byte), 3 },
{ typeof(Int16), 4 },
{ typeof(UInt16), 5 },
{ typeof(Int32), 6 },
{ typeof(UInt32), 7 },
{ typeof(Int64), 8 },
{ typeof(UInt64), 9 },
{ typeof(Single), 10 },
{ typeof(Double), 11 },
{ typeof(DateTime), 12 },
{ typeof(string), 13 },
{ typeof(byte[]), 14 },
};
private PrimitiveObjectFormatter()
{
}
#if !UNITY_2018_3_OR_NEWER
public static bool IsSupportedType(Type type, TypeInfo typeInfo, object value)
{
if (value == null)
{
return true;
}
if (TypeToJumpCode.ContainsKey(type))
{
return true;
}
if (typeInfo.IsEnum)
{
return true;
}
if (value is System.Collections.IDictionary)
{
return true;
}
if (value is System.Collections.ICollection)
{
return true;
}
return false;
}
#endif
public void Serialize(ref MessagePackWriter writer, object value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
return;
}
Type t = value.GetType();
int code;
if (TypeToJumpCode.TryGetValue(t, out code))
{
switch (code)
{
case 0:
writer.Write((bool)value);
return;
case 1:
writer.Write((char)value);
return;
case 2:
writer.WriteInt8((sbyte)value);
return;
case 3:
writer.WriteUInt8((byte)value);
return;
case 4:
writer.WriteInt16((Int16)value);
return;
case 5:
writer.WriteUInt16((UInt16)value);
return;
case 6:
writer.WriteInt32((Int32)value);
return;
case 7:
writer.WriteUInt32((UInt32)value);
return;
case 8:
writer.WriteInt64((Int64)value);
return;
case 9:
writer.WriteUInt64((UInt64)value);
return;
case 10:
writer.Write((Single)value);
return;
case 11:
writer.Write((double)value);
return;
case 12:
writer.Write((DateTime)value);
return;
case 13:
writer.Write((string)value);
return;
case 14:
writer.Write((byte[])value);
return;
default:
throw new MessagePackSerializationException("Not supported primitive object resolver. type:" + t.Name);
}
}
else
{
#if UNITY_2018_3_OR_NEWER && !NETFX_CORE
if (t.IsEnum)
#else
if (t.GetTypeInfo().IsEnum)
#endif
{
Type underlyingType = Enum.GetUnderlyingType(t);
var code2 = TypeToJumpCode[underlyingType];
switch (code2)
{
case 2:
writer.WriteInt8((sbyte)value);
return;
case 3:
writer.WriteUInt8((byte)value);
return;
case 4:
writer.WriteInt16((Int16)value);
return;
case 5:
writer.WriteUInt16((UInt16)value);
return;
case 6:
writer.WriteInt32((Int32)value);
return;
case 7:
writer.WriteUInt32((UInt32)value);
return;
case 8:
writer.WriteInt64((Int64)value);
return;
case 9:
writer.WriteUInt64((UInt64)value);
return;
default:
break;
}
}
else if (value is System.Collections.IDictionary)
{
// check IDictionary first
var d = value as System.Collections.IDictionary;
writer.WriteMapHeader(d.Count);
foreach (System.Collections.DictionaryEntry item in d)
{
this.Serialize(ref writer, item.Key, options);
this.Serialize(ref writer, item.Value, options);
}
return;
}
else if (value is System.Collections.ICollection)
{
var c = value as System.Collections.ICollection;
writer.WriteArrayHeader(c.Count);
foreach (var item in c)
{
this.Serialize(ref writer, item, options);
}
return;
}
}
throw new MessagePackSerializationException("Not supported primitive object resolver. type:" + t.Name);
}
public object Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
MessagePackType type = reader.NextMessagePackType;
IFormatterResolver resolver = options.Resolver;
switch (type)
{
case MessagePackType.Integer:
var code = reader.NextCode;
if (code >= MessagePackCode.MinNegativeFixInt && code <= MessagePackCode.MaxNegativeFixInt)
{
return reader.ReadSByte();
}
else if (code >= MessagePackCode.MinFixInt && code <= MessagePackCode.MaxFixInt)
{
return reader.ReadByte();
}
else if (code == MessagePackCode.Int8)
{
return reader.ReadSByte();
}
else if (code == MessagePackCode.Int16)
{
return reader.ReadInt16();
}
else if (code == MessagePackCode.Int32)
{
return reader.ReadInt32();
}
else if (code == MessagePackCode.Int64)
{
return reader.ReadInt64();
}
else if (code == MessagePackCode.UInt8)
{
return reader.ReadByte();
}
else if (code == MessagePackCode.UInt16)
{
return reader.ReadUInt16();
}
else if (code == MessagePackCode.UInt32)
{
return reader.ReadUInt32();
}
else if (code == MessagePackCode.UInt64)
{
return reader.ReadUInt64();
}
throw new MessagePackSerializationException("Invalid primitive bytes.");
case MessagePackType.Boolean:
return reader.ReadBoolean();
case MessagePackType.Float:
if (reader.NextCode == MessagePackCode.Float32)
{
return reader.ReadSingle();
}
else
{
return reader.ReadDouble();
}
case MessagePackType.String:
return reader.ReadString();
case MessagePackType.Binary:
// We must copy the sequence returned by ReadBytes since the reader's sequence is only valid during deserialization.
return reader.ReadBytes()?.ToArray();
case MessagePackType.Extension:
ExtensionHeader ext = reader.ReadExtensionFormatHeader();
if (ext.TypeCode == ReservedMessagePackExtensionTypeCode.DateTime)
{
return reader.ReadDateTime(ext);
}
throw new MessagePackSerializationException("Invalid primitive bytes.");
case MessagePackType.Array:
{
var length = reader.ReadArrayHeader();
IMessagePackFormatter<object> objectFormatter = resolver.GetFormatter<object>();
var array = new object[length];
options.Security.DepthStep(ref reader);
try
{
for (int i = 0; i < length; i++)
{
array[i] = objectFormatter.Deserialize(ref reader, options);
}
}
finally
{
reader.Depth--;
}
return array;
}
case MessagePackType.Map:
{
var length = reader.ReadMapHeader();
IMessagePackFormatter<object> objectFormatter = resolver.GetFormatter<object>();
var hash = new Dictionary<object, object>(length, options.Security.GetEqualityComparer<object>());
options.Security.DepthStep(ref reader);
try
{
for (int i = 0; i < length; i++)
{
var key = objectFormatter.Deserialize(ref reader, options);
var value = objectFormatter.Deserialize(ref reader, options);
hash.Add(key, value);
}
}
finally
{
reader.Depth--;
}
return hash;
}
case MessagePackType.Nil:
reader.ReadNil();
return null;
default:
throw new MessagePackSerializationException("Invalid primitive bytes.");
}
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d46d293dc804af1669409cc12690a3ad
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,599 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Buffers;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using MessagePack.Internal;
#pragma warning disable SA1649 // File name should match first type name
namespace MessagePack.Formatters
{
// NET40 -> BigInteger, Complex, Tuple
// byte[] is special. represents bin type.
public sealed class ByteArrayFormatter : IMessagePackFormatter<byte[]>
{
public static readonly ByteArrayFormatter Instance = new ByteArrayFormatter();
private ByteArrayFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, byte[] value, MessagePackSerializerOptions options)
{
writer.Write(value);
}
public byte[] Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
return reader.ReadBytes()?.ToArray();
}
}
public sealed class NullableStringFormatter : IMessagePackFormatter<String>
{
public static readonly NullableStringFormatter Instance = new NullableStringFormatter();
private NullableStringFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, string value, MessagePackSerializerOptions options)
{
writer.Write(value);
}
public string Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
return reader.ReadString();
}
}
public sealed class NullableStringArrayFormatter : IMessagePackFormatter<String[]>
{
public static readonly NullableStringArrayFormatter Instance = new NullableStringArrayFormatter();
private NullableStringArrayFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, String[] value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
}
else
{
writer.WriteArrayHeader(value.Length);
for (int i = 0; i < value.Length; i++)
{
writer.Write(value[i]);
}
}
}
public String[] Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return null;
}
else
{
var len = reader.ReadArrayHeader();
var array = new String[len];
for (int i = 0; i < array.Length; i++)
{
array[i] = reader.ReadString();
}
return array;
}
}
}
public sealed class DecimalFormatter : IMessagePackFormatter<Decimal>
{
public static readonly DecimalFormatter Instance = new DecimalFormatter();
private DecimalFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, decimal value, MessagePackSerializerOptions options)
{
var dest = writer.GetSpan(MessagePackRange.MaxFixStringLength);
if (System.Buffers.Text.Utf8Formatter.TryFormat(value, dest.Slice(1), out var written))
{
// write header
dest[0] = (byte)(MessagePackCode.MinFixStr | written);
writer.Advance(written + 1);
}
else
{
// reset writer's span previously acquired that does not use
writer.Advance(0);
writer.Write(value.ToString(CultureInfo.InvariantCulture));
}
}
public decimal Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (!(reader.ReadStringSequence() is ReadOnlySequence<byte> sequence))
{
throw new MessagePackSerializationException(string.Format("Unexpected msgpack code {0} ({1}) encountered.", MessagePackCode.Nil, MessagePackCode.ToFormatName(MessagePackCode.Nil)));
}
if (sequence.IsSingleSegment)
{
var span = sequence.First.Span;
if (System.Buffers.Text.Utf8Parser.TryParse(span, out decimal result, out var bytesConsumed))
{
if (span.Length != bytesConsumed)
{
throw new MessagePackSerializationException("Unexpected length of string.");
}
return result;
}
}
else
{
// sequence.Length is not free
var seqLen = (int)sequence.Length;
if (seqLen < 128)
{
Span<byte> span = stackalloc byte[seqLen];
sequence.CopyTo(span);
if (System.Buffers.Text.Utf8Parser.TryParse(span, out decimal result, out var bytesConsumed))
{
if (seqLen != bytesConsumed)
{
throw new MessagePackSerializationException("Unexpected length of string.");
}
return result;
}
}
else
{
var rentArray = ArrayPool<byte>.Shared.Rent(seqLen);
try
{
sequence.CopyTo(rentArray);
if (System.Buffers.Text.Utf8Parser.TryParse(rentArray.AsSpan(0, seqLen), out decimal result, out var bytesConsumed))
{
if (seqLen != bytesConsumed)
{
throw new MessagePackSerializationException("Unexpected length of string.");
}
return result;
}
}
finally
{
ArrayPool<byte>.Shared.Return(rentArray);
}
}
}
throw new MessagePackSerializationException("Can't parse to decimal, input string was not in a correct format.");
}
}
public sealed class TimeSpanFormatter : IMessagePackFormatter<TimeSpan>
{
public static readonly IMessagePackFormatter<TimeSpan> Instance = new TimeSpanFormatter();
private TimeSpanFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, TimeSpan value, MessagePackSerializerOptions options)
{
writer.Write(value.Ticks);
return;
}
public TimeSpan Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
return new TimeSpan(reader.ReadInt64());
}
}
public sealed class DateTimeOffsetFormatter : IMessagePackFormatter<DateTimeOffset>
{
public static readonly IMessagePackFormatter<DateTimeOffset> Instance = new DateTimeOffsetFormatter();
private DateTimeOffsetFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, DateTimeOffset value, MessagePackSerializerOptions options)
{
writer.WriteArrayHeader(2);
writer.Write(new DateTime(value.Ticks, DateTimeKind.Utc)); // current ticks as is
writer.Write((short)value.Offset.TotalMinutes); // offset is normalized in minutes
return;
}
public DateTimeOffset Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
var count = reader.ReadArrayHeader();
if (count != 2)
{
throw new MessagePackSerializationException("Invalid DateTimeOffset format.");
}
DateTime utc = reader.ReadDateTime();
var dtOffsetMinutes = reader.ReadInt16();
return new DateTimeOffset(utc.Ticks, TimeSpan.FromMinutes(dtOffsetMinutes));
}
}
public sealed class GuidFormatter : IMessagePackFormatter<Guid>
{
public static readonly IMessagePackFormatter<Guid> Instance = new GuidFormatter();
private GuidFormatter()
{
}
public unsafe void Serialize(ref MessagePackWriter writer, Guid value, MessagePackSerializerOptions options)
{
byte* pBytes = stackalloc byte[36];
Span<byte> bytes = new Span<byte>(pBytes, 36);
new GuidBits(ref value).Write(bytes);
writer.WriteString(bytes);
}
public Guid Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
ReadOnlySequence<byte> segment = reader.ReadStringSequence().Value;
if (segment.Length != 36)
{
throw new MessagePackSerializationException("Unexpected length of string.");
}
GuidBits result;
if (segment.IsSingleSegment)
{
result = new GuidBits(segment.First.Span);
}
else
{
Span<byte> bytes = stackalloc byte[36];
segment.CopyTo(bytes);
result = new GuidBits(bytes);
}
return result.Value;
}
}
public sealed class UriFormatter : IMessagePackFormatter<Uri>
{
public static readonly IMessagePackFormatter<Uri> Instance = new UriFormatter();
private UriFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, Uri value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
}
else
{
writer.Write(value.ToString());
}
}
public Uri Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return null;
}
else
{
return new Uri(reader.ReadString(), UriKind.RelativeOrAbsolute);
}
}
}
public sealed class VersionFormatter : IMessagePackFormatter<Version>
{
public static readonly IMessagePackFormatter<Version> Instance = new VersionFormatter();
private VersionFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, Version value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
}
else
{
writer.Write(value.ToString());
}
}
public Version Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return null;
}
else
{
return new Version(reader.ReadString());
}
}
}
public sealed class KeyValuePairFormatter<TKey, TValue> : IMessagePackFormatter<KeyValuePair<TKey, TValue>>
{
public void Serialize(ref MessagePackWriter writer, KeyValuePair<TKey, TValue> value, MessagePackSerializerOptions options)
{
writer.WriteArrayHeader(2);
IFormatterResolver resolver = options.Resolver;
resolver.GetFormatterWithVerify<TKey>().Serialize(ref writer, value.Key, options);
resolver.GetFormatterWithVerify<TValue>().Serialize(ref writer, value.Value, options);
return;
}
public KeyValuePair<TKey, TValue> Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
var count = reader.ReadArrayHeader();
if (count != 2)
{
throw new MessagePackSerializationException("Invalid KeyValuePair format.");
}
IFormatterResolver resolver = options.Resolver;
options.Security.DepthStep(ref reader);
try
{
TKey key = resolver.GetFormatterWithVerify<TKey>().Deserialize(ref reader, options);
TValue value = resolver.GetFormatterWithVerify<TValue>().Deserialize(ref reader, options);
return new KeyValuePair<TKey, TValue>(key, value);
}
finally
{
reader.Depth--;
}
}
}
public sealed class StringBuilderFormatter : IMessagePackFormatter<StringBuilder>
{
public static readonly IMessagePackFormatter<StringBuilder> Instance = new StringBuilderFormatter();
private StringBuilderFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, StringBuilder value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
}
else
{
writer.Write(value.ToString());
}
}
public StringBuilder Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return null;
}
else
{
return new StringBuilder(reader.ReadString());
}
}
}
public sealed class BitArrayFormatter : IMessagePackFormatter<BitArray>
{
public static readonly IMessagePackFormatter<BitArray> Instance = new BitArrayFormatter();
private BitArrayFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, BitArray value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
}
else
{
var len = value.Length;
writer.WriteArrayHeader(len);
for (int i = 0; i < len; i++)
{
writer.Write(value.Get(i));
}
return;
}
}
public BitArray Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return null;
}
else
{
var len = reader.ReadArrayHeader();
var array = new BitArray(len);
for (int i = 0; i < len; i++)
{
array[i] = reader.ReadBoolean();
}
return array;
}
}
}
public sealed class BigIntegerFormatter : IMessagePackFormatter<System.Numerics.BigInteger>
{
public static readonly IMessagePackFormatter<System.Numerics.BigInteger> Instance = new BigIntegerFormatter();
private BigIntegerFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, System.Numerics.BigInteger value, MessagePackSerializerOptions options)
{
#if NETCOREAPP2_1
if (!writer.OldSpec)
{
// try to get bin8 buffer.
var span = writer.GetSpan(byte.MaxValue);
if (value.TryWriteBytes(span.Slice(2), out var written))
{
span[0] = MessagePackCode.Bin8;
span[1] = (byte)written;
writer.Advance(written + 2);
return;
}
else
{
// reset writer's span previously acquired that does not use
writer.Advance(0);
}
}
#endif
writer.Write(value.ToByteArray());
return;
}
public System.Numerics.BigInteger Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
ReadOnlySequence<byte> bytes = reader.ReadBytes().Value;
#if NETCOREAPP2_1
if (bytes.IsSingleSegment)
{
return new System.Numerics.BigInteger(bytes.First.Span);
}
else
{
byte[] bytesArray = ArrayPool<byte>.Shared.Rent((int)bytes.Length);
try
{
bytes.CopyTo(bytesArray);
return new System.Numerics.BigInteger(bytesArray.AsSpan(0, (int)bytes.Length));
}
finally
{
ArrayPool<byte>.Shared.Return(bytesArray);
}
}
#else
return new System.Numerics.BigInteger(bytes.ToArray());
#endif
}
}
public sealed class ComplexFormatter : IMessagePackFormatter<System.Numerics.Complex>
{
public static readonly IMessagePackFormatter<System.Numerics.Complex> Instance = new ComplexFormatter();
private ComplexFormatter()
{
}
public void Serialize(ref MessagePackWriter writer, System.Numerics.Complex value, MessagePackSerializerOptions options)
{
writer.WriteArrayHeader(2);
writer.Write(value.Real);
writer.Write(value.Imaginary);
return;
}
public System.Numerics.Complex Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
var count = reader.ReadArrayHeader();
if (count != 2)
{
throw new MessagePackSerializationException("Invalid Complex format.");
}
var real = reader.ReadDouble();
var imaginary = reader.ReadDouble();
return new System.Numerics.Complex(real, imaginary);
}
}
public sealed class LazyFormatter<T> : IMessagePackFormatter<Lazy<T>>
{
public void Serialize(ref MessagePackWriter writer, Lazy<T> value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
}
else
{
IFormatterResolver resolver = options.Resolver;
resolver.GetFormatterWithVerify<T>().Serialize(ref writer, value.Value, options);
}
}
public Lazy<T> Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return null;
}
else
{
options.Security.DepthStep(ref reader);
try
{
// deserialize immediately(no delay, because capture byte[] causes memory leak)
IFormatterResolver resolver = options.Resolver;
T v = resolver.GetFormatterWithVerify<T>().Deserialize(ref reader, options);
return new Lazy<T>(() => v);
}
finally
{
reader.Depth--;
}
}
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6dc8f5f9191421c21bd1ba87f5a70d27
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,313 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#if !UNITY_2018_3_OR_NEWER
using System;
using System.Buffers;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using MessagePack.Internal;
namespace MessagePack.Formatters
{
/// <summary>
/// For `object` field that holds derived from `object` value, ex: var arr = new object[] { 1, "a", new Model() };.
/// </summary>
public sealed class TypelessFormatter : IMessagePackFormatter<object>
{
private delegate void SerializeMethod(object dynamicContractlessFormatter, ref MessagePackWriter writer, object value, MessagePackSerializerOptions options);
private delegate object DeserializeMethod(object dynamicContractlessFormatter, ref MessagePackReader reader, MessagePackSerializerOptions options);
/// <summary>
/// The singleton instance that can be used.
/// </summary>
public static readonly IMessagePackFormatter<object> Instance = new TypelessFormatter();
private readonly ThreadsafeTypeKeyHashTable<SerializeMethod> serializers = new ThreadsafeTypeKeyHashTable<SerializeMethod>();
private readonly ThreadsafeTypeKeyHashTable<DeserializeMethod> deserializers = new ThreadsafeTypeKeyHashTable<DeserializeMethod>();
private readonly ThreadsafeTypeKeyHashTable<byte[]> fullTypeNameCache = new ThreadsafeTypeKeyHashTable<byte[]>();
private readonly ThreadsafeTypeKeyHashTable<byte[]> shortenedTypeNameCache = new ThreadsafeTypeKeyHashTable<byte[]>();
private readonly AsymmetricKeyHashTable<byte[], ArraySegment<byte>, Type> typeCache = new AsymmetricKeyHashTable<byte[], ArraySegment<byte>, Type>(new StringArraySegmentByteAscymmetricEqualityComparer());
private static readonly HashSet<Type> UseBuiltinTypes = new HashSet<Type>
{
typeof(Boolean),
////typeof(Char),
typeof(SByte),
typeof(Byte),
typeof(Int16),
typeof(UInt16),
typeof(Int32),
typeof(UInt32),
typeof(Int64),
typeof(UInt64),
typeof(Single),
typeof(Double),
typeof(string),
typeof(byte[]),
// array should save their types.
////typeof(Boolean[]),
////typeof(Char[]),
////typeof(SByte[]),
////typeof(Int16[]),
////typeof(UInt16[]),
////typeof(Int32[]),
////typeof(UInt32[]),
////typeof(Int64[]),
////typeof(UInt64[]),
////typeof(Single[]),
////typeof(Double[]),
////typeof(string[]),
typeof(Boolean?),
////typeof(Char?),
typeof(SByte?),
typeof(Byte?),
typeof(Int16?),
typeof(UInt16?),
typeof(Int32?),
typeof(UInt32?),
typeof(Int64?),
typeof(UInt64?),
typeof(Single?),
typeof(Double?),
};
//ForceSizePrimitiveObjectResolver.Instance,
//ContractlessStandardResolverAllowPrivate.Instance);
// mscorlib or System.Private.CoreLib
private static readonly bool IsMscorlib = typeof(int).AssemblyQualifiedName.Contains("mscorlib");
private TypelessFormatter()
{
this.serializers.TryAdd(typeof(object), _ => (object p1, ref MessagePackWriter p2, object p3, MessagePackSerializerOptions p4) => { });
this.deserializers.TryAdd(typeof(object), _ => (object p1, ref MessagePackReader p2, MessagePackSerializerOptions p3) => new object());
}
private string BuildTypeName(Type type, MessagePackSerializerOptions options)
{
if (options.OmitAssemblyVersion)
{
string full = type.AssemblyQualifiedName;
var shortened = MessagePackSerializerOptions.AssemblyNameVersionSelectorRegex.Replace(full, string.Empty);
if (Type.GetType(shortened, false) == null)
{
// if type cannot be found with shortened name - use full name
shortened = full;
}
return shortened;
}
else
{
return type.AssemblyQualifiedName;
}
}
public void Serialize(ref MessagePackWriter writer, object value, MessagePackSerializerOptions options)
{
if (value == null)
{
writer.WriteNil();
return;
}
Type type = value.GetType();
byte[] typeName;
var typeNameCache = options.OmitAssemblyVersion ? this.shortenedTypeNameCache : this.fullTypeNameCache;
if (!typeNameCache.TryGetValue(type, out typeName))
{
TypeInfo ti = type.GetTypeInfo();
if (ti.IsAnonymous() || UseBuiltinTypes.Contains(type))
{
typeName = null;
}
else
{
typeName = StringEncoding.UTF8.GetBytes(this.BuildTypeName(type, options));
}
typeNameCache.TryAdd(type, typeName);
}
if (typeName == null)
{
DynamicObjectTypeFallbackFormatter.Instance.Serialize(ref writer, value, options);
return;
}
var formatter = options.Resolver.GetFormatterDynamicWithVerify(type);
// don't use GetOrAdd for avoid closure capture.
if (!this.serializers.TryGetValue(type, out SerializeMethod serializeMethod))
{
// double check locking...
lock (this.serializers)
{
if (!this.serializers.TryGetValue(type, out serializeMethod))
{
TypeInfo ti = type.GetTypeInfo();
Type formatterType = typeof(IMessagePackFormatter<>).MakeGenericType(type);
ParameterExpression param0 = Expression.Parameter(typeof(object), "formatter");
ParameterExpression param1 = Expression.Parameter(typeof(MessagePackWriter).MakeByRefType(), "writer");
ParameterExpression param2 = Expression.Parameter(typeof(object), "value");
ParameterExpression param3 = Expression.Parameter(typeof(MessagePackSerializerOptions), "options");
MethodInfo serializeMethodInfo = formatterType.GetRuntimeMethod("Serialize", new[] { typeof(MessagePackWriter).MakeByRefType(), type, typeof(MessagePackSerializerOptions) });
MethodCallExpression body = Expression.Call(
Expression.Convert(param0, formatterType),
serializeMethodInfo,
param1,
ti.IsValueType ? Expression.Unbox(param2, type) : Expression.Convert(param2, type),
param3);
serializeMethod = Expression.Lambda<SerializeMethod>(body, param0, param1, param2, param3).Compile();
this.serializers.TryAdd(type, serializeMethod);
}
}
}
// mark will be written at the end, when size is known
using (var scratchRental = SequencePool.Shared.Rent())
{
MessagePackWriter scratchWriter = writer.Clone(scratchRental.Value);
scratchWriter.WriteString(typeName);
serializeMethod(formatter, ref scratchWriter, value, options);
scratchWriter.Flush();
// mark as extension with code 100
writer.WriteExtensionFormat(new ExtensionResult((sbyte)ThisLibraryExtensionTypeCodes.TypelessFormatter, scratchRental.Value));
}
}
public object Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (reader.TryReadNil())
{
return null;
}
if (reader.NextMessagePackType == MessagePackType.Extension)
{
ExtensionHeader ext = reader.ReadExtensionFormatHeader();
if (ext.TypeCode == ThisLibraryExtensionTypeCodes.TypelessFormatter)
{
// it has type name serialized
ReadOnlySequence<byte> typeName = reader.ReadStringSequence().Value;
ArraySegment<byte> typeNameArraySegment;
byte[] rented = null;
if (!typeName.IsSingleSegment || !MemoryMarshal.TryGetArray(typeName.First, out typeNameArraySegment))
{
rented = ArrayPool<byte>.Shared.Rent((int)typeName.Length);
typeName.CopyTo(rented);
typeNameArraySegment = new ArraySegment<byte>(rented, 0, (int)typeName.Length);
}
var result = this.DeserializeByTypeName(typeNameArraySegment, ref reader, options);
if (rented != null)
{
ArrayPool<byte>.Shared.Return(rented);
}
return result;
}
}
// fallback
return DynamicObjectTypeFallbackFormatter.Instance.Deserialize(ref reader, options);
}
/// <summary>
/// Does not support deserializing of anonymous types
/// Type should be covered by preceeding resolvers in complex/standard resolver.
/// </summary>
private object DeserializeByTypeName(ArraySegment<byte> typeName, ref MessagePackReader byteSequence, MessagePackSerializerOptions options)
{
// try get type with assembly name, throw if not found
Type type;
if (!this.typeCache.TryGetValue(typeName, out type))
{
var buffer = new byte[typeName.Count];
Buffer.BlockCopy(typeName.Array, typeName.Offset, buffer, 0, buffer.Length);
var str = StringEncoding.UTF8.GetString(buffer);
type = options.LoadType(str);
if (type == null)
{
if (IsMscorlib && str.Contains("System.Private.CoreLib"))
{
str = str.Replace("System.Private.CoreLib", "mscorlib");
type = Type.GetType(str, true); // throw
}
else if (!IsMscorlib && str.Contains("mscorlib"))
{
str = str.Replace("mscorlib", "System.Private.CoreLib");
type = Type.GetType(str, true); // throw
}
else
{
type = Type.GetType(str, true); // re-throw
}
}
this.typeCache.TryAdd(buffer, type);
}
options.ThrowIfDeserializingTypeIsDisallowed(type);
var formatter = options.Resolver.GetFormatterDynamicWithVerify(type);
if (!this.deserializers.TryGetValue(type, out DeserializeMethod deserializeMethod))
{
lock (this.deserializers)
{
if (!this.deserializers.TryGetValue(type, out deserializeMethod))
{
TypeInfo ti = type.GetTypeInfo();
Type formatterType = typeof(IMessagePackFormatter<>).MakeGenericType(type);
ParameterExpression param0 = Expression.Parameter(typeof(object), "formatter");
ParameterExpression param1 = Expression.Parameter(typeof(MessagePackReader).MakeByRefType(), "reader");
ParameterExpression param2 = Expression.Parameter(typeof(MessagePackSerializerOptions), "options");
MethodInfo deserializeMethodInfo = formatterType.GetRuntimeMethod("Deserialize", new[] { typeof(MessagePackReader).MakeByRefType(), typeof(MessagePackSerializerOptions) });
MethodCallExpression deserialize = Expression.Call(
Expression.Convert(param0, formatterType),
deserializeMethodInfo,
param1,
param2);
Expression body = deserialize;
if (ti.IsValueType)
{
body = Expression.Convert(deserialize, typeof(object));
}
deserializeMethod = Expression.Lambda<DeserializeMethod>(body, param0, param1, param2).Compile();
this.deserializers.TryAdd(type, deserializeMethod);
}
}
}
return deserializeMethod(formatter, ref byteSequence, options);
}
}
}
#endif

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fe17a811684aa2fa786684f83f7fbbe7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,100 @@
// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Buffers;
#pragma warning disable SA1649 // File name should match first type name
namespace MessagePack.Formatters
{
public sealed class NativeGuidFormatter : IMessagePackFormatter<Guid>
{
/// <summary>
/// Unsafe binary Guid formatter. this is only allowed on LittleEndian environment.
/// </summary>
public static readonly IMessagePackFormatter<Guid> Instance = new NativeGuidFormatter();
private NativeGuidFormatter()
{
}
/* Guid's underlying _a,...,_k field is sequential and same layout as .NET Framework and Mono(Unity).
* But target machines must be same endian so restrict only for little endian. */
public unsafe void Serialize(ref MessagePackWriter writer, Guid value, MessagePackSerializerOptions options)
{
if (!BitConverter.IsLittleEndian)
{
throw new InvalidOperationException("NativeGuidFormatter only allows on little endian env.");
}
var valueSpan = new ReadOnlySpan<byte>(&value, sizeof(Guid));
writer.Write(valueSpan);
}
public unsafe Guid Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (!BitConverter.IsLittleEndian)
{
throw new InvalidOperationException("NativeGuidFormatter only allows on little endian env.");
}
ReadOnlySequence<byte> valueSequence = reader.ReadBytes().Value;
if (valueSequence.Length != sizeof(Guid))
{
throw new MessagePackSerializationException("Invalid Guid Size.");
}
Guid result;
var resultSpan = new Span<byte>(&result, sizeof(Guid));
valueSequence.CopyTo(resultSpan);
return result;
}
}
public sealed class NativeDecimalFormatter : IMessagePackFormatter<Decimal>
{
/// <summary>
/// Unsafe binary Decimal formatter. this is only allows on LittleEndian environment.
/// </summary>
public static readonly IMessagePackFormatter<Decimal> Instance = new NativeDecimalFormatter();
private NativeDecimalFormatter()
{
}
/* decimal underlying "flags, hi, lo, mid" fields are sequential and same layuout with .NET Framework and Mono(Unity)
* But target machines must be same endian so restrict only for little endian. */
public unsafe void Serialize(ref MessagePackWriter writer, Decimal value, MessagePackSerializerOptions options)
{
if (!BitConverter.IsLittleEndian)
{
throw new InvalidOperationException("NativeDecimalFormatter only allows on little endian env.");
}
var valueSpan = new ReadOnlySpan<byte>(&value, sizeof(Decimal));
writer.Write(valueSpan);
}
public unsafe Decimal Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
if (!BitConverter.IsLittleEndian)
{
throw new InvalidOperationException("NativeDecimalFormatter only allows on little endian env.");
}
ReadOnlySequence<byte> valueSequence = reader.ReadBytes().Value;
if (valueSequence.Length != sizeof(decimal))
{
throw new MessagePackSerializationException("Invalid decimal Size.");
}
decimal result;
var resultSpan = new Span<byte>(&result, sizeof(decimal));
valueSequence.CopyTo(resultSpan);
return result;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2c4fcfc3f496806c7915aba0cdb3f1ba
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: