internal DatabaseCreationBuilder(string path, Guid versionCheck)
 {
     this.path         = path;
     this.versionCheck = versionCheck;
     buffer            = new byte[8192];
     headers           = new List <ArrayHeader>();
     stream            = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read);
     db = new Database(() => Database.Open(FileShare.ReadWrite | FileShare.Delete, path), headers);
     try
     {
         stream.Write(BitConverter.GetBytes(0L));
         stream.Write(versionCheck.ToByteArray());
     }
     catch
     {
         stream.Dispose();
         db.Dispose();
     }
 }
 public void Dispose()
 {
     db.Dispose();
 }
        public override DatabaseBuilder AddIndirectArray <T, TKey>(
            ISerializer <T> serializer,
            Func <Database, IEnumerable <T> > elements,
            Func <T, TKey> selector,
            IComparer <TKey>?comparer)
        {
            try
            {
                var headerPosition = stream.Position;
                // write a dummy header
                var dummyHeaderBytes = new ArrayHeader(serializer).AsBytes();
                stream.Write(dummyHeaderBytes);

                var pointersArrayOffsetPosition = stream.Position;
                stream.Write(BitConverter.GetBytes(0L));

                var  dataStartPosition = stream.Position;
                long elementCount      = 0;
                // TODO: less lazy way
                var offsetList         = new List <long>();
                var elementsEnumerable = elements(db);
                if (comparer != null)
                {
                    elementsEnumerable = elementsEnumerable.OrderBy(selector, comparer);
                }
                foreach (var element in elementsEnumerable)
                {
                    int actualLength;
                    while (!serializer.TrySerialize(element, buffer.AsSpan(), out actualLength))
                    {
                        Utility.Reallocate(ref buffer);
                    }
                    offsetList.Add(stream.Position - dataStartPosition);
                    stream.Write(BitConverter.GetBytes(actualLength));
                    stream.Write(buffer, 0, actualLength);
                    elementCount++;
                }

                var pointerArrayPosition = stream.Position;
                stream.Position += elementCount * sizeof(long);

                var pastEndPosition = stream.Position;
                stream.Seek(headerPosition, SeekOrigin.Begin);
                var arrayHeader = new ArrayHeader(serializer)
                {
                    OverallLength = pastEndPosition - pointersArrayOffsetPosition,
                    RecordCount   = elementCount,
                    StartsAt      = pointersArrayOffsetPosition,
                    EndsAt        = pastEndPosition,
                    Type          = 2
                };
                stream.Write(arrayHeader.AsBytes());
                stream.Write(BitConverter.GetBytes(pointerArrayPosition - pointersArrayOffsetPosition));

                stream.Seek(pointerArrayPosition, SeekOrigin.Begin);
                foreach (var off in offsetList)
                {
                    stream.Write(BitConverter.GetBytes(off));
                }
                stream.Seek(pastEndPosition, SeekOrigin.Begin);
                headers.Add(arrayHeader);
            }
            catch
            {
                stream.Dispose();
                db.Dispose();
                throw;
            }
            return(this);
        }