using System; using System.Text.RegularExpressions; using Microsoft.Xna.Framework; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using StardewModdingAPI.Framework.Exceptions; namespace StardewModdingAPI.Framework.Serialisation { /// Handles deserialisation of for crossplatform compatibility. internal class RectangleConverter : JsonConverter { /********* ** Accessors *********/ /// Whether this converter can write JSON. public override bool CanWrite => false; /********* ** Public methods *********/ /// Get whether this instance can convert the specified object type. /// The object type. public override bool CanConvert(Type objectType) { return objectType == typeof(Rectangle); } /// Reads the JSON representation of the object. /// The JSON reader. /// The object type. /// The object being read. /// The calling serializer. public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { // Linux/Mac: { "X": 1, "Y": 2, "Width": 3, "Height": 4 } // Windows: "{X:1 Y:2 Width:3 Height:4}" JToken token = JToken.Load(reader); switch (token.Type) { case JTokenType.Object: { JObject obj = (JObject)token; int x = obj.Value(nameof(Rectangle.X)); int y = obj.Value(nameof(Rectangle.Y)); int width = obj.Value(nameof(Rectangle.Width)); int height = obj.Value(nameof(Rectangle.Height)); return new Rectangle(x, y, width, height); } case JTokenType.String: { string str = token.Value(); if (string.IsNullOrWhiteSpace(str)) return Rectangle.Empty; var match = Regex.Match(str, @"^\{X:(?\d+) Y:(?\d+) Width:(?\d+) Height:(?\d+)\}$"); if (!match.Success) throw new SParseException($"Can't parse {typeof(Rectangle).Name} from {reader.Path}, invalid string format."); int x = Convert.ToInt32(match.Groups["x"].Value); int y = Convert.ToInt32(match.Groups["y"].Value); int width = Convert.ToInt32(match.Groups["width"].Value); int height = Convert.ToInt32(match.Groups["height"].Value); return new Rectangle(x, y, width, height); } default: throw new SParseException($"Can't parse {typeof(Rectangle).Name} from {reader.Path}, must be an object or string."); } } /// Writes the JSON representation of the object. /// The JSON writer. /// The value. /// The calling serializer. public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new InvalidOperationException("This converter does not write JSON."); } } }