public void Decompile()
        {
            NameDataReader = new IO.EndianReader(
                new MemoryStream(NameData, writable: false),
                Shell.EndianFormat.Little,
                name: "NameDataReader");

            ValueDataPool = new BinaryDataTreeMemoryPool(ValueData);

            Nodes = new List <BinaryDataTreeBuildNode>(PackedNodes.Length);
            for (int x = 0; x < PackedNodes.Length; x++)
            {
                Nodes.Add(new BinaryDataTreeBuildNode());
            }

            for (int x = 0; x < PackedNodes.Length; x++)
            {
                var packed_node = PackedNodes[x];
                var build_node  = Nodes[x];

                build_node.SetParent(this, packed_node);

                int num_child_nodes;
                CalculateChildNodesCount(x, out num_child_nodes);
                build_node.SetChildren(this, packed_node, num_child_nodes);

                int num_name_values;
                CalculateNameValuesCount(x, out num_name_values);
                if (num_name_values == 0)
                {
                    throw new InvalidDataException("No name-values: #" + x);
                }
                build_node.SetNameValues(this, packed_node, num_name_values);
            }

            Util.DisposeAndNull(ref NameDataReader);
        }
        internal void Read(BinaryDataTreeMemoryPool pool, BinaryDataTreeNameValue nameValue)
        {
            TypeDesc = nameValue.GuessTypeDesc();

            bool direct_encoding = nameValue.DirectEncoding;

            uint total_data_size = nameValue.Size;

            if (nameValue.SizeIsIndirect)
            {
                if (direct_encoding)
                {
                    throw new InvalidOperationException();
                }

                total_data_size = pool.GetSizeValue(nameValue.Offset);

                if (total_data_size < BinaryDataTreeNameValue.kIndirectSizeThreshold)
                {
                    throw new InvalidOperationException();
                }
            }

            if (TypeDesc.SizeOf > 0)
            {
                if ((total_data_size % TypeDesc.SizeOf) != 0)
                {
                    throw new InvalidOperationException(nameValue.ToString());
                }

                ArrayLength = (int)(total_data_size / TypeDesc.SizeOf);
            }

            if (ArrayLength > 1)
            {
                if (Type != BinaryDataTreeVariantType.String)
                {
                    OpaqueArrayRef = TypeDesc.MakeArray(ArrayLength);
                }

                pool.InternalBuffer.Seek(nameValue.Offset);
            }

            switch (Type)
            {
            case BinaryDataTreeVariantType.Null:
                break;

            case BinaryDataTreeVariantType.Bool:
                if (ArrayLength > 1)
                {
                    TypeDesc.ReadArray(pool.InternalBuffer, OpaqueArrayRef);
                }
                else
                {
                    this.Bool = nameValue.Bool;
                }
                break;

            case BinaryDataTreeVariantType.Int:
                if (ArrayLength > 1)
                {
                    TypeDesc.ReadArray(pool.InternalBuffer, OpaqueArrayRef);
                }
                else
                {
                    if (TypeDesc.SizeOf < sizeof(long))
                    {
                        this.Int = nameValue.Int;
                    }
                    else
                    {
                        this.Int64 = pool.InternalBuffer.ReadUInt64();
                    }
                }
                break;

            case BinaryDataTreeVariantType.Float:
                if (ArrayLength > 1)
                {
                    TypeDesc.ReadArray(pool.InternalBuffer, OpaqueArrayRef);
                }
                else
                {
                    if (TypeDesc.SizeOf < sizeof(double))
                    {
                        this.Single = nameValue.Single;
                    }
                    else
                    {
                        this.Double = pool.InternalBuffer.ReadDouble();
                    }
                }
                break;

            case BinaryDataTreeVariantType.String:
                ArrayLength = 1;
                if (!IsUnicode && total_data_size <= sizeof(uint))
                {
                    var sb = new System.Text.StringBuilder();
                    for (uint x = 0, v = nameValue.Int; x < sizeof(uint); x++, v >>= Bits.kByteBitCount)
                    {
                        sb.Append((char)(v & 0xFF));
                    }

                    this.String = sb.ToString();
                }
                else
                {
                    this.String = pool.InternalBuffer.ReadString(IsUnicode
                                                        ? Memory.Strings.StringStorage.CStringUnicode
                                                        : Memory.Strings.StringStorage.CStringAscii);
                }
                break;

            default: throw new KSoft.Debug.UnreachableException(Type.ToString());
            }
        }