private Graph(int zoom, int edgeDataSize, int tileSizeInIndex, SparseMemoryArray <byte> tiles,
                      int coordinateSizeInBytes, MemoryArray <byte> vertices, uint vertexPointer, MemoryArray <uint> edgePointers,
                      uint edgePointer, MemoryArray <byte> edges, ShapesArray shapes)
        {
            _zoom         = zoom;
            _edgeDataSize = edgeDataSize;
            _edgeSize     = 8 * 2 +        // the vertices.
                            4 * 2 +        // the pointers to previous edges.
                            _edgeDataSize; // the edge data package.

            if (TileSizeInIndex != tileSizeInIndex)
            {
                throw new ArgumentOutOfRangeException($"{nameof(tileSizeInIndex)}");
            }
            _tiles = tiles;
            if (CoordinateSizeInBytes != coordinateSizeInBytes)
            {
                throw new ArgumentOutOfRangeException($"{nameof(coordinateSizeInBytes)}");
            }
            _vertices      = vertices;
            _vertexPointer = vertexPointer;
            _edgePointers  = edgePointers;
            _edgePointer   = edgePointer;
            _edges         = edges;
            _shapes        = shapes;
        }
        /// <summary>
        /// Creates a new graph.
        /// </summary>
        /// <param name="zoom">The zoom level.</param>
        /// <param name="edgeDataSize">The size of the data package per edge.</param>
        public Graph(int zoom = 14, int edgeDataSize = 0)
        {
            _zoom         = zoom;
            _edgeDataSize = edgeDataSize;
            _edgeSize     = 8 * 2 +        // the vertices.
                            4 * 2 +        // the pointers to previous edges.
                            _edgeDataSize; // the edge data package.

            _tiles        = new SparseMemoryArray <byte>(0, emptyDefault: byte.MaxValue);
            _vertices     = new MemoryArray <byte>(CoordinateSizeInBytes);
            _edgePointers = new MemoryArray <uint>(1);
            _edges        = new MemoryArray <byte>(0);

            for (var p = 0; p < _edgePointers.Length; p++)
            {
                _edgePointers[p] = GraphConstants.TileNotLoaded;
            }
        }
        internal static Graph ReadFrom(Stream stream)
        {
            // read & verify header.
            var header  = stream.ReadWithSizeString();
            var version = stream.ReadByte();

            if (header != nameof(Graph))
            {
                throw new InvalidDataException($"Cannot read {nameof(Graph)}: Header invalid.");
            }
            if (version != 1)
            {
                throw new InvalidDataException($"Cannot read {nameof(Graph)}: Version # invalid.");
            }

            // read zoom and edge data size.
            var zoom         = stream.ReadByte();
            var edgeDataSize = stream.ReadByte();

            // read tile index.
            var tileSizeIndex = stream.ReadByte();
            var tiles         = SparseMemoryArray <byte> .CopyFromWithHeader(stream);

            // read vertices.
            var coordinateSizeInBytes = stream.ReadByte();
            var vertexPointer         = stream.ReadInt64();
            var vertices = MemoryArray <byte> .CopyFromWithSize(stream);

            var edgePointers = MemoryArray <uint> .CopyFromWithSize(stream);

            // read edges.
            var edgePointer = stream.ReadInt64();
            var edges       = MemoryArray <byte> .CopyFromWithSize(stream);

            // read shapes.
            var shapes = ShapesArray.CreateFrom(stream, true, false);

            return(new Graph(zoom, edgeDataSize, tileSizeIndex, tiles, coordinateSizeInBytes, vertices, (uint)vertexPointer, edgePointers,
                             (uint)edgePointer, edges, shapes));
        }