using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Reflection; namespace Robust.Shared.Serialization.Manager { public partial class SerializationManager { private readonly Dictionary _flagsMapping = new(); private readonly Dictionary _highestFlagBit = new(); private readonly Dictionary _constantsMapping = new(); private void InitializeFlagsAndConstants(IEnumerable flags, IEnumerable constants) { foreach (Type constType in constants) { if (!constType.IsEnum) { throw new InvalidOperationException($"Could not create ConstantMapping for non-enum {constType}."); } if (Enum.GetUnderlyingType(constType) != typeof(int)) { throw new InvalidOperationException($"Could not create ConstantMapping for non-int enum {constType}."); } foreach (var constantsForAttribute in constType.GetCustomAttributes(true)) { if (_constantsMapping.ContainsKey(constantsForAttribute.Tag)) { throw new NotSupportedException($"Multiple constant enums declared for the tag {constantsForAttribute.Tag}."); } _constantsMapping.Add(constantsForAttribute.Tag, constType); } } foreach (var bitflagType in flags) { if (!bitflagType.IsEnum) { throw new InvalidOperationException($"Could not create FlagSerializer for non-enum {bitflagType}."); } if (Enum.GetUnderlyingType(bitflagType) != typeof(int)) { throw new InvalidOperationException($"Could not create FlagSerializer for non-int enum {bitflagType}."); } if (!bitflagType.GetCustomAttributes(false).Any()) { throw new InvalidOperationException($"Could not create FlagSerializer for non-bitflag enum {bitflagType}."); } foreach (var flagType in bitflagType.GetCustomAttributes(true)) { if (!_flagsMapping.TryAdd(flagType.Tag, bitflagType)) { throw new NotSupportedException($"Multiple bitflag enums declared for the tag {flagType.Tag}."); } var highestBit = bitflagType .GetEnumValues() .Cast() .Select(value => Convert.ToString(value, 2)) .Max(s => s.Length); _highestFlagBit.Add(flagType.Tag, highestBit); } } } public Type GetFlagTypeFromTag(Type tagType) { return _flagsMapping[tagType]; } public int GetFlagHighestBit(Type tagType) { return _highestFlagBit[tagType]; } public Type GetConstantTypeFromTag(Type tagType) { return _constantsMapping[tagType]; } } }