640 lines
27 KiB
C#
Executable File
640 lines
27 KiB
C#
Executable File
using System.Text;
|
|
using System.Text.Json;
|
|
using Nbt.Tag;
|
|
|
|
namespace Nbt.Serialization;
|
|
|
|
public static class JsonNbt
|
|
{
|
|
private static readonly JsonEncodedText TypeProperty = JsonEncodedText.Encode("type");
|
|
private static readonly JsonEncodedText ValueProperty = JsonEncodedText.Encode("value");
|
|
|
|
#region Serialize lossless
|
|
|
|
public static string Serialize(INbtTag tag) => Serialize(serializer => serializer.Serialize(tag));
|
|
public static string Serialize(INbtList tag) => Serialize(serializer => serializer.Serialize(tag));
|
|
public static string Serialize(INbtCompound tag) => Serialize(serializer => serializer.Serialize(tag));
|
|
public static string Serialize(INbtArray tag) => Serialize(serializer => serializer.Serialize(tag));
|
|
public static string Serialize(INbtValue tag) => Serialize(serializer => serializer.Serialize(tag));
|
|
public static string Serialize(INbtArray<sbyte> tag) => Serialize(serializer => serializer.Serialize(tag));
|
|
public static string Serialize(INbtArray<int> tag) => Serialize(serializer => serializer.Serialize(tag));
|
|
public static string Serialize(INbtArray<long> tag) => Serialize(serializer => serializer.Serialize(tag));
|
|
public static string Serialize(INbtValue<sbyte> tag) => Serialize(serializer => serializer.Serialize(tag));
|
|
public static string Serialize(INbtValue<short> tag) => Serialize(serializer => serializer.Serialize(tag));
|
|
public static string Serialize(INbtValue<int> tag) => Serialize(serializer => serializer.Serialize(tag));
|
|
public static string Serialize(INbtValue<long> tag) => Serialize(serializer => serializer.Serialize(tag));
|
|
public static string Serialize(INbtValue<float> tag) => Serialize(serializer => serializer.Serialize(tag));
|
|
public static string Serialize(INbtValue<double> tag) => Serialize(serializer => serializer.Serialize(tag));
|
|
public static string Serialize(INbtValue<string> tag) => Serialize(serializer => serializer.Serialize(tag));
|
|
|
|
public static void Serialize(TextWriter writer, INbtTag tag) => Serialize(writer, serializer => serializer.Serialize(tag));
|
|
public static void Serialize(TextWriter writer, INbtList tag) => Serialize(writer, serializer => serializer.Serialize(tag));
|
|
public static void Serialize(TextWriter writer, INbtCompound tag) => Serialize(writer, serializer => serializer.Serialize(tag));
|
|
public static void Serialize(TextWriter writer, INbtArray tag) => Serialize(writer, serializer => serializer.Serialize(tag));
|
|
public static void Serialize(TextWriter writer, INbtValue tag) => Serialize(writer, serializer => serializer.Serialize(tag));
|
|
public static void Serialize(TextWriter writer, INbtArray<sbyte> tag) => Serialize(writer, serializer => serializer.Serialize(tag));
|
|
public static void Serialize(TextWriter writer, INbtArray<int> tag) => Serialize(writer, serializer => serializer.Serialize(tag));
|
|
public static void Serialize(TextWriter writer, INbtArray<long> tag) => Serialize(writer, serializer => serializer.Serialize(tag));
|
|
public static void Serialize(TextWriter writer, INbtValue<sbyte> tag) => Serialize(writer, serializer => serializer.Serialize(tag));
|
|
public static void Serialize(TextWriter writer, INbtValue<short> tag) => Serialize(writer, serializer => serializer.Serialize(tag));
|
|
public static void Serialize(TextWriter writer, INbtValue<int> tag) => Serialize(writer, serializer => serializer.Serialize(tag));
|
|
public static void Serialize(TextWriter writer, INbtValue<long> tag) => Serialize(writer, serializer => serializer.Serialize(tag));
|
|
public static void Serialize(TextWriter writer, INbtValue<float> tag) => Serialize(writer, serializer => serializer.Serialize(tag));
|
|
public static void Serialize(TextWriter writer, INbtValue<double> tag) => Serialize(writer, serializer => serializer.Serialize(tag));
|
|
public static void Serialize(TextWriter writer, INbtValue<string> tag) => Serialize(writer, serializer => serializer.Serialize(tag));
|
|
|
|
public static void Serialize(Stream stream, INbtTag tag) => Serialize(stream, serializer => serializer.Serialize(tag));
|
|
public static void Serialize(Stream stream, INbtList tag) => Serialize(stream, serializer => serializer.Serialize(tag));
|
|
public static void Serialize(Stream stream, INbtCompound tag) => Serialize(stream, serializer => serializer.Serialize(tag));
|
|
public static void Serialize(Stream stream, INbtArray tag) => Serialize(stream, serializer => serializer.Serialize(tag));
|
|
public static void Serialize(Stream stream, INbtValue tag) => Serialize(stream, serializer => serializer.Serialize(tag));
|
|
public static void Serialize(Stream stream, INbtArray<sbyte> tag) => Serialize(stream, serializer => serializer.Serialize(tag));
|
|
public static void Serialize(Stream stream, INbtArray<int> tag) => Serialize(stream, serializer => serializer.Serialize(tag));
|
|
public static void Serialize(Stream stream, INbtArray<long> tag) => Serialize(stream, serializer => serializer.Serialize(tag));
|
|
public static void Serialize(Stream stream, INbtValue<sbyte> tag) => Serialize(stream, serializer => serializer.Serialize(tag));
|
|
public static void Serialize(Stream stream, INbtValue<short> tag) => Serialize(stream, serializer => serializer.Serialize(tag));
|
|
public static void Serialize(Stream stream, INbtValue<int> tag) => Serialize(stream, serializer => serializer.Serialize(tag));
|
|
public static void Serialize(Stream stream, INbtValue<long> tag) => Serialize(stream, serializer => serializer.Serialize(tag));
|
|
public static void Serialize(Stream stream, INbtValue<float> tag) => Serialize(stream, serializer => serializer.Serialize(tag));
|
|
public static void Serialize(Stream stream, INbtValue<double> tag) => Serialize(stream, serializer => serializer.Serialize(tag));
|
|
public static void Serialize(Stream stream, INbtValue<string> tag) => Serialize(stream, serializer => serializer.Serialize(tag));
|
|
|
|
private static string Serialize(Action<Serializer> serialize)
|
|
{
|
|
using var writer = new StringWriter();
|
|
Serialize(writer, serialize);
|
|
return writer.ToString();
|
|
}
|
|
|
|
private static void Serialize(TextWriter writer, Action<Serializer> serialize)
|
|
{
|
|
using var stream = new MemoryStream();
|
|
Serialize(stream, serialize);
|
|
stream.Position = 0L;
|
|
|
|
using var reader = new StreamReader(stream, encoding: Encoding.UTF8, leaveOpen: true);
|
|
|
|
while (true)
|
|
{
|
|
var i = reader.Read();
|
|
|
|
if (i < 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
writer.Write((char)i);
|
|
}
|
|
}
|
|
|
|
private static void Serialize(Stream stream, Action<Serializer> serialize)
|
|
{
|
|
using var serializer = new Serializer(stream);
|
|
serialize(serializer);
|
|
}
|
|
|
|
private sealed class Serializer(Stream stream) : IDisposable
|
|
{
|
|
private readonly Utf8JsonWriter writer = new(stream, new() { Indented = true, SkipValidation = true });
|
|
|
|
public void Serialize(INbtTag tag)
|
|
{
|
|
switch (tag)
|
|
{
|
|
case INbtArray arrayTag:
|
|
Serialize(arrayTag);
|
|
break;
|
|
|
|
case INbtValue valueTag:
|
|
Serialize(valueTag);
|
|
break;
|
|
|
|
case INbtList listTag:
|
|
Serialize(listTag);
|
|
break;
|
|
|
|
case INbtCompound compoundTag:
|
|
Serialize(compoundTag);
|
|
break;
|
|
}
|
|
}
|
|
|
|
public void Serialize(INbtList tag)
|
|
{
|
|
using (new NbtObjectMeta(writer, tag.Type))
|
|
{
|
|
writer.WriteStartArray();
|
|
|
|
foreach (var entry in tag)
|
|
{
|
|
Serialize(entry);
|
|
}
|
|
|
|
writer.WriteEndArray();
|
|
}
|
|
}
|
|
|
|
public void Serialize(INbtCompound tag)
|
|
{
|
|
using (new NbtObjectMeta(writer, tag.Type))
|
|
{
|
|
writer.WriteStartObject();
|
|
|
|
foreach (var entry in tag as IEnumerable<NamedTag>)
|
|
{
|
|
writer.WritePropertyName(entry.Name);
|
|
Serialize(entry.Tag);
|
|
}
|
|
|
|
writer.WriteEndObject();
|
|
}
|
|
}
|
|
|
|
public void Serialize(INbtArray tag)
|
|
{
|
|
switch (tag)
|
|
{
|
|
case INbtArray<sbyte> byteArrayTag:
|
|
Serialize(byteArrayTag);
|
|
break;
|
|
|
|
case INbtArray<int> intArrayTag:
|
|
Serialize(intArrayTag);
|
|
break;
|
|
|
|
case INbtArray<long> longArrayTag:
|
|
Serialize(longArrayTag);
|
|
break;
|
|
}
|
|
}
|
|
|
|
public void Serialize(INbtValue valueTag)
|
|
{
|
|
switch (valueTag)
|
|
{
|
|
case INbtValue<sbyte> tag:
|
|
Serialize(tag);
|
|
break;
|
|
|
|
case INbtValue<short> tag:
|
|
Serialize(tag);
|
|
break;
|
|
|
|
case INbtValue<int> tag:
|
|
Serialize(tag);
|
|
break;
|
|
|
|
case INbtValue<long> tag:
|
|
Serialize(tag);
|
|
break;
|
|
|
|
case INbtValue<float> tag:
|
|
Serialize(tag);
|
|
break;
|
|
|
|
case INbtValue<double> tag:
|
|
Serialize(tag);
|
|
break;
|
|
|
|
case INbtValue<string> tag:
|
|
Serialize(tag);
|
|
break;
|
|
}
|
|
}
|
|
|
|
public void Serialize(INbtArray<sbyte> tag) => Serialize(tag, Serialize);
|
|
public void Serialize(INbtArray<int> tag) => Serialize(tag, Serialize);
|
|
public void Serialize(INbtArray<long> tag) => Serialize(tag, Serialize);
|
|
|
|
public void Serialize(INbtValue<sbyte> tag) => Serialize(tag, Serialize);
|
|
public void Serialize(INbtValue<short> tag) => Serialize(tag, Serialize);
|
|
public void Serialize(INbtValue<int> tag) => Serialize(tag, Serialize);
|
|
public void Serialize(INbtValue<long> tag) => Serialize(tag, Serialize);
|
|
public void Serialize(INbtValue<float> tag) => Serialize(tag, Serialize);
|
|
public void Serialize(INbtValue<double> tag) => Serialize(tag, Serialize);
|
|
public void Serialize(INbtValue<string> tag) => Serialize(tag, Serialize);
|
|
|
|
private void Serialize<T>(INbtArray<T> tag, Action<T> writeValue) where T : notnull
|
|
{
|
|
using (new NbtObjectMeta(writer, tag.Type))
|
|
{
|
|
writer.WriteStartArray();
|
|
|
|
foreach (var e in tag)
|
|
{
|
|
writeValue(e);
|
|
}
|
|
|
|
writer.WriteEndArray();
|
|
}
|
|
}
|
|
|
|
private void Serialize<T>(INbtValue<T> tag, Action<T> writeValue) where T : notnull
|
|
{
|
|
using (new NbtObjectMeta(writer, tag.Type))
|
|
{
|
|
writeValue(tag.Value);
|
|
}
|
|
}
|
|
|
|
private void Serialize(sbyte value) => writer.WriteNumberValue(value);
|
|
private void Serialize(short value) => writer.WriteNumberValue(value);
|
|
private void Serialize(int value) => writer.WriteNumberValue(value);
|
|
private void Serialize(long value) => writer.WriteNumberValue(value);
|
|
private void Serialize(float value) => writer.WriteNumberValue(value);
|
|
private void Serialize(double value) => writer.WriteNumberValue(value);
|
|
private void Serialize(string value) => writer.WriteStringValue(value);
|
|
|
|
public void Dispose()
|
|
{
|
|
writer.Dispose();
|
|
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
private readonly struct NbtObjectMeta : IDisposable
|
|
{
|
|
private readonly Utf8JsonWriter writer;
|
|
|
|
public NbtObjectMeta(Utf8JsonWriter writer, NbtTagType tagType)
|
|
{
|
|
this.writer = writer;
|
|
|
|
writer.WriteStartObject();
|
|
writer.WriteNumber(TypeProperty, (int)tagType);
|
|
writer.WritePropertyName(ValueProperty);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
writer.WriteEndObject();
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Serialize lossy
|
|
|
|
public static string ToJson(INbtTag tag) => ToJson(serializer => serializer.ToJson(tag));
|
|
public static string ToJson(INbtList tag) => ToJson(serializer => serializer.ToJson(tag));
|
|
public static string ToJson(INbtCompound tag) => ToJson(serializer => serializer.ToJson(tag));
|
|
public static string ToJson(INbtArray tag) => ToJson(serializer => serializer.ToJson(tag));
|
|
public static string ToJson(INbtValue tag) => ToJson(serializer => serializer.ToJson(tag));
|
|
public static string ToJson(INbtArray<sbyte> tag) => ToJson(serializer => serializer.ToJson(tag));
|
|
public static string ToJson(INbtArray<int> tag) => ToJson(serializer => serializer.ToJson(tag));
|
|
public static string ToJson(INbtArray<long> tag) => ToJson(serializer => serializer.ToJson(tag));
|
|
public static string ToJson(INbtValue<sbyte> tag) => ToJson(serializer => serializer.ToJson(tag));
|
|
public static string ToJson(INbtValue<short> tag) => ToJson(serializer => serializer.ToJson(tag));
|
|
public static string ToJson(INbtValue<int> tag) => ToJson(serializer => serializer.ToJson(tag));
|
|
public static string ToJson(INbtValue<long> tag) => ToJson(serializer => serializer.ToJson(tag));
|
|
public static string ToJson(INbtValue<float> tag) => ToJson(serializer => serializer.ToJson(tag));
|
|
public static string ToJson(INbtValue<double> tag) => ToJson(serializer => serializer.ToJson(tag));
|
|
public static string ToJson(INbtValue<string> tag) => ToJson(serializer => serializer.ToJson(tag));
|
|
|
|
public static void ToJson(TextWriter writer, INbtTag tag) => ToJson(writer, serializer => serializer.ToJson(tag));
|
|
public static void ToJson(TextWriter writer, INbtList tag) => ToJson(writer, serializer => serializer.ToJson(tag));
|
|
public static void ToJson(TextWriter writer, INbtCompound tag) => ToJson(writer, serializer => serializer.ToJson(tag));
|
|
public static void ToJson(TextWriter writer, INbtArray tag) => ToJson(writer, serializer => serializer.ToJson(tag));
|
|
public static void ToJson(TextWriter writer, INbtValue tag) => ToJson(writer, serializer => serializer.ToJson(tag));
|
|
public static void ToJson(TextWriter writer, INbtArray<sbyte> tag) => ToJson(writer, serializer => serializer.ToJson(tag));
|
|
public static void ToJson(TextWriter writer, INbtArray<int> tag) => ToJson(writer, serializer => serializer.ToJson(tag));
|
|
public static void ToJson(TextWriter writer, INbtArray<long> tag) => ToJson(writer, serializer => serializer.ToJson(tag));
|
|
public static void ToJson(TextWriter writer, INbtValue<sbyte> tag) => ToJson(writer, serializer => serializer.ToJson(tag));
|
|
public static void ToJson(TextWriter writer, INbtValue<short> tag) => ToJson(writer, serializer => serializer.ToJson(tag));
|
|
public static void ToJson(TextWriter writer, INbtValue<int> tag) => ToJson(writer, serializer => serializer.ToJson(tag));
|
|
public static void ToJson(TextWriter writer, INbtValue<long> tag) => ToJson(writer, serializer => serializer.ToJson(tag));
|
|
public static void ToJson(TextWriter writer, INbtValue<float> tag) => ToJson(writer, serializer => serializer.ToJson(tag));
|
|
public static void ToJson(TextWriter writer, INbtValue<double> tag) => ToJson(writer, serializer => serializer.ToJson(tag));
|
|
public static void ToJson(TextWriter writer, INbtValue<string> tag) => ToJson(writer, serializer => serializer.ToJson(tag));
|
|
|
|
public static void ToJson(Stream stream, INbtTag tag) => ToJson(stream, serializer => serializer.ToJson(tag));
|
|
public static void ToJson(Stream stream, INbtList tag) => ToJson(stream, serializer => serializer.ToJson(tag));
|
|
public static void ToJson(Stream stream, INbtCompound tag) => ToJson(stream, serializer => serializer.ToJson(tag));
|
|
public static void ToJson(Stream stream, INbtArray tag) => ToJson(stream, serializer => serializer.ToJson(tag));
|
|
public static void ToJson(Stream stream, INbtValue tag) => ToJson(stream, serializer => serializer.ToJson(tag));
|
|
public static void ToJson(Stream stream, INbtArray<sbyte> tag) => ToJson(stream, serializer => serializer.ToJson(tag));
|
|
public static void ToJson(Stream stream, INbtArray<int> tag) => ToJson(stream, serializer => serializer.ToJson(tag));
|
|
public static void ToJson(Stream stream, INbtArray<long> tag) => ToJson(stream, serializer => serializer.ToJson(tag));
|
|
public static void ToJson(Stream stream, INbtValue<sbyte> tag) => ToJson(stream, serializer => serializer.ToJson(tag));
|
|
public static void ToJson(Stream stream, INbtValue<short> tag) => ToJson(stream, serializer => serializer.ToJson(tag));
|
|
public static void ToJson(Stream stream, INbtValue<int> tag) => ToJson(stream, serializer => serializer.ToJson(tag));
|
|
public static void ToJson(Stream stream, INbtValue<long> tag) => ToJson(stream, serializer => serializer.ToJson(tag));
|
|
public static void ToJson(Stream stream, INbtValue<float> tag) => ToJson(stream, serializer => serializer.ToJson(tag));
|
|
public static void ToJson(Stream stream, INbtValue<double> tag) => ToJson(stream, serializer => serializer.ToJson(tag));
|
|
public static void ToJson(Stream stream, INbtValue<string> tag) => ToJson(stream, serializer => serializer.ToJson(tag));
|
|
|
|
private static string ToJson(Action<LossySerializer> serialize)
|
|
{
|
|
using var writer = new StringWriter();
|
|
ToJson(writer, serialize);
|
|
return writer.ToString();
|
|
}
|
|
|
|
private static void ToJson(TextWriter writer, Action<LossySerializer> serialize)
|
|
{
|
|
using var stream = new MemoryStream();
|
|
ToJson(stream, serialize);
|
|
stream.Position = 0L;
|
|
|
|
using var reader = new StreamReader(stream, encoding: Encoding.UTF8, leaveOpen: true);
|
|
|
|
while (true)
|
|
{
|
|
var i = reader.Read();
|
|
|
|
if (i < 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
writer.Write((char)i);
|
|
}
|
|
}
|
|
|
|
private static void ToJson(Stream stream, Action<LossySerializer> serialize)
|
|
{
|
|
using var serializer = new LossySerializer(stream);
|
|
serialize(serializer);
|
|
}
|
|
|
|
private sealed class LossySerializer(Stream stream) : IDisposable
|
|
{
|
|
private readonly Utf8JsonWriter writer = new(stream, new() { Indented = true, SkipValidation = true });
|
|
|
|
public void ToJson(INbtTag tag)
|
|
{
|
|
switch (tag)
|
|
{
|
|
case INbtArray arrayTag:
|
|
ToJson(arrayTag);
|
|
break;
|
|
|
|
case INbtValue valueTag:
|
|
ToJson(valueTag);
|
|
break;
|
|
|
|
case INbtList listTag:
|
|
ToJson(listTag);
|
|
break;
|
|
|
|
case INbtCompound compoundTag:
|
|
ToJson(compoundTag);
|
|
break;
|
|
}
|
|
}
|
|
|
|
public void ToJson(INbtList tag)
|
|
{
|
|
writer.WriteStartArray();
|
|
|
|
foreach (var entry in tag)
|
|
{
|
|
ToJson(entry);
|
|
}
|
|
|
|
writer.WriteEndArray();
|
|
}
|
|
|
|
public void ToJson(INbtCompound tag)
|
|
{
|
|
writer.WriteStartObject();
|
|
|
|
foreach (var entry in tag as IEnumerable<NamedTag>)
|
|
{
|
|
writer.WritePropertyName(entry.Name);
|
|
ToJson(entry.Tag);
|
|
}
|
|
|
|
writer.WriteEndObject();
|
|
}
|
|
|
|
public void ToJson(INbtArray tag)
|
|
{
|
|
switch (tag)
|
|
{
|
|
case INbtArray<sbyte> byteArrayTag:
|
|
ToJson(byteArrayTag);
|
|
break;
|
|
|
|
case INbtArray<int> intArrayTag:
|
|
ToJson(intArrayTag);
|
|
break;
|
|
|
|
case INbtArray<long> longArrayTag:
|
|
ToJson(longArrayTag);
|
|
break;
|
|
}
|
|
}
|
|
|
|
public void ToJson(INbtValue valueTag)
|
|
{
|
|
switch (valueTag)
|
|
{
|
|
case INbtValue<sbyte> tag:
|
|
ToJson(tag);
|
|
break;
|
|
|
|
case INbtValue<short> tag:
|
|
ToJson(tag);
|
|
break;
|
|
|
|
case INbtValue<int> tag:
|
|
ToJson(tag);
|
|
break;
|
|
|
|
case INbtValue<long> tag:
|
|
ToJson(tag);
|
|
break;
|
|
|
|
case INbtValue<float> tag:
|
|
ToJson(tag);
|
|
break;
|
|
|
|
case INbtValue<double> tag:
|
|
ToJson(tag);
|
|
break;
|
|
|
|
case INbtValue<string> tag:
|
|
ToJson(tag);
|
|
break;
|
|
}
|
|
}
|
|
|
|
public void ToJson(INbtArray<sbyte> tag) => ToJson(tag, ToJson);
|
|
public void ToJson(INbtArray<int> tag) => ToJson(tag, ToJson);
|
|
public void ToJson(INbtArray<long> tag) => ToJson(tag, ToJson);
|
|
|
|
public void ToJson(INbtValue<sbyte> tag) => ToJson(tag, ToJson);
|
|
public void ToJson(INbtValue<short> tag) => ToJson(tag, ToJson);
|
|
public void ToJson(INbtValue<int> tag) => ToJson(tag, ToJson);
|
|
public void ToJson(INbtValue<long> tag) => ToJson(tag, ToJson);
|
|
public void ToJson(INbtValue<float> tag) => ToJson(tag, ToJson);
|
|
public void ToJson(INbtValue<double> tag) => ToJson(tag, ToJson);
|
|
public void ToJson(INbtValue<string> tag) => ToJson(tag, ToJson);
|
|
|
|
private void ToJson<T>(INbtArray<T> tag, Action<T> writeValue) where T : notnull
|
|
{
|
|
writer.WriteStartArray();
|
|
|
|
foreach (var e in tag)
|
|
{
|
|
writeValue(e);
|
|
}
|
|
|
|
writer.WriteEndArray();
|
|
}
|
|
|
|
private static void ToJson<T>(INbtValue<T> tag, Action<T> writeValue) where T : notnull => writeValue(tag.Value);
|
|
|
|
private void ToJson(sbyte value) => writer.WriteNumberValue(value);
|
|
private void ToJson(short value) => writer.WriteNumberValue(value);
|
|
private void ToJson(int value) => writer.WriteNumberValue(value);
|
|
private void ToJson(long value) => writer.WriteNumberValue(value);
|
|
private void ToJson(float value) => writer.WriteNumberValue(value);
|
|
private void ToJson(double value) => writer.WriteNumberValue(value);
|
|
private void ToJson(string value) => writer.WriteStringValue(value);
|
|
|
|
public void Dispose()
|
|
{
|
|
writer.Dispose();
|
|
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Deserialize
|
|
|
|
public static INbtTag Deserialize(string s)
|
|
{
|
|
using var reader = new StringReader(s);
|
|
return Deserialize(reader);
|
|
}
|
|
|
|
public static INbtTag Deserialize(Stream stream)
|
|
{
|
|
var doc = JsonDocument.Parse(stream);
|
|
return Deserialize(doc.RootElement);
|
|
}
|
|
|
|
public static INbtTag Deserialize(TextReader reader)
|
|
{
|
|
using var stream = new MemoryStream();
|
|
|
|
using (var writer = new StreamWriter(stream, encoding: Encoding.UTF8, leaveOpen: true))
|
|
{
|
|
while (true)
|
|
{
|
|
var i = reader.Read();
|
|
|
|
if (i < 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
writer.Write((char)i);
|
|
}
|
|
}
|
|
|
|
stream.Position = 0L;
|
|
|
|
return Deserialize(stream);
|
|
}
|
|
|
|
private static INbtTag Deserialize(JsonElement serialized)
|
|
{
|
|
var tagType = (NbtTagType)serialized.GetProperty(TypeProperty.Value).GetByte();
|
|
var value = serialized.GetProperty(ValueProperty.Value);
|
|
|
|
switch (tagType)
|
|
{
|
|
case NbtTagType.End:
|
|
throw new NbtException($"Invalid tag type: {Enum.GetName(tagType)}");
|
|
|
|
case NbtTagType.Byte:
|
|
return new NbtByte(value.GetSByte());
|
|
case NbtTagType.Short:
|
|
return new NbtShort(value.GetInt16());
|
|
case NbtTagType.Int:
|
|
return new NbtInt(value.GetInt32());
|
|
case NbtTagType.Long:
|
|
return new NbtLong(value.GetInt64());
|
|
case NbtTagType.Float:
|
|
return new NbtFloat(value.GetSingle());
|
|
case NbtTagType.Double:
|
|
return new NbtDouble(value.GetDouble());
|
|
case NbtTagType.String:
|
|
return new NbtString(value.GetString() ?? throw new NbtException("Null string value"));
|
|
|
|
case NbtTagType.ByteArray:
|
|
{
|
|
var bytes = new sbyte[value.GetArrayLength()];
|
|
var i = 0;
|
|
|
|
foreach (var element in value.EnumerateArray())
|
|
{
|
|
bytes[i++] = element.GetSByte();
|
|
}
|
|
|
|
return new NbtByteArray(bytes);
|
|
}
|
|
|
|
case NbtTagType.IntArray:
|
|
{
|
|
var ints = new int[value.GetArrayLength()];
|
|
var i = 0;
|
|
|
|
foreach (var element in value.EnumerateArray())
|
|
{
|
|
ints[i++] = element.GetInt32();
|
|
}
|
|
|
|
return new NbtIntArray(ints);
|
|
}
|
|
|
|
case NbtTagType.LongArray:
|
|
{
|
|
var longs = new long[value.GetArrayLength()];
|
|
var i = 0;
|
|
|
|
foreach (var element in value.EnumerateArray())
|
|
{
|
|
longs[i++] = element.GetInt64();
|
|
}
|
|
|
|
return new NbtLongArray(longs);
|
|
}
|
|
|
|
case NbtTagType.List:
|
|
{
|
|
var list = new NbtList();
|
|
|
|
foreach (var element in value.EnumerateArray())
|
|
{
|
|
list.Add(Deserialize(element));
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
case NbtTagType.Compound:
|
|
{
|
|
var compound = new NbtCompound();
|
|
|
|
foreach (var property in value.EnumerateObject())
|
|
{
|
|
compound.Add(property.Name, Deserialize(property.Value));
|
|
}
|
|
|
|
return compound;
|
|
}
|
|
|
|
default:
|
|
throw new UnknownTagTypeException(tagType);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
} |