public void Deserialize(Stream input) { var basePosition = input.Position; var magic = input.ReadValueU32(Endian.Little); if (magic != Signature && magic.Swap() != Signature) { throw new FormatException(); } var endian = magic == Signature ? Endian.Little : Endian.Big; var version = input.ReadValueU32(endian); if (version != 1) { throw new FormatException(); } var rawRootNode = RawNode.Read(input, endian); var rootNode = new Node(); rootNode.NameHash = rawRootNode.NameHash; var instanceQueue = new Queue <Tuple <Node, RawNode> >(); instanceQueue.Enqueue(new Tuple <Node, RawNode>(rootNode, rawRootNode)); var propertyQueue = new Queue <Tuple <Node, RawProperty[]> >(); while (instanceQueue.Count > 0) { var item = instanceQueue.Dequeue(); var node = item.Item1; var rawNode = item.Item2; input.Position = basePosition + rawNode.DataOffset; var rawProperties = new RawProperty[rawNode.PropertyCount]; for (int i = 0; i < rawNode.PropertyCount; i++) { rawProperties[i] = RawProperty.Read(input, endian); } input.Position = basePosition + (rawNode.DataOffset + (RawProperty.Size * rawNode.PropertyCount)).Align(4); for (int i = 0; i < rawNode.InstanceCount; i++) { var rawChildNode = RawNode.Read(input, endian); var childNode = new Node(); childNode.NameHash = rawChildNode.NameHash; node.Children.Add(childNode); instanceQueue.Enqueue(new Tuple <Node, RawNode>(childNode, rawChildNode)); } propertyQueue.Enqueue(new Tuple <Node, RawProperty[]>(node, rawProperties)); } while (propertyQueue.Count > 0) { var item = propertyQueue.Dequeue(); var node = item.Item1; var rawProperties = item.Item2; foreach (var rawProperty in rawProperties) { var variant = VariantFactory.GetVariant(rawProperty.Type); if (variant.IsPrimitive == true) { using (var temp = new MemoryStream(rawProperty.Data, false)) { variant.Deserialize(temp, endian); if (temp.Position != temp.Length) { throw new InvalidOperationException(); } } } else { if (rawProperty.Data.Length != 4) { throw new InvalidOperationException(); } uint offset; using (var temp = new MemoryStream(rawProperty.Data, false)) { offset = temp.ReadValueU32(endian); } input.Position = basePosition + offset; variant.Deserialize(input, endian); } node.Properties.Add(rawProperty.NameHash, (IVariant)variant); } } this._Root = rootNode; }