public void CanBuildSir0()
        {
            // Arrange
            var builder  = new Sir0Builder(8);
            var testData = new int[] { 1, 2, 3, 7, 11, 13 };

            // Act
            var pointers = new List <long>();

            foreach (var value in testData)
            {
                pointers.Add(builder.Length);
                builder.WriteInt32(builder.Length, value);
            }

            builder.SubHeaderOffset = builder.Length;
            builder.WriteInt32(builder.Length, pointers.Count);
            foreach (var pointer in pointers)
            {
                builder.WritePointer(builder.Length, pointer);
            }

            var sir0 = builder.Build();

            // Assert
            sir0.Data.Length.Should().BeGreaterThan(
                0x20                                // Header
                + (testData.Length * 4)             // The integers from testData
                + (testData.Length * 8)             // Pointers to each integer
                + (testData.Length));               // Minimum footer size. Testing the size of the footer is outside the scope of this test, but is covered by checking each pointer later

            sir0.PointerOffsets[0].Should().Be(8);  // Index of the subheader pointer
            sir0.PointerOffsets[1].Should().Be(16); // Index of the footer pointer

            var entryCount = sir0.SubHeader.ReadInt32(0);

            entryCount.Should().Be(testData.Length);
            for (int i = 0; i < entryCount; i++)
            {
                var entryPointerOffset = sir0.SubHeaderOffset + 4 + i * 8;
                sir0.PointerOffsets[i + 2].Should().Be(entryPointerOffset);

                var entryPointer             = sir0.SubHeader.ReadInt64(4 + i * 8);
                var entryPointerFromAbsolute = sir0.Data.ReadInt64(sir0.SubHeaderOffset + 4 + i * 8);
                entryPointerFromAbsolute.Should().Be(entryPointer);

                var entry = sir0.Data.ReadInt32(entryPointer);
                entry.Should().Be(testData[i]);
            }
        }
        public Sir0 ToSir0()
        {
            var sir0 = new Sir0Builder(8);

            void align(int length)
            {
                var paddingLength = length - (sir0.Length % length);

                if (paddingLength != length)
                {
                    sir0.WritePadding(sir0.Length, paddingLength);
                }
            }

            var allStringValues = Strings.Values.SelectMany(strList => strList).ToArray();

            // Ensure that the order in the generated message.bin matches the original if possible
            var orderedStrings = allStringValues.OrderBy(str => str.Hash).ToArray();

            foreach (var entry in orderedStrings)
            {
                entry.StringOffset = sir0.Length;
                sir0.WriteNullTerminatedString(sir0.Length, Encoding.Unicode, entry.Value);
            }
            align(8);

            int entriesOffset = sir0.Length;

            foreach (var entry in allStringValues)
            {
                sir0.MarkPointer(sir0.Length);
                sir0.WriteInt64(sir0.Length, entry.StringOffset);
                sir0.WriteInt32(sir0.Length, entry.Hash);
                sir0.WriteInt32(sir0.Length, entry.Unknown);
            }

            sir0.SubHeaderOffset = sir0.Length;
            sir0.WriteInt32(sir0.Length, Strings.Count);
            sir0.WriteInt32(sir0.Length, Strings.Count);

            sir0.MarkPointer(sir0.Length);
            sir0.WriteInt64(sir0.Length, entriesOffset);

            return(sir0.Build());
        }