You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
449 lines
16 KiB
449 lines
16 KiB
3 years ago
|
|
||
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Collections.ObjectModel;
|
||
|
|
||
|
#if NETSTANDARD
|
||
|
using System.Collections.Concurrent;
|
||
|
#endif
|
||
|
|
||
|
namespace MessagePack.Formatters
|
||
|
{
|
||
|
#if NETSTANDARD
|
||
|
|
||
|
// 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 int Serialize(ref byte[] bytes, int offset, TDictionary value, IFormatterResolver formatterResolver)
|
||
|
{
|
||
|
if (value == null)
|
||
|
{
|
||
|
return MessagePackBinary.WriteNil(ref bytes, offset);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
var startOffset = offset;
|
||
|
var keyFormatter = formatterResolver.GetFormatterWithVerify<TKey>();
|
||
|
var valueFormatter = formatterResolver.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 InvalidOperationException("DictionaryFormatterBase's TDictionary supports only ICollection<KVP> or IReadOnlyCollection<KVP>");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
offset += MessagePackBinary.WriteMapHeader(ref bytes, offset, count);
|
||
|
|
||
|
var e = GetSourceEnumerator(value);
|
||
|
try
|
||
|
{
|
||
|
while (e.MoveNext())
|
||
|
{
|
||
|
var item = e.Current;
|
||
|
offset += keyFormatter.Serialize(ref bytes, offset, item.Key, formatterResolver);
|
||
|
offset += valueFormatter.Serialize(ref bytes, offset, item.Value, formatterResolver);
|
||
|
}
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
e.Dispose();
|
||
|
}
|
||
|
|
||
|
return offset - startOffset;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public TDictionary Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize)
|
||
|
{
|
||
|
if (MessagePackBinary.IsNil(bytes, offset))
|
||
|
{
|
||
|
readSize = 1;
|
||
|
return default(TDictionary);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
var startOffset = offset;
|
||
|
var keyFormatter = formatterResolver.GetFormatterWithVerify<TKey>();
|
||
|
var valueFormatter = formatterResolver.GetFormatterWithVerify<TValue>();
|
||
|
|
||
|
var len = MessagePackBinary.ReadMapHeader(bytes, offset, out readSize);
|
||
|
offset += readSize;
|
||
|
|
||
|
var dict = Create(len);
|
||
|
for (int i = 0; i < len; i++)
|
||
|
{
|
||
|
var key = keyFormatter.Deserialize(bytes, offset, formatterResolver, out readSize);
|
||
|
offset += readSize;
|
||
|
|
||
|
var value = valueFormatter.Deserialize(bytes, offset, formatterResolver, out readSize);
|
||
|
offset += readSize;
|
||
|
|
||
|
Add(dict, i, key, value);
|
||
|
}
|
||
|
readSize = offset - startOffset;
|
||
|
|
||
|
return 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);
|
||
|
protected abstract void Add(TIntermediate collection, int index, TKey key, TValue value);
|
||
|
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)
|
||
|
{
|
||
|
collection.Add(key, value);
|
||
|
}
|
||
|
|
||
|
protected override Dictionary<TKey, TValue> Complete(Dictionary<TKey, TValue> intermediateCollection)
|
||
|
{
|
||
|
return intermediateCollection;
|
||
|
}
|
||
|
|
||
|
protected override Dictionary<TKey, TValue> Create(int count)
|
||
|
{
|
||
|
return new Dictionary<TKey, TValue>(count);
|
||
|
}
|
||
|
|
||
|
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)
|
||
|
{
|
||
|
collection.Add(key, value);
|
||
|
}
|
||
|
|
||
|
protected override TDictionary Create(int count)
|
||
|
{
|
||
|
return new TDictionary();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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)
|
||
|
{
|
||
|
collection.Add(key, value);
|
||
|
}
|
||
|
|
||
|
protected override Dictionary<TKey, TValue> Create(int count)
|
||
|
{
|
||
|
return new Dictionary<TKey, TValue>(count);
|
||
|
}
|
||
|
|
||
|
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)
|
||
|
{
|
||
|
collection.Add(key, value);
|
||
|
}
|
||
|
|
||
|
protected override SortedList<TKey, TValue> Create(int count)
|
||
|
{
|
||
|
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)
|
||
|
{
|
||
|
collection.Add(key, value);
|
||
|
}
|
||
|
|
||
|
protected override SortedDictionary<TKey, TValue> Complete(SortedDictionary<TKey, TValue> intermediateCollection)
|
||
|
{
|
||
|
return intermediateCollection;
|
||
|
}
|
||
|
|
||
|
protected override SortedDictionary<TKey, TValue> Create(int count)
|
||
|
{
|
||
|
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)
|
||
|
{
|
||
|
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)
|
||
|
{
|
||
|
return new Dictionary<TKey, TValue>(count);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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)
|
||
|
{
|
||
|
collection.Add(key, value);
|
||
|
}
|
||
|
|
||
|
protected override IReadOnlyDictionary<TKey, TValue> Complete(Dictionary<TKey, TValue> intermediateCollection)
|
||
|
{
|
||
|
return intermediateCollection;
|
||
|
}
|
||
|
|
||
|
protected override Dictionary<TKey, TValue> Create(int count)
|
||
|
{
|
||
|
return new Dictionary<TKey, TValue>(count);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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)
|
||
|
{
|
||
|
collection.TryAdd(key, value);
|
||
|
}
|
||
|
|
||
|
protected override ConcurrentDictionary<TKey, TValue> Create(int count)
|
||
|
{
|
||
|
// concurrent dictionary can't access defaultConcurrecyLevel so does not use count overload.
|
||
|
return new ConcurrentDictionary<TKey, TValue>();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#else
|
||
|
|
||
|
public abstract class DictionaryFormatterBase<TKey, TValue, TIntermediate, TDictionary> : IMessagePackFormatter<TDictionary>
|
||
|
where TDictionary : IDictionary<TKey, TValue>
|
||
|
{
|
||
|
public int Serialize(ref byte[] bytes, int offset, TDictionary value, IFormatterResolver formatterResolver)
|
||
|
{
|
||
|
if (value == null)
|
||
|
{
|
||
|
return MessagePackBinary.WriteNil(ref bytes, offset);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
var startOffset = offset;
|
||
|
var keyFormatter = formatterResolver.GetFormatterWithVerify<TKey>();
|
||
|
var valueFormatter = formatterResolver.GetFormatterWithVerify<TValue>();
|
||
|
|
||
|
var count = value.Count;
|
||
|
|
||
|
offset += MessagePackBinary.WriteMapHeader(ref bytes, offset, count);
|
||
|
|
||
|
var e = value.GetEnumerator();
|
||
|
try
|
||
|
{
|
||
|
while (e.MoveNext())
|
||
|
{
|
||
|
var item = e.Current;
|
||
|
offset += keyFormatter.Serialize(ref bytes, offset, item.Key, formatterResolver);
|
||
|
offset += valueFormatter.Serialize(ref bytes, offset, item.Value, formatterResolver);
|
||
|
}
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
e.Dispose();
|
||
|
}
|
||
|
|
||
|
return offset - startOffset;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public TDictionary Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize)
|
||
|
{
|
||
|
if (MessagePackBinary.IsNil(bytes, offset))
|
||
|
{
|
||
|
readSize = 1;
|
||
|
return default(TDictionary);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
var startOffset = offset;
|
||
|
var keyFormatter = formatterResolver.GetFormatterWithVerify<TKey>();
|
||
|
var valueFormatter = formatterResolver.GetFormatterWithVerify<TValue>();
|
||
|
|
||
|
var len = MessagePackBinary.ReadMapHeader(bytes, offset, out readSize);
|
||
|
offset += readSize;
|
||
|
|
||
|
var dict = Create(len);
|
||
|
for (int i = 0; i < len; i++)
|
||
|
{
|
||
|
var key = keyFormatter.Deserialize(bytes, offset, formatterResolver, out readSize);
|
||
|
offset += readSize;
|
||
|
|
||
|
var value = valueFormatter.Deserialize(bytes, offset, formatterResolver, out readSize);
|
||
|
offset += readSize;
|
||
|
|
||
|
Add(dict, i, key, value);
|
||
|
}
|
||
|
readSize = offset - startOffset;
|
||
|
|
||
|
return Complete(dict);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// abstraction for deserialize
|
||
|
protected abstract TIntermediate Create(int count);
|
||
|
protected abstract void Add(TIntermediate collection, int index, TKey key, TValue value);
|
||
|
protected abstract TDictionary Complete(TIntermediate intermediateCollection);
|
||
|
}
|
||
|
|
||
|
public sealed class DictionaryFormatter<TKey, TValue> : DictionaryFormatterBase<TKey, TValue, Dictionary<TKey, TValue>, Dictionary<TKey, TValue>>
|
||
|
{
|
||
|
protected override void Add(Dictionary<TKey, TValue> collection, int index, TKey key, TValue value)
|
||
|
{
|
||
|
collection.Add(key, value);
|
||
|
}
|
||
|
|
||
|
protected override Dictionary<TKey, TValue> Complete(Dictionary<TKey, TValue> intermediateCollection)
|
||
|
{
|
||
|
return intermediateCollection;
|
||
|
}
|
||
|
|
||
|
protected override Dictionary<TKey, TValue> Create(int count)
|
||
|
{
|
||
|
return new Dictionary<TKey, TValue>(count);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public sealed class GenericDictionaryFormatter<TKey, TValue, TDictionary> : DictionaryFormatterBase<TKey, TValue, TDictionary, TDictionary>
|
||
|
where TDictionary : IDictionary<TKey, TValue>, new()
|
||
|
{
|
||
|
protected override void Add(TDictionary collection, int index, TKey key, TValue value)
|
||
|
{
|
||
|
collection.Add(key, value);
|
||
|
}
|
||
|
|
||
|
protected override TDictionary Complete(TDictionary intermediateCollection)
|
||
|
{
|
||
|
return intermediateCollection;
|
||
|
}
|
||
|
|
||
|
protected override TDictionary Create(int count)
|
||
|
{
|
||
|
return new TDictionary();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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)
|
||
|
{
|
||
|
collection.Add(key, value);
|
||
|
}
|
||
|
|
||
|
protected override Dictionary<TKey, TValue> Create(int count)
|
||
|
{
|
||
|
return new Dictionary<TKey, TValue>(count);
|
||
|
}
|
||
|
|
||
|
protected override IDictionary<TKey, TValue> Complete(Dictionary<TKey, TValue> intermediateCollection)
|
||
|
{
|
||
|
return intermediateCollection;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public sealed class SortedListFormatter<TKey, TValue> : DictionaryFormatterBase<TKey, TValue, SortedList<TKey, TValue>, SortedList<TKey, TValue>>
|
||
|
{
|
||
|
protected override void Add(SortedList<TKey, TValue> collection, int index, TKey key, TValue value)
|
||
|
{
|
||
|
collection.Add(key, value);
|
||
|
}
|
||
|
|
||
|
protected override SortedList<TKey, TValue> Complete(SortedList<TKey, TValue> intermediateCollection)
|
||
|
{
|
||
|
return intermediateCollection;
|
||
|
}
|
||
|
|
||
|
protected override SortedList<TKey, TValue> Create(int count)
|
||
|
{
|
||
|
return new SortedList<TKey, TValue>(count);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public sealed class SortedDictionaryFormatter<TKey, TValue> : DictionaryFormatterBase<TKey, TValue, SortedDictionary<TKey, TValue>, SortedDictionary<TKey, TValue>>
|
||
|
{
|
||
|
protected override void Add(SortedDictionary<TKey, TValue> collection, int index, TKey key, TValue value)
|
||
|
{
|
||
|
collection.Add(key, value);
|
||
|
}
|
||
|
|
||
|
protected override SortedDictionary<TKey, TValue> Complete(SortedDictionary<TKey, TValue> intermediateCollection)
|
||
|
{
|
||
|
return intermediateCollection;
|
||
|
}
|
||
|
|
||
|
protected override SortedDictionary<TKey, TValue> Create(int count)
|
||
|
{
|
||
|
return new SortedDictionary<TKey, TValue>();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
}
|