private static byte[] BuildHeader(ulong count, GeometryType geometryType, IList <ColumnMeta> columns, PackedRTree index)
        {
            var builder = new FlatBufferBuilder(4096);

            VectorOffset?columnsOffset = null;

            if (columns != null)
            {
                var columnsArray = columns
                                   .Select(c => Column.CreateColumn(builder, builder.CreateString(c.Name), c.Type))
                                   .ToArray();
                columnsOffset = Header.CreateColumnsVector(builder, columnsArray);
            }

            Header.StartHeader(builder);
            Header.AddGeometryType(builder, geometryType);
            if (columnsOffset.HasValue)
            {
                Header.AddColumns(builder, columnsOffset.Value);
            }
            //if (index != null)
            Header.AddIndexNodeSize(builder, 0);
            Header.AddFeaturesCount(builder, count);
            var offset = Header.EndHeader(builder);

            builder.FinishSizePrefixed(offset.Value);

            return(builder.DataBuffer.ToSizedArray());
        }
        public static IEnumerable <IFeature> Deserialize(Stream stream, Envelope rect = null)
        {
            var reader = new BinaryReader(stream);

            var magicBytes = reader.ReadBytes(8);

            if (!magicBytes.SequenceEqual(Constants.MagicBytes))
            {
                throw new Exception("Not a FlatGeobuf file");
            }

            var headerSize = reader.ReadInt32();
            var header     = Header.GetRootAsHeader(new ByteBuffer(reader.ReadBytes(headerSize)));

            var count        = header.FeaturesCount;
            var nodeSize     = header.IndexNodeSize;
            var geometryType = header.GeometryType;

            IList <ColumnMeta> columns = null;

            if (header.ColumnsLength > 0)
            {
                columns = new List <ColumnMeta>();
                for (int i = 0; i < header.ColumnsLength; i++)
                {
                    var column = header.Columns(i).Value;
                    columns.Add(new ColumnMeta()
                    {
                        Name = column.Name, Type = column.Type
                    });
                }
            }

            if (nodeSize > 0)
            {
                long offset = 8 + 4 + headerSize;
                var  size   = PackedRTree.CalcSize(count, nodeSize);
                if (rect != null)
                {
                    var result = PackedRTree.StreamSearch(count, nodeSize, rect, (ulong treeOffset, ulong size) => {
                        stream.Seek(offset + (long)treeOffset, SeekOrigin.Begin);
                        return(stream);
                    }).ToList();
                    foreach (var item in result)
                    {
                        stream.Seek(offset + (long)size + (long)item.Offset, SeekOrigin.Begin);
                        var featureLength = reader.ReadInt32();
                        var feature       = FeatureConversions.FromByteBuffer(new ByteBuffer(reader.ReadBytes(featureLength)), geometryType, 2, columns);
                        yield return(feature);
                    }
                    yield break;
                }
                stream.Seek(8 + 4 + headerSize + (long)size, SeekOrigin.Begin);
            }

            while (stream.Position < stream.Length)
            {
                var featureLength = reader.ReadInt32();
                var feature       = FeatureConversions.FromByteBuffer(new ByteBuffer(reader.ReadBytes(featureLength)), geometryType, 2, columns);
                yield return(feature);
            }
        }