// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Text.Json; using System.Text.Json.Serialization; using EpicGames.Horde; namespace HordeServer.Plugins { /// /// Collection of objects. /// [JsonConverter(typeof(PluginConfigCollectionConverter))] public class PluginConfigCollection : Dictionary { /// /// Attempts to get a plugin config of a specific type /// public bool TryGetValue(PluginName name, [NotNullWhen(true)] out T? value) where T : class, IPluginConfig { IPluginConfig? config; if (base.TryGetValue(name, out config) && config is T typedConfig) { value = typedConfig; return true; } else { value = null; return false; } } } /// /// Serializer to and from strongly typed plugin config classes /// class PluginConfigCollectionConverter : JsonConverter { /// /// Map of plugin names to the expected config type /// public Dictionary NameToType { get; } = new Dictionary(); /// public override PluginConfigCollection? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType != JsonTokenType.StartObject) { throw new JsonException("Expected an object for plugin config type"); } PluginConfigCollection result = new PluginConfigCollection(); while (reader.Read() && reader.TokenType == JsonTokenType.PropertyName) { string? nameStr = reader.GetString(); if (nameStr == null || !reader.Read()) { throw new JsonException("Invalid plugin name"); } PluginName name = new PluginName(new StringId(nameStr)); if (NameToType.TryGetValue(name, out Type? type)) { object? obj = JsonSerializer.Deserialize(ref reader, type, options); if (obj != null) { result.Add(name, (IPluginConfig)obj); } } else { reader.Skip(); } } if (reader.TokenType != JsonTokenType.EndObject) { throw new JsonException("Invalid token while parsing plugin config"); } return result; } /// public override void Write(Utf8JsonWriter writer, PluginConfigCollection value, JsonSerializerOptions options) { writer.WriteStartObject(); foreach ((PluginName name, IPluginConfig config) in value) { writer.WritePropertyName(name.ToString()); JsonSerializer.Serialize(writer, config, config.GetType(), options); } writer.WriteEndObject(); } } }