AssetRipper / AssemblyDumper

Assembly Source Generator for AssetRipper

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Json Serialization

ds5678 opened this issue · comments

#nullable disable

namespace AssetRipper.AssemblyDumper.InjectedTypes;

public static class JsonConstants
{
	/// <summary>
	/// The key used to specify the style of a map or sequence.
	/// </summary>
	public const string Style = "@style";

	/// <summary>
	/// The key used to specify that an array of key-value pairs should be treated as a map.
	/// </summary>
	public const string Map = "@map";

	/// <summary>
	/// The key used to specify that an object should be treated as a pair.
	/// </summary>
	public const string Pair = "@pair";

	/// <summary>
	/// The key used to specify that an array of values should be treated as a sequence.
	/// </summary>
	public const string Sequence = "@sequence";

	/// <summary>
	/// The set of values that can be used for the <see cref="Style"/> key.
	/// </summary>
	public static class Styles
	{
		/// <summary>
		/// Usable on both maps and sequences.
		/// </summary>
		public const string Block = "Block";

		/// <summary>
		/// Usable only on sequences.
		/// </summary>
		public const string BlockCurve = "BlockCurve";

		/// <summary>
		/// Usable on both maps and sequences.
		/// </summary>
		public const string Flow = "Flow";

		/// <summary>
		/// Usable only on sequences.
		/// </summary>
		public const string Raw = "Raw";
	}
}

#nullable enable
#nullable disable

using System.Runtime.CompilerServices;
using System.Text.Json.Nodes;

namespace AssetRipper.AssemblyDumper.InjectedTypes;

internal static class JsonHelper
{
	/// <summary>
	/// Maps appear to have default constructors, but they actually have an options parameter that is null by default.
	/// </summary>
	/// <returns>A new <see cref="JsonObject"/></returns>
	public static JsonObject CreateMap() => new();

	/// <summary>
	/// Sequences appear to have default constructors, but they actually have an options parameter that is null by default.
	/// </summary>
	/// <returns></returns>
	public static JsonArray CreateSequence() => new();

	/// <summary>
	/// There is a generic version of <see cref="JsonArray.Add(JsonNode)"/>, but it should not be used.
	/// </summary>
	/// <param name="sequence"></param>
	/// <param name="node"></param>
	public static void Append(this JsonArray sequence, JsonNode node) => sequence.Add(node);

	public static void Append(this JsonObject map, string key, JsonNode node) => map.Add(key, node);

	//There is exactly one overload of JsonValue.Create for each primitive type.
	//Each one is a nongeneric static method that takes a value and a set of options, in that order.
	//The options can and should be null.

	public static JsonValue CreateBoolean(bool value) => JsonValue.Create(value);

	public static JsonValue CreateChar(char value) => JsonValue.Create(value);

	public static JsonValue CreateByte(byte value) => JsonValue.Create(value);

	public static JsonValue CreateSByte(sbyte value) => JsonValue.Create(value);

	public static JsonValue CreateUShort(ushort value) => JsonValue.Create(value);

	public static JsonValue CreateShort(short value) => JsonValue.Create(value);

	public static JsonValue CreateUInt(uint value) => JsonValue.Create(value);

	public static JsonValue CreateInt(int value) => JsonValue.Create(value);

	public static JsonValue CreateULong(ulong value) => JsonValue.Create(value);

	public static JsonValue CreateLong(long value) => JsonValue.Create(value);

	public static JsonValue CreateFloat(float value) => JsonValue.Create(value);

	public static JsonValue CreateDouble(double value) => JsonValue.Create(value);

	public static JsonValue CreateString(string value) => JsonValue.Create(value);

	public static JsonValue CreateUtf8String(Utf8String value) => JsonValue.Create(value.String);

	/// <summary>
	/// Create a <see cref="JsonNode"/> for a byte array.
	/// </summary>
	/// <remarks>
	/// This is NOT base 64 encoded, but instead a hex string.
	/// AssetRipper 0.3.4.0 and earlier used lower case hex digits,
	/// but <see cref="Convert.ToHexString(ReadOnlySpan{byte})"/> uses upper case hex digits and is very efficient.
	/// </remarks>
	/// <param name="value">The array of bytes to be encoded.</param>
	/// <returns>A <see cref="JsonValue"/> containing the hex string.</returns>
	public static JsonValue CreateByteArray(byte[] value)
	{
		//Converting to span eliminates a null check.
		return JsonValue.Create(Convert.ToHexString(new ReadOnlySpan<byte>(value)));
	}

	public static JsonValue Create<T>(T value)
	{
		if (typeof(T) == typeof(bool))
		{
			return JsonValue.Create(Unsafe.As<T, bool>(ref value));
		}
		else if (typeof(T) == typeof(char))
		{
			return JsonValue.Create(Unsafe.As<T, char>(ref value));
		}
		else if (typeof(T) == typeof(byte))
		{
			return JsonValue.Create(Unsafe.As<T, byte>(ref value));
		}
		else if (typeof(T) == typeof(sbyte))
		{
			return JsonValue.Create(Unsafe.As<T, sbyte>(ref value));
		}
		else if (typeof(T) == typeof(ushort))
		{
			return JsonValue.Create(Unsafe.As<T, ushort>(ref value));
		}
		else if (typeof(T) == typeof(short))
		{
			return JsonValue.Create(Unsafe.As<T, short>(ref value));
		}
		else if (typeof(T) == typeof(uint))
		{
			return JsonValue.Create(Unsafe.As<T, uint>(ref value));
		}
		else if (typeof(T) == typeof(int))
		{
			return JsonValue.Create(Unsafe.As<T, int>(ref value));
		}
		else if (typeof(T) == typeof(ulong))
		{
			return JsonValue.Create(Unsafe.As<T, ulong>(ref value));
		}
		else if (typeof(T) == typeof(long))
		{
			return JsonValue.Create(Unsafe.As<T, long>(ref value));
		}
		else if (typeof(T) == typeof(float))
		{
			return JsonValue.Create(Unsafe.As<T, float>(ref value));
		}
		else if (typeof(T) == typeof(double))
		{
			return JsonValue.Create(Unsafe.As<T, double>(ref value));
		}
		else if (typeof(T) == typeof(string))
		{
			return JsonValue.Create(Unsafe.As<T, string>(ref value));
		}
		else if (typeof(T) == typeof(Utf8String))
		{
			return JsonValue.Create(Unsafe.As<T, Utf8String>(ref value).String);
		}
		else if (typeof(T) == typeof(byte[]))
		{
			return CreateByteArray(Unsafe.As<T, byte[]>(ref value));
		}
		else
		{
			return ThrowNotSupportException();
		}
		[DoesNotReturn]
		static JsonValue ThrowNotSupportException() => throw new NotSupportedException($"Type {typeof(T)} is not supported.");
	}

	public static void AppendTypelessData(this JsonObject map, string name, byte[] data)
	{
		const string TypelessdataName = "_typelessdata";
		map.Add(name, data.Length);
		map.Add(TypelessdataName, CreateByteArray(data));
	}
}

#nullable enable

I think this has been enabled by d67af04