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 because supports IReadOnlyDictionary. public abstract class DictionaryFormatterBase : IMessagePackFormatter where TDictionary : IEnumerable> where TEnumerator : IEnumerator> { 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(); var valueFormatter = formatterResolver.GetFormatterWithVerify(); int count; { var col = value as ICollection>; if (col != null) { count = col.Count; } else { var col2 = value as IReadOnlyCollection>; if (col2 != null) { count = col2.Count; } else { throw new InvalidOperationException("DictionaryFormatterBase's TDictionary supports only ICollection or IReadOnlyCollection"); } } } 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(); var valueFormatter = formatterResolver.GetFormatterWithVerify(); 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 : DictionaryFormatterBase>, TDictionary> where TDictionary : IEnumerable> { protected override IEnumerator> GetSourceEnumerator(TDictionary source) { return source.GetEnumerator(); } } public abstract class DictionaryFormatterBase : DictionaryFormatterBase where TDictionary : IDictionary { protected override TDictionary Complete(TDictionary intermediateCollection) { return intermediateCollection; } } public sealed class DictionaryFormatter : DictionaryFormatterBase, Dictionary.Enumerator, Dictionary> { protected override void Add(Dictionary collection, int index, TKey key, TValue value) { collection.Add(key, value); } protected override Dictionary Complete(Dictionary intermediateCollection) { return intermediateCollection; } protected override Dictionary Create(int count) { return new Dictionary(count); } protected override Dictionary.Enumerator GetSourceEnumerator(Dictionary source) { return source.GetEnumerator(); } } public sealed class GenericDictionaryFormatter : DictionaryFormatterBase where TDictionary : IDictionary, 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 : DictionaryFormatterBase, IDictionary> { protected override void Add(Dictionary collection, int index, TKey key, TValue value) { collection.Add(key, value); } protected override Dictionary Create(int count) { return new Dictionary(count); } protected override IDictionary Complete(Dictionary intermediateCollection) { return intermediateCollection; } } public sealed class SortedListFormatter : DictionaryFormatterBase> { protected override void Add(SortedList collection, int index, TKey key, TValue value) { collection.Add(key, value); } protected override SortedList Create(int count) { return new SortedList(count); } } public sealed class SortedDictionaryFormatter : DictionaryFormatterBase, SortedDictionary.Enumerator, SortedDictionary> { protected override void Add(SortedDictionary collection, int index, TKey key, TValue value) { collection.Add(key, value); } protected override SortedDictionary Complete(SortedDictionary intermediateCollection) { return intermediateCollection; } protected override SortedDictionary Create(int count) { return new SortedDictionary(); } protected override SortedDictionary.Enumerator GetSourceEnumerator(SortedDictionary source) { return source.GetEnumerator(); } } public sealed class ReadOnlyDictionaryFormatter : DictionaryFormatterBase, ReadOnlyDictionary> { protected override void Add(Dictionary collection, int index, TKey key, TValue value) { collection.Add(key, value); } protected override ReadOnlyDictionary Complete(Dictionary intermediateCollection) { return new ReadOnlyDictionary(intermediateCollection); } protected override Dictionary Create(int count) { return new Dictionary(count); } } public sealed class InterfaceReadOnlyDictionaryFormatter : DictionaryFormatterBase, IReadOnlyDictionary> { protected override void Add(Dictionary collection, int index, TKey key, TValue value) { collection.Add(key, value); } protected override IReadOnlyDictionary Complete(Dictionary intermediateCollection) { return intermediateCollection; } protected override Dictionary Create(int count) { return new Dictionary(count); } } public sealed class ConcurrentDictionaryFormatter : DictionaryFormatterBase> { protected override void Add(ConcurrentDictionary collection, int index, TKey key, TValue value) { collection.TryAdd(key, value); } protected override ConcurrentDictionary Create(int count) { // concurrent dictionary can't access defaultConcurrecyLevel so does not use count overload. return new ConcurrentDictionary(); } } #else public abstract class DictionaryFormatterBase : IMessagePackFormatter where TDictionary : IDictionary { 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(); var valueFormatter = formatterResolver.GetFormatterWithVerify(); 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(); var valueFormatter = formatterResolver.GetFormatterWithVerify(); 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 : DictionaryFormatterBase, Dictionary> { protected override void Add(Dictionary collection, int index, TKey key, TValue value) { collection.Add(key, value); } protected override Dictionary Complete(Dictionary intermediateCollection) { return intermediateCollection; } protected override Dictionary Create(int count) { return new Dictionary(count); } } public sealed class GenericDictionaryFormatter : DictionaryFormatterBase where TDictionary : IDictionary, 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 : DictionaryFormatterBase, IDictionary> { protected override void Add(Dictionary collection, int index, TKey key, TValue value) { collection.Add(key, value); } protected override Dictionary Create(int count) { return new Dictionary(count); } protected override IDictionary Complete(Dictionary intermediateCollection) { return intermediateCollection; } } public sealed class SortedListFormatter : DictionaryFormatterBase, SortedList> { protected override void Add(SortedList collection, int index, TKey key, TValue value) { collection.Add(key, value); } protected override SortedList Complete(SortedList intermediateCollection) { return intermediateCollection; } protected override SortedList Create(int count) { return new SortedList(count); } } public sealed class SortedDictionaryFormatter : DictionaryFormatterBase, SortedDictionary> { protected override void Add(SortedDictionary collection, int index, TKey key, TValue value) { collection.Add(key, value); } protected override SortedDictionary Complete(SortedDictionary intermediateCollection) { return intermediateCollection; } protected override SortedDictionary Create(int count) { return new SortedDictionary(); } } #endif }