1
0
Files
named-binary-tag/Nbt/Serialization/SNbt.cs
2024-03-15 14:44:21 +01:00

402 lines
18 KiB
C#
Executable File

namespace Nbt.Serialization;
using System.Globalization;
using Nbt.Tag;
public static class SNbt
{
#region Serialize
public enum SerializationStyle
{
Compact, Spaced, Indented
}
public class SerializerOptions
{
public static readonly SerializerOptions Default = new();
public SerializationStyle Style { get; init; } = SerializationStyle.Compact;
public bool AlwaysQuoteTagNames { get; init; } = false;
// public bool AlwaysQuoteStringTags { get; init; } = false;
}
public static string Serialize(INbtTag tag, SerializerOptions? options = null) => Serialize(options, serializer => serializer.Serialize(tag));
public static string Serialize(NamedTag tag, SerializerOptions? options = null) => Serialize(options, serializer => serializer.Serialize(tag));
public static string Serialize(INbtList tag, SerializerOptions? options = null) => Serialize(options, serializer => serializer.Serialize(tag));
public static string Serialize(INbtCompound tag, SerializerOptions? options = null) => Serialize(options, serializer => serializer.Serialize(tag));
public static string Serialize(INbtArray tag, SerializerOptions? options = null) => Serialize(options, serializer => serializer.Serialize(tag));
public static string Serialize(INbtValue tag, SerializerOptions? options = null) => Serialize(options, serializer => serializer.Serialize(tag));
public static string Serialize(INbtArray<sbyte> tag, SerializerOptions? options = null) => Serialize(options, serializer => serializer.Serialize(tag));
public static string Serialize(INbtArray<int> tag, SerializerOptions? options = null) => Serialize(options, serializer => serializer.Serialize(tag));
public static string Serialize(INbtArray<long> tag, SerializerOptions? options = null) => Serialize(options, serializer => serializer.Serialize(tag));
public static string Serialize(INbtValue<sbyte> tag, SerializerOptions? options = null) => Serialize(options, serializer => serializer.Serialize(tag));
public static string Serialize(INbtValue<short> tag, SerializerOptions? options = null) => Serialize(options, serializer => serializer.Serialize(tag));
public static string Serialize(INbtValue<int> tag, SerializerOptions? options = null) => Serialize(options, serializer => serializer.Serialize(tag));
public static string Serialize(INbtValue<long> tag, SerializerOptions? options = null) => Serialize(options, serializer => serializer.Serialize(tag));
public static string Serialize(INbtValue<float> tag, SerializerOptions? options = null) => Serialize(options, serializer => serializer.Serialize(tag));
public static string Serialize(INbtValue<double> tag, SerializerOptions? options = null) => Serialize(options, serializer => serializer.Serialize(tag));
public static string Serialize(INbtValue<string> tag, SerializerOptions? options = null) => Serialize(options, serializer => serializer.Serialize(tag));
public static void Serialize(TextWriter writer, INbtTag tag, SerializerOptions? options = null) => Serialize(writer, options, serializer => serializer.Serialize(tag));
public static void Serialize(TextWriter writer, NamedTag tag, SerializerOptions? options = null) => Serialize(writer, options, serializer => serializer.Serialize(tag));
public static void Serialize(TextWriter writer, INbtList tag, SerializerOptions? options = null) => Serialize(writer, options, serializer => serializer.Serialize(tag));
public static void Serialize(TextWriter writer, INbtCompound tag, SerializerOptions? options = null) => Serialize(writer, options, serializer => serializer.Serialize(tag));
public static void Serialize(TextWriter writer, INbtArray tag, SerializerOptions? options = null) => Serialize(writer, options, serializer => serializer.Serialize(tag));
public static void Serialize(TextWriter writer, INbtValue tag, SerializerOptions? options = null) => Serialize(writer, options, serializer => serializer.Serialize(tag));
public static void Serialize(TextWriter writer, INbtArray<sbyte> tag, SerializerOptions? options = null) => Serialize(writer, options, serializer => serializer.Serialize(tag));
public static void Serialize(TextWriter writer, INbtArray<int> tag, SerializerOptions? options = null) => Serialize(writer, options, serializer => serializer.Serialize(tag));
public static void Serialize(TextWriter writer, INbtArray<long> tag, SerializerOptions? options = null) => Serialize(writer, options, serializer => serializer.Serialize(tag));
public static void Serialize(TextWriter writer, INbtValue<sbyte> tag, SerializerOptions? options = null) => Serialize(writer, options, serializer => serializer.Serialize(tag));
public static void Serialize(TextWriter writer, INbtValue<short> tag, SerializerOptions? options = null) => Serialize(writer, options, serializer => serializer.Serialize(tag));
public static void Serialize(TextWriter writer, INbtValue<int> tag, SerializerOptions? options = null) => Serialize(writer, options, serializer => serializer.Serialize(tag));
public static void Serialize(TextWriter writer, INbtValue<long> tag, SerializerOptions? options = null) => Serialize(writer, options, serializer => serializer.Serialize(tag));
public static void Serialize(TextWriter writer, INbtValue<float> tag, SerializerOptions? options = null) => Serialize(writer, options, serializer => serializer.Serialize(tag));
public static void Serialize(TextWriter writer, INbtValue<double> tag, SerializerOptions? options = null) => Serialize(writer, options, serializer => serializer.Serialize(tag));
public static void Serialize(TextWriter writer, INbtValue<string> tag, SerializerOptions? options = null) => Serialize(writer, options, serializer => serializer.Serialize(tag));
public static void Serialize(Stream stream, INbtTag tag, SerializerOptions? options = null) => Serialize(stream, options, serializer => serializer.Serialize(tag));
public static void Serialize(Stream stream, NamedTag tag, SerializerOptions? options = null) => Serialize(stream, options, serializer => serializer.Serialize(tag));
public static void Serialize(Stream stream, INbtList tag, SerializerOptions? options = null) => Serialize(stream, options, serializer => serializer.Serialize(tag));
public static void Serialize(Stream stream, INbtCompound tag, SerializerOptions? options = null) => Serialize(stream, options, serializer => serializer.Serialize(tag));
public static void Serialize(Stream stream, INbtArray tag, SerializerOptions? options = null) => Serialize(stream, options, serializer => serializer.Serialize(tag));
public static void Serialize(Stream stream, INbtValue tag, SerializerOptions? options = null) => Serialize(stream, options, serializer => serializer.Serialize(tag));
public static void Serialize(Stream stream, INbtArray<sbyte> tag, SerializerOptions? options = null) => Serialize(stream, options, serializer => serializer.Serialize(tag));
public static void Serialize(Stream stream, INbtArray<int> tag, SerializerOptions? options = null) => Serialize(stream, options, serializer => serializer.Serialize(tag));
public static void Serialize(Stream stream, INbtArray<long> tag, SerializerOptions? options = null) => Serialize(stream, options, serializer => serializer.Serialize(tag));
public static void Serialize(Stream stream, INbtValue<sbyte> tag, SerializerOptions? options = null) => Serialize(stream, options, serializer => serializer.Serialize(tag));
public static void Serialize(Stream stream, INbtValue<short> tag, SerializerOptions? options = null) => Serialize(stream, options, serializer => serializer.Serialize(tag));
public static void Serialize(Stream stream, INbtValue<int> tag, SerializerOptions? options = null) => Serialize(stream, options, serializer => serializer.Serialize(tag));
public static void Serialize(Stream stream, INbtValue<long> tag, SerializerOptions? options = null) => Serialize(stream, options, serializer => serializer.Serialize(tag));
public static void Serialize(Stream stream, INbtValue<float> tag, SerializerOptions? options = null) => Serialize(stream, options, serializer => serializer.Serialize(tag));
public static void Serialize(Stream stream, INbtValue<double> tag, SerializerOptions? options = null) => Serialize(stream, options, serializer => serializer.Serialize(tag));
public static void Serialize(Stream stream, INbtValue<string> tag, SerializerOptions? options = null) => Serialize(stream, options, serializer => serializer.Serialize(tag));
private static void Serialize(TextWriter writer, SerializerOptions? options, Action<Serializer> serialize)
{
var serializer = new Serializer(writer, options);
serialize(serializer);
}
private static void Serialize(Stream stream, SerializerOptions? options, Action<Serializer> serialize)
{
using var writer = new StreamWriter(stream, leaveOpen: true);
Serialize(writer, options, serialize);
}
private static string Serialize(SerializerOptions? options, Action<Serializer> serialize)
{
using var writer = new StringWriter();
Serialize(writer, options, serialize);
return writer.ToString();
}
private sealed class Serializer(TextWriter writer, SerializerOptions? options)
{
private readonly TextWriter writer = writer;
private readonly SerializerOptions options = options ?? SerializerOptions.Default;
private uint depth = 0u;
private void WriteIndent()
{
for (var i = 0u; i < depth; i++)
{
writer.Write(" ");
}
}
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(NamedTag namedTag)
{
if (!string.IsNullOrEmpty(namedTag.Name))
{
writer.Write(NbtUtils.QuoteString(namedTag.Name, onlyIfNeeded: !options.AlwaysQuoteTagNames));
writer.Write(':');
if (options.Style is not SerializationStyle.Compact)
{
writer.Write(' ');
}
}
Serialize(namedTag.Tag);
}
public void Serialize(INbtList tag)
{
writer.Write('[');
depth++;
var style = options.Style;
var isSpaced = style is SerializationStyle.Spaced;
var isIndented = style is SerializationStyle.Indented;
var b = false;
foreach (var entry in tag)
{
if (b)
{
writer.Write(',');
if (isSpaced)
{
writer.Write(' ');
}
}
else
{
b = true;
}
if (isIndented)
{
writer.WriteLine();
WriteIndent();
}
Serialize(entry);
}
depth--;
if (b && isIndented)
{
writer.WriteLine();
WriteIndent();
}
writer.Write(']');
}
public void Serialize(INbtCompound tag)
{
writer.Write('{');
depth++;
var style = options.Style;
var isSpaced = style is SerializationStyle.Spaced;
var isIndented = style is SerializationStyle.Indented;
var b = false;
foreach (var entry in tag as IEnumerable<NamedTag>)
{
if (b)
{
writer.Write(',');
if (isSpaced)
{
writer.Write(' ');
}
}
else
{
b = true;
}
if (isIndented)
{
writer.WriteLine();
WriteIndent();
}
Serialize(entry);
}
depth--;
if (b && isIndented)
{
writer.WriteLine();
WriteIndent();
}
writer.Write('}');
}
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, 'B', Serialize);
public void Serialize(INbtArray<int> tag) => Serialize(tag, 'I', Serialize);
public void Serialize(INbtArray<long> tag) => Serialize(tag, 'L', Serialize);
public void Serialize(INbtValue<sbyte> tag) => Serialize(tag.Value);
public void Serialize(INbtValue<short> tag) => Serialize(tag.Value);
public void Serialize(INbtValue<int> tag) => Serialize(tag.Value);
public void Serialize(INbtValue<long> tag) => Serialize(tag.Value);
public void Serialize(INbtValue<float> tag) => Serialize(tag.Value);
public void Serialize(INbtValue<double> tag) => Serialize(tag.Value);
public void Serialize(INbtValue<string> tag) => Serialize(tag.Value);
private void Serialize<T>(INbtArray<T> tag, char decorator, Action<T> writeValue) where T : notnull
{
writer.Write('[');
writer.Write(decorator);
writer.Write(';');
if (tag.Value.Length > 0)
{
var isNotCompact = options.Style is not SerializationStyle.Compact;
if (isNotCompact)
{
writer.Write(' ');
}
var b = false;
foreach (var e in tag)
{
if (b)
{
writer.Write(',');
if (isNotCompact)
{
writer.Write(' ');
}
}
else
{
b = true;
}
writeValue(e);
}
}
writer.Write(']');
}
private void Serialize(sbyte value)
{
writer.Write(value.ToString(CultureInfo.InvariantCulture));
writer.Write('b');
}
private void Serialize(short value)
{
writer.Write(value.ToString(CultureInfo.InvariantCulture));
writer.Write('s');
}
private void Serialize(int value)
{
writer.Write(value.ToString(CultureInfo.InvariantCulture));
}
private void Serialize(long value)
{
writer.Write(value.ToString(CultureInfo.InvariantCulture));
writer.Write('L');
}
private void Serialize(float value)
{
writer.Write(value.ToString(CultureInfo.InvariantCulture));
if (float.IsFinite(value))
{
writer.Write('F');
}
}
private void Serialize(double value)
{
writer.Write(value.ToString(CultureInfo.InvariantCulture));
if (double.IsFinite(value))
{
writer.Write('D');
}
}
private void Serialize(string value)
{
// Utils.Quote(writer, value, NbtUtils.DOUBLE_QUOTE_CHAR, NbtUtils.ESCAPE_CHAR);
writer.Write(NbtUtils.QuoteString(value, onlyIfNeeded: false));
}
}
#endregion
}