3using System.Collections;
 
    4using System.Collections.Generic;
 
   21            public abstract object Clone(
object o);
 
   40                var list = 
new List<T>(size);
 
   41                for (
int i = 0; i < size; i++)
 
   53            public override object Clone(
object o) => o;
 
   55            public virtual IList 
CloneList(IList<T> list) => 
new List<T>(list);
 
   57            public override object Default() => 
default(T);
 
   67                    base(reader, writer) {
 
   73            public override IList 
CloneList(IList<T> list) => list.Select(
clone).ToList();
 
   86                r => r.ReadBytes(r.ReadInt32()),
 
   91                v => (
byte[]) v.Clone(),
 
   94                r => Encoding.UTF8.GetString(r.ReadBytes(r.ReadInt16())),
 
   96                    var b = Encoding.UTF8.GetBytes(v);
 
   97                    w.Write((short)b.Length);
 
  107                        id = GetPayloadId(v.GetType().GetGenericArguments()[0]);
 
  110                        throw new IOException(
"Invalid NBT list type: "+v.GetType());
 
  121                        throw new ArgumentException(
"Invalid NBT list type: "+v.GetType());
 
  124            new ClassPayloadHandler<TagCompound>(
 
  126                    var compound = 
new TagCompound();
 
  129                    while ((tag = 
ReadTag(r, out name)) != 
null)
 
  130                        compound.Set(name, tag);
 
  135                    foreach (var entry 
in v)
 
  136                        if (entry.Value != 
null)
 
  137                            WriteTag(entry.Key, entry.Value, w);
 
  141                v => (TagCompound) v.Clone(),
 
  142                () => 
new TagCompound()),
 
  143            new ClassPayloadHandler<
int[]>(
 
  145                    var ia = 
new int[r.ReadInt32()];
 
  146                    for (
int i = 0; i < ia.Length; i++)
 
  147                        ia[i] = r.ReadInt32();
 
  155                v => (
int[]) v.Clone(),
 
  159        private static readonly Dictionary<Type, int> PayloadIDs =
 
  160            Enumerable.Range(1, PayloadHandlers.Length - 1).ToDictionary(i => PayloadHandlers[i].PayloadType);
 
  165            if (id < 1 || id >= PayloadHandlers.Length)
 
  166                throw new IOException(
"Invalid NBT payload id: " + 
id);
 
  168            return PayloadHandlers[id];
 
  173            if (PayloadIDs.TryGetValue(t, out 
id))
 
  176            if (typeof(IList).IsAssignableFrom(t))
 
  179            throw new IOException($
"Invalid NBT payload type '{t}'");
 
  183            var type = value.GetType();
 
  190            if (GetPayloadId(type) != 9)
 
  193            var elemType = type.GetGenericArguments()[0];
 
  197            if (GetPayloadId(elemType) != 9)
 
  201            var list = value as IList<IList> ?? ((IList)value).Cast<IList>().ToList();
 
  202            for (
int i = 0; i < list.Count; i++)
 
  203                list[i] = (IList)Serialize(list[i]);
 
  208        public static T Deserialize<T>(
object tag) {
 
  209            if (tag is T) 
return (T)tag;
 
  210            return (T)Deserialize(typeof(T), tag);
 
  214            if (type.IsInstanceOfType(tag))
 
  220                    tag = Deserialize(serializer.
TagType, 
null);
 
  227                if (type.GetGenericArguments().Length == 0)
 
  228                    return GetHandler(GetPayloadId(type)).Default();
 
  230                if (type.GetGenericTypeDefinition() == typeof(Nullable<>))
 
  235            if ((tag == 
null || tag is IList) &&
 
  236                type.GetGenericArguments().Length == 1) {
 
  237                var elemType = type.GetGenericArguments()[0];
 
  238                var newListType = typeof(List<>).MakeGenericType(elemType);
 
  239                if (type.IsAssignableFrom(newListType)) {
 
  241                        return newListType.GetConstructor(
new Type[0]).Invoke(
new object[0]);
 
  244                        return serializer.DeserializeList((IList)tag);
 
  247                    var oldList = (IList)tag;
 
  248                    var newList = (IList)newListType.GetConstructor(
new[] { typeof(
int) }).Invoke(
new object[] { oldList.Count });
 
  249                    foreach (var elem 
in oldList)
 
  250                        newList.Add(Deserialize(elemType, elem));
 
  257                throw new IOException($
"Invalid NBT payload type '{type}'");
 
  259            throw new InvalidCastException($
"Unable to cast object of type '{tag.GetType()}' to type '{type}'");
 
  262        public static T Clone<T>(T o) => (T)GetHandler(GetPayloadId(o.GetType())).Clone(o);
 
  265            int id = r.ReadByte();
 
  271            name = StringHandler.reader(r);
 
  272            return PayloadHandlers[id].Read(r);
 
  276            int id = GetPayloadId(tag.GetType());
 
  278            StringHandler.writer(w, name);
 
  279            PayloadHandlers[id].Write(w, tag);
 
  284                using (Stream fs = 
new FileStream(path, FileMode.Open, FileAccess.Read))
 
  285                    return FromStream(fs, compressed);
 
  288                throw new IOException(
"Failed to read NBT file: " + path, e);
 
  293            if (compressed) stream = 
new GZipStream(stream, CompressionMode.Decompress);
 
  299            var tag = ReadTag(reader, out name);
 
  301                throw new IOException(
"Root tag not a TagCompound");
 
  308                using (Stream fs = 
new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))
 
  309                    ToStream(root, fs, compress);
 
  312                throw new IOException(
"Failed to read NBT file: " + path, e);
 
  317            if (compress) stream = 
new GZipStream(stream, CompressionMode.Compress, 
true);
 
  319            if (compress) stream.Close();
 
override object Clone(object o)
 
override object Default()
 
ClassPayloadHandler(Func< BinaryReader, T > reader, Action< BinaryWriter, T > writer, Func< T, T > clone, Func< T > makeDefault=null)
 
override IList CloneList(IList< T > list)
 
override void Write(BinaryWriter w, object v)
 
override object Clone(object o)
 
override IList ReadList(BinaryReader r, int size)
 
virtual IList CloneList(IList< T > list)
 
abstract object Clone(object o)
 
abstract void Write(BinaryWriter w, object v)
 
override void WriteList(BinaryWriter w, IList list)
 
abstract IList ReadList(BinaryReader r, int size)
 
abstract object Default()
 
override object Read(BinaryReader r)
 
override IList CloneList(IList list)
 
void WriteList(BinaryWriter w, IList< T > list)
 
PayloadHandler(Func< BinaryReader, T > reader, Action< BinaryWriter, T > writer)
 
abstract void WriteList(BinaryWriter w, IList list)
 
abstract Type PayloadType
 
abstract IList CloneList(IList list)
 
abstract object Read(BinaryReader r)
 
override object Default()
 
static readonly PayloadHandler[] PayloadHandlers
 
static int GetPayloadId(Type t)
 
static void Write(TagCompound root, BinaryWriter writer)
 
static void WriteTag(string name, object tag, BinaryWriter w)
 
static object Deserialize(Type type, object tag)
 
static void ToStream(TagCompound root, Stream stream, bool compress=true)
 
static TagCompound FromStream(Stream stream, bool compressed=true)
 
static PayloadHandler GetHandler(int id)
 
static object ReadTag(BinaryReader r, out string name)
 
static TagCompound Read(BinaryReader reader)
 
static object Serialize(object value)
 
static TagCompound FromFile(string path, bool compressed=true)
 
static void ToFile(TagCompound root, string path, bool compress=true)
 
abstract object Serialize(object value)
 
static bool TryGetSerializer(Type type, out TagSerializer serializer)
 
abstract IList SerializeList(IList value)
 
abstract object Deserialize(object tag)