1
0

Initial sync

This commit is contained in:
2024-03-15 14:44:21 +01:00
commit d2a1cabe35
59 changed files with 3783 additions and 0 deletions

185
Nbt/Serialization/NbtWriter.cs Executable file
View File

@@ -0,0 +1,185 @@
using System.Text;
using Nbt.Tag;
namespace Nbt.Serialization;
public interface INbtWriter : IDisposable
{
void WriteNamedTag(NamedTag namedTag);
void WriteTag(INbtTag tag);
void WriteTagType(NbtTagType tagType);
void WriteSByte(sbyte b);
void WriteShort(short s);
void WriteInt(int i);
void WriteLong(long l);
void WriteFloat(float f);
void WriteDouble(double d);
void WriteString(string s);
}
public sealed class NbtWriter(Stream stream, bool leaveOpen = false) : INbtWriter
{
private readonly Stream stream = stream;
private readonly bool leaveOpen = leaveOpen;
public Stream BaseStream => stream;
public static NbtWriter Create(Stream stream, Compression compression = Compression.None, bool leaveOpen = false) => compression switch
{
Compression.GZip => new(Utils.CreateGZipDeflater(stream, leaveOpen), false),
Compression.ZLib => new(Utils.CreateZLibDeflater(stream, leaveOpen), false),
Compression.LZ4 => new(Utils.CreateLZ4Deflater(stream, leaveOpen), false),
Compression.Auto => throw new ArgumentException($"{nameof(Compression.Auto)} is invalid for a writer", nameof(compression)),
_ => new(stream, leaveOpen)
};
public void Flush() => stream.Flush();
public void WriteBytes(byte[] buffer, int offset, int count) => stream.Write(buffer, offset, count);
public void WriteBytes(byte[] buffer) => stream.Write(buffer, 0, buffer.Length);
public void WriteBytes(ReadOnlySpan<byte> buffer) => stream.Write(buffer);
public void WriteByte(byte b) => stream.WriteByte(b);
private void WriteEndian(Span<byte> buffer)
{
if (BitConverter.IsLittleEndian)
{
for (var i = buffer.Length - 1; i >= 0; i--)
{
WriteByte(buffer[i]);
}
}
else
{
WriteBytes(buffer);
}
}
public void WriteSByte(sbyte b)
{
WriteByte((byte)b);
}
public void WriteUShort(ushort s)
{
Span<byte> buffer = stackalloc byte[sizeof(ushort)];
BitConverter.TryWriteBytes(buffer, s);
WriteEndian(buffer);
}
public void WriteShort(short s)
{
Span<byte> buffer = stackalloc byte[sizeof(short)];
BitConverter.TryWriteBytes(buffer, s);
WriteEndian(buffer);
}
public void WriteUInt(uint i)
{
Span<byte> buffer = stackalloc byte[sizeof(uint)];
BitConverter.TryWriteBytes(buffer, i);
WriteEndian(buffer);
}
public void WriteInt(int i)
{
Span<byte> buffer = stackalloc byte[sizeof(int)];
BitConverter.TryWriteBytes(buffer, i);
WriteEndian(buffer);
}
public void WriteULong(ulong l)
{
Span<byte> buffer = stackalloc byte[sizeof(ulong)];
BitConverter.TryWriteBytes(buffer, l);
WriteEndian(buffer);
}
public void WriteLong(long l)
{
Span<byte> buffer = stackalloc byte[sizeof(long)];
BitConverter.TryWriteBytes(buffer, l);
WriteEndian(buffer);
}
public void WriteFloat(float f)
{
Span<byte> buffer = stackalloc byte[sizeof(float)];
BitConverter.TryWriteBytes(buffer, f);
WriteEndian(buffer);
}
public void WriteDouble(double d)
{
Span<byte> buffer = stackalloc byte[sizeof(double)];
BitConverter.TryWriteBytes(buffer, d);
WriteEndian(buffer);
}
public void WriteString(string s)
{
WriteUShort((ushort)s.Length);
var buffer = Encoding.UTF8.GetBytes(s);
WriteBytes(buffer);
}
public void WriteNamedTag(NamedTag namedTag) => WriteNamedTag(namedTag.Name, namedTag.Tag);
public void WriteNamedTag(string tagName, INbtTag tag)
{
var tagType = NbtUtils.GetTagType(tag.Type);
WriteTagType(tag.Type);
WriteString(tagName);
tagType.Write(this, tag);
}
public void WriteTag(INbtTag tag)
{
var tagType = NbtUtils.GetTagType(tag.Type);
WriteTagType(tag.Type);
tagType.Write(this, tag);
}
public void WriteTagType(NbtTagType tagType) => WriteByte((byte)tagType);
#region IDisposable
private bool _disposedValue;
private void Dispose(bool disposing)
{
if (!_disposedValue)
{
if (disposing)
{
if (!leaveOpen)
{
stream.Dispose();
}
}
_disposedValue = true;
}
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
#endregion
}