// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Generic; using System.Linq; namespace EpicGames.Serialization.Converters { /// /// Converter for dictionary types /// class CbDictionaryConverter : CbConverter> where TKey : notnull { /// public override Dictionary Read(CbField field) { if (field.IsNull()) { return null!; } Dictionary dictionary = []; foreach (CbField element in field) { IEnumerator enumerator = element.AsArray().GetEnumerator(); if (!enumerator.MoveNext()) { throw new CbException("Missing key for dictionary entry"); } TKey key = CbSerializer.Deserialize(enumerator.Current); if (!enumerator.MoveNext()) { throw new CbException("Missing value for dictionary entry"); } TValue value = CbSerializer.Deserialize(enumerator.Current); dictionary.Add(key, value); } return dictionary; } /// public override void Write(CbWriter writer, Dictionary value) { if (value == null) { writer.WriteNullValue(); } else { writer.BeginUniformArray(CbFieldType.Array); foreach (KeyValuePair pair in value) { writer.BeginArray(); CbSerializer.Serialize(writer, pair.Key); CbSerializer.Serialize(writer, pair.Value); writer.EndArray(); } writer.EndUniformArray(); } } /// public override void WriteNamed(CbWriter writer, CbFieldName name, Dictionary value) { if (value == null) { writer.WriteNull(name); } else if (value.Count > 0) { writer.BeginUniformArray(name, CbFieldType.Array); foreach (KeyValuePair pair in value) { writer.BeginArray(); CbSerializer.Serialize(writer, pair.Key); CbSerializer.Serialize(writer, pair.Value); writer.EndArray(); } writer.EndUniformArray(); } } } /// /// Factory for CbDictionaryConverter /// class CbDictionaryConverterFactory : CbConverterFactory { /// public override CbConverter? CreateConverter(Type type) { if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary<,>)) { Type? keyType = type.GetGenericArguments().FirstOrDefault(); if (keyType == typeof(string)) { // if the key type is a string serialize as a CbObject to more closely follow typical conventions Type converterType = typeof(CbStringDictionaryConverter<>).MakeGenericType(type.GenericTypeArguments[1..]); return (CbConverter)Activator.CreateInstance(converterType)!; } else { Type converterType = typeof(CbDictionaryConverter<,>).MakeGenericType(type.GenericTypeArguments); return (CbConverter)Activator.CreateInstance(converterType)!; } } return null; } } /// /// Converter for dictionary types with string keys, serialized as objects /// class CbStringDictionaryConverter : CbConverter> { /// public override Dictionary Read(CbField field) { if (field.IsNull()) { return null!; } Dictionary dictionary = []; foreach (CbField element in field) { string key = element.Name.ToString(); TValue value = CbSerializer.Deserialize(element); dictionary.Add(key, value); } return dictionary; } /// public override void Write(CbWriter writer, Dictionary value) { if (value == null) { writer.WriteNullValue(); } else { writer.BeginObject(); foreach (KeyValuePair pair in value) { CbSerializer.Serialize(writer, pair.Key, pair.Value); } writer.EndObject(); } } /// public override void WriteNamed(CbWriter writer, CbFieldName name, Dictionary value) { if (value == null) { writer.WriteNull(name); } else if (value.Count > 0) { writer.BeginObject(name); foreach (KeyValuePair pair in value) { CbSerializer.Serialize(writer, pair.Key, pair.Value); } writer.EndObject(); } } } }