public static void Write(Stream output, PropertySchema instance, Endian endian)
        {
            var typeAndOffset = instance.Offset & 0x00FFFFFFu | (uint)instance.Type << 24;

            output.WriteValueU32(typeAndOffset, endian);
            output.WriteValueU32(instance.Id, endian);
        }
        public static PropertySet Read(
            Stream input,
            DataFormats.PropertySet resource,
            Endian endian,
            PropertySetSchemaProvider schemaProvider)
        {
            var instance = new PropertySet();

            instance._Name           = resource.Name;
            instance._ReferenceCount = resource.ReferenceCount;
            instance._SchemaName     = resource.SchemaName;
            instance._Flags          = resource.Flags;

            var parentHandles = new ResourceHandle[resource.ParentCount];

            if (resource.ParentCount > 0)
            {
                input.Position = resource.ParentsOffset;
                for (uint i = 0; i < resource.ParentCount; i++)
                {
                    parentHandles[i] = ResourceHandle.Read(input, endian);
                }
            }
            instance._Parents.Clear();
            instance._Parents.AddRange(parentHandles);

            PropertySetSchema schema;

            if (resource.SchemaName == Symbol.Invalid || resource.SchemaName == resource.Name)
            {
                if ((resource.Flags & PropertyCollectionFlags.InheritSchema) != 0)
                {
                    throw new InvalidOperationException();
                }

                var properties = new PropertySchema[resource.PropertyCount];
                if (resource.PropertyCount > 0)
                {
                    input.Position = resource.PropertiesOffset;
                    for (uint i = 0; i < resource.PropertyCount; i++)
                    {
                        properties[i] = PropertySchema.Read(input, endian);
                    }
                }

                schema = new PropertySetSchema(properties, resource.DataSize);

                if (resource.Name != Symbol.Invalid && resource.SchemaName == resource.Name)
                {
                    schemaProvider.Add(resource.Name.Id, schema);
                }

                instance._DefinedSchema = schema;
            }
            else
            {
                if (resource.PropertyCount != 0)
                {
                    throw new NotSupportedException();
                }

                schema = schemaProvider.Get(resource.SchemaName.Id);
            }

            instance._Properties.Clear();
            instance._DefaultProperties.Clear();

            if (schema.Count > 0)
            {
                if (resource.DataOffset == 0)
                {
                    throw new InvalidOperationException();
                }

                input.Position = resource.DefaultBitsOffset;

                var defaultBits = new uint[(schema.Count + 31) >> 5];
                for (int i = 0; i < defaultBits.Length; i++)
                {
                    defaultBits[i] = input.ReadValueU32(endian);
                }

                input.Position = resource.DataOffset;
                using (var data = input.ReadToMemoryStream(schema.DataSize))
                {
                    for (int i = 0; i < schema.Count; i++)
                    {
                        var property  = schema[i];
                        var isDefault = (defaultBits[i >> 5] & (1u << (i % 32))) != 0;

                        var handler = HandlerFactory.Get(property.Type);

                        data.Position = property.Offset;

                        object value;
                        if (handler.UsesPointer == false)
                        {
                            value = handler.Read(data, endian, schemaProvider);
                        }
                        else
                        {
                            var pointerOffset = data.ReadOffset(endian);
                            if (pointerOffset == 0)
                            {
                                throw new InvalidOperationException();
                            }

                            input.Position = resource.DataOffset + pointerOffset;
                            value          = handler.Read(input, endian, schemaProvider);
                        }

                        instance._Properties.Add(property.Id, value);

                        if (isDefault == true)
                        {
                            instance._DefaultProperties.Add(property.Id);
                        }
                    }
                }
            }

            return(instance);
        }