// MIT License - Copyright (c) 2025 wallstop // Full license text: https://github.com/wallstop/unity-helpers/blob/main/LICENSE namespace WallstopStudios.UnityHelpers.Core.Serialization.JsonConverters { using System; using System.Text.Json; using System.Text.Json.Serialization; using WallstopStudios.UnityHelpers.Core.Math; public sealed class RangeConverterFactory : JsonConverterFactory { public static readonly RangeConverterFactory Instance = new(); private RangeConverterFactory() { } public override bool CanConvert(Type typeToConvert) { return typeToConvert.IsGenericType && typeToConvert.GetGenericTypeDefinition() == typeof(Range<>); } public override JsonConverter CreateConverter( Type typeToConvert, JsonSerializerOptions options ) { Type tArg = typeToConvert.GetGenericArguments()[0]; Type converterType = typeof(RangeConverter<>).MakeGenericType(tArg); return (JsonConverter)Activator.CreateInstance(converterType); } private sealed class RangeConverter : JsonConverter> where T : IEquatable, IComparable { public override Range Read( ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options ) { if (reader.TokenType != JsonTokenType.StartObject) { throw new JsonException("Range must be an object"); } T min = default; T max = default; bool startInclusive = true; bool endInclusive = true; while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndObject) { return new Range(min, max, startInclusive, endInclusive); } if (reader.TokenType != JsonTokenType.PropertyName) { throw new JsonException("Expected property name for Range"); } if (reader.ValueTextEquals("min")) { reader.Read(); min = JsonSerializer.Deserialize(ref reader, options); } else if (reader.ValueTextEquals("max")) { reader.Read(); max = JsonSerializer.Deserialize(ref reader, options); } else if (reader.ValueTextEquals("startInclusive")) { reader.Read(); startInclusive = reader.GetBoolean(); } else if (reader.ValueTextEquals("endInclusive")) { reader.Read(); endInclusive = reader.GetBoolean(); } else { throw new JsonException("Unknown property for Range"); } } throw new JsonException("Incomplete JSON for Range"); } public override void Write( Utf8JsonWriter writer, Range value, JsonSerializerOptions options ) { writer.WriteStartObject(); writer.WritePropertyName("min"); JsonSerializer.Serialize(writer, value.min, options); writer.WritePropertyName("max"); JsonSerializer.Serialize(writer, value.max, options); writer.WriteBoolean("startInclusive", value.startInclusive); writer.WriteBoolean("endInclusive", value.endInclusive); writer.WriteEndObject(); } } } }