public byte[] Write(object root)
        {
            using (this.Writer = new BinaryWriter(Stream))
            {
                this.Magic = InitMagic();
                WriteMagic(Magic);

                this.Header = InitHeader();
                WriteHeader(Header);

                for (int i = 0; i < Header.numSections; i++)
                {
                    var section = new WritableSection((SectionType)i, this);
                    WriteSectionHeader(section.Header);
                    Sections.Add(section);
                }

                Magic.headersSize = (UInt32)Stream.Position;

                CurrentSection = Sections[(int)SectionType.Main];
                CurrentSection.WriteStruct(root);

                while (ArrayWrites.Count > 0 || StructWrites.Count > 0 || StringWrites.Count > 0)
                {
                    FlushPendingWrites();
                }

                foreach (var defn in Types.Values)
                {
                    Sections[(int)SectionType.Discardable].WriteStructDefinition(defn);
                }

                // We need to do this again to flush strings written by WriteMemberDefinition()
                FlushPendingWrites();

                FinalizeOffsets();

                foreach (var section in Sections)
                {
                    section.Header.first16bit = (UInt32)section.MainStream.Length;
                    section.Header.first8bit  = (UInt32)section.MainStream.Length;
                    section.Finish();
                }

                var relocSection = Sections[(int)SectionType.Discardable];
                foreach (var section in Sections)
                {
                    relocSection.WriteSectionRelocations(section);
                }

                foreach (var section in Sections)
                {
                    relocSection.WriteSectionMixedMarshallingRelocations(section);
                }

                foreach (var section in Sections)
                {
                    // Pad section size to a multiple of the section alignment
                    while ((section.MainStream.Position % section.Header.alignment) > 0)
                    {
                        section.Writer.Write((Byte)0);
                    }

                    section.MainStream.Flush();
                    section.Header.offsetInFile     = (UInt32)Stream.Position;
                    section.Header.uncompressedSize = (UInt32)section.MainStream.Length;
                    section.Header.compressedSize   = (UInt32)section.MainStream.Length;
                    Writer.Write(section.MainStream.ToArray());
                }

                foreach (var section in Sections)
                {
                    section.Header.relocationsOffset          += relocSection.Header.offsetInFile;
                    section.Header.mixedMarshallingDataOffset += relocSection.Header.offsetInFile;
                }

                var rootStruct = LookupStructDefinition(root.GetType(), root);
                Header.rootType = ObjectOffsets[rootStruct];
                Header.rootNode = new SectionReference(SectionType.Main, 0);
                Header.fileSize = (UInt32)Stream.Length;

                Stream.Seek(Magic.MagicSize + Header.Size(), SeekOrigin.Begin);

                foreach (var section in Sections)
                {
                    WriteSectionHeader(section.Header);
                }

                Header.crc = Header.CalculateCRC(Stream);
                Stream.Seek(0, SeekOrigin.Begin);
                WriteMagic(Magic);
                WriteHeader(Header);

                return(Stream.ToArray());
            }
        }