public long SaveToStream([NotNull] Stream stream, NbtCompression compression)
{
if (stream == null) throw new ArgumentNullException("stream");
switch (compression) {
case NbtCompression.AutoDetect:
throw new ArgumentException("AutoDetect is not a valid NbtCompression value for saving.");
case NbtCompression.ZLib:
case NbtCompression.GZip:
case NbtCompression.None:
break;
default:
throw new ArgumentOutOfRangeException("compression");
}
if (rootTag.Name == null) {
// This may trigger if root tag has been renamed
throw new NbtFormatException(
"Cannot save NbtFile: Root tag is not named. Its name may be an empty string, but not null.");
}
long startOffset = 0;
if (stream.CanSeek) {
startOffset = stream.Position;
} else {
stream = new ByteCountingStream(stream);
}
switch (compression) {
case NbtCompression.ZLib:
stream.WriteByte(0x78);
stream.WriteByte(0x01);
int checksum;
using (var compressStream = new ZLibStream(stream, CompressionMode.Compress, true)) {
var bufferedStream = new BufferedStream(compressStream, WriteBufferSize);
RootTag.WriteTag(new NbtBinaryWriter(bufferedStream, BigEndian));
bufferedStream.Flush();
checksum = compressStream.Checksum;
}
byte[] checksumBytes = BitConverter.GetBytes(checksum);
if (BitConverter.IsLittleEndian) {
// Adler32 checksum is big-endian
Array.Reverse(checksumBytes);
}
stream.Write(checksumBytes, 0, checksumBytes.Length);
break;
case NbtCompression.GZip:
using (var compressStream = new GZipStream(stream, CompressionMode.Compress, true)) {
// use a buffered stream to avoid GZipping in small increments (which has a lot of overhead)
var bufferedStream = new BufferedStream(compressStream, WriteBufferSize);
RootTag.WriteTag(new NbtBinaryWriter(bufferedStream, BigEndian));
bufferedStream.Flush();
}
break;
case NbtCompression.None:
var writer = new NbtBinaryWriter(stream, BigEndian);
RootTag.WriteTag(writer);
break;
default:
throw new ArgumentOutOfRangeException("compression");
}
if (stream.CanSeek) {
return stream.Position - startOffset;
} else {
return ((ByteCountingStream)stream).BytesWritten;
}
}