Implemented TagWriter class to support Java, Bedrock file, and Bedrock network specs
This commit is contained in:
parent
b34702d06c
commit
3c12e34eec
|
@ -0,0 +1,44 @@
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.Reflection;
|
||||||
|
using Xunit;
|
||||||
|
using Xunit.Abstractions;
|
||||||
|
|
||||||
|
namespace SharpNBT.Tests
|
||||||
|
{
|
||||||
|
public class ReadWriteTest
|
||||||
|
{
|
||||||
|
private readonly ITestOutputHelper output;
|
||||||
|
|
||||||
|
public ReadWriteTest(ITestOutputHelper output)
|
||||||
|
{
|
||||||
|
this.output = output;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Stream GetFile(string filename)
|
||||||
|
{
|
||||||
|
var assembly = Assembly.GetExecutingAssembly();
|
||||||
|
return assembly.GetManifestResourceStream($"SharpNBT.Tests.Data.{filename}");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ReadUncompressed()
|
||||||
|
{
|
||||||
|
using var stream = GetFile("hello_world.nbt");
|
||||||
|
using var reader = new TagReader(stream, FormatOptions.Java);
|
||||||
|
var compound = reader.ReadTag<CompoundTag>();
|
||||||
|
output.WriteLine(compound.PrettyPrinted());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ReadGZipped()
|
||||||
|
{
|
||||||
|
using var stream = GetFile("bigtest.nbt");
|
||||||
|
using var gzip = new GZipStream(stream, CompressionMode.Decompress);
|
||||||
|
using var reader = new TagReader(gzip, FormatOptions.Java);
|
||||||
|
var compound = reader.ReadTag<CompoundTag>();
|
||||||
|
output.WriteLine(compound.PrettyPrinted());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -56,7 +56,10 @@ namespace SharpNBT
|
||||||
public virtual void WriteShort(ShortTag tag)
|
public virtual void WriteShort(ShortTag tag)
|
||||||
{
|
{
|
||||||
WriteTypeAndName(tag);
|
WriteTypeAndName(tag);
|
||||||
BaseStream.Write(GetBytes(tag.Value), 0, sizeof(short));
|
if (UseVarInt)
|
||||||
|
VarInt.Write(BaseStream, tag.Value, ZigZagEncoding);
|
||||||
|
else
|
||||||
|
BaseStream.Write(GetBytes(tag.Value), 0, sizeof(short));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -66,7 +69,10 @@ namespace SharpNBT
|
||||||
public virtual void WriteInt(IntTag tag)
|
public virtual void WriteInt(IntTag tag)
|
||||||
{
|
{
|
||||||
WriteTypeAndName(tag);
|
WriteTypeAndName(tag);
|
||||||
BaseStream.Write(GetBytes(tag.Value), 0, sizeof(int));
|
if (UseVarInt)
|
||||||
|
VarInt.Write(BaseStream, tag.Value, ZigZagEncoding);
|
||||||
|
else
|
||||||
|
BaseStream.Write(GetBytes(tag.Value), 0, sizeof(int));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -76,7 +82,10 @@ namespace SharpNBT
|
||||||
public virtual void WriteLong(LongTag tag)
|
public virtual void WriteLong(LongTag tag)
|
||||||
{
|
{
|
||||||
WriteTypeAndName(tag);
|
WriteTypeAndName(tag);
|
||||||
BaseStream.Write(GetBytes(tag.Value), 0, sizeof(long));
|
if (UseVarInt)
|
||||||
|
VarLong.Write(BaseStream, tag.Value, ZigZagEncoding);
|
||||||
|
else
|
||||||
|
BaseStream.Write(GetBytes(tag.Value), 0, sizeof(long));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -116,7 +125,7 @@ namespace SharpNBT
|
||||||
public virtual void WriteByteArray(ByteArrayTag tag)
|
public virtual void WriteByteArray(ByteArrayTag tag)
|
||||||
{
|
{
|
||||||
WriteTypeAndName(tag);
|
WriteTypeAndName(tag);
|
||||||
BaseStream.Write(GetBytes(tag.Count), 0, sizeof(int));
|
WriteCount(tag);
|
||||||
BaseStream.Write(tag.ToArray(), 0, tag.Count);
|
BaseStream.Write(tag.ToArray(), 0, tag.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,15 +136,21 @@ namespace SharpNBT
|
||||||
public virtual void WriteIntArray(IntArrayTag tag)
|
public virtual void WriteIntArray(IntArrayTag tag)
|
||||||
{
|
{
|
||||||
WriteTypeAndName(tag);
|
WriteTypeAndName(tag);
|
||||||
BaseStream.Write(GetBytes(tag.Count), 0, sizeof(int));
|
WriteCount(tag);
|
||||||
|
|
||||||
var values = new Span<int>(tag.ToArray());
|
var values = new Span<int>(tag.ToArray());
|
||||||
|
if (UseVarInt)
|
||||||
|
{
|
||||||
|
// VarInt is effectively always little-endian
|
||||||
|
foreach (var n in values)
|
||||||
|
VarInt.Write(BaseStream, n, ZigZagEncoding);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (SwapEndian)
|
if (SwapEndian)
|
||||||
{
|
{
|
||||||
for (var i = 0; i < values.Length; i++)
|
for (var i = 0; i < values.Length; i++)
|
||||||
values[i] = values[i].SwapEndian();
|
values[i] = values[i].SwapEndian();
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseStream.Write(MemoryMarshal.AsBytes(values));
|
BaseStream.Write(MemoryMarshal.AsBytes(values));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,15 +162,22 @@ namespace SharpNBT
|
||||||
{
|
{
|
||||||
|
|
||||||
WriteTypeAndName(tag);
|
WriteTypeAndName(tag);
|
||||||
BaseStream.Write(GetBytes(tag.Count), 0, sizeof(int));
|
WriteCount(tag);
|
||||||
|
|
||||||
var values = new Span<long>(tag.ToArray());
|
var values = new Span<long>(tag.ToArray());
|
||||||
|
if (UseVarInt)
|
||||||
|
{
|
||||||
|
// VarLong is effectively always little-endian
|
||||||
|
foreach (var n in values)
|
||||||
|
VarLong.Write(BaseStream, n, ZigZagEncoding);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (SwapEndian)
|
if (SwapEndian)
|
||||||
{
|
{
|
||||||
for (var i = 0; i < values.Length; i++)
|
for (var i = 0; i < values.Length; i++)
|
||||||
values[i] = values[i].SwapEndian();
|
values[i] = values[i].SwapEndian();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseStream.Write(MemoryMarshal.AsBytes(values));
|
BaseStream.Write(MemoryMarshal.AsBytes(values));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,7 +189,7 @@ namespace SharpNBT
|
||||||
{
|
{
|
||||||
WriteTypeAndName(tag);
|
WriteTypeAndName(tag);
|
||||||
BaseStream.WriteByte((byte) tag.ChildType);
|
BaseStream.WriteByte((byte) tag.ChildType);
|
||||||
BaseStream.Write(GetBytes(tag.Count), 0, sizeof(int));
|
WriteCount(tag);
|
||||||
|
|
||||||
foreach (var child in tag)
|
foreach (var child in tag)
|
||||||
WriteTag(child);
|
WriteTag(child);
|
||||||
|
@ -281,7 +303,7 @@ namespace SharpNBT
|
||||||
if (!leaveOpen)
|
if (!leaveOpen)
|
||||||
await BaseStream.DisposeAsync();
|
await BaseStream.DisposeAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void WriteTypeAndName(Tag tag)
|
private void WriteTypeAndName(Tag tag)
|
||||||
{
|
{
|
||||||
|
@ -295,14 +317,23 @@ namespace SharpNBT
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void WriteUTF8String(string value)
|
private void WriteUTF8String(string value)
|
||||||
{
|
{
|
||||||
|
// String length prefixes never use ZigZag encoding
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(value))
|
if (string.IsNullOrEmpty(value))
|
||||||
{
|
{
|
||||||
BaseStream.Write(GetBytes((ushort) 0), 0, sizeof(ushort));
|
if (UseVarInt)
|
||||||
|
VarInt.Write(BaseStream, 0);
|
||||||
|
else
|
||||||
|
BaseStream.Write(GetBytes((ushort) 0), 0, sizeof(ushort));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var utf8 = Encoding.UTF8.GetBytes(value);
|
var utf8 = Encoding.UTF8.GetBytes(value);
|
||||||
BaseStream.Write(GetBytes((ushort) utf8.Length), 0, sizeof(ushort));
|
if (UseVarInt)
|
||||||
|
VarInt.Write(BaseStream, utf8.Length);
|
||||||
|
else
|
||||||
|
BaseStream.Write(GetBytes((ushort) utf8.Length), 0, sizeof(ushort));
|
||||||
|
|
||||||
BaseStream.Write(utf8, 0, utf8.Length);
|
BaseStream.Write(utf8, 0, utf8.Length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -346,5 +377,13 @@ namespace SharpNBT
|
||||||
Array.Reverse(bytes);
|
Array.Reverse(bytes);
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void WriteCount<T>(EnumerableTag<T> tag)
|
||||||
|
{
|
||||||
|
if (UseVarInt)
|
||||||
|
VarInt.Write(BaseStream, tag.Count, ZigZagEncoding);
|
||||||
|
else
|
||||||
|
BaseStream.Write(GetBytes(tag.Count), 0, sizeof(int));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue