mirror of
https://github.com/protomaps/PMTiles.git
synced 2026-02-04 10:51:07 +00:00
add minimal shim stubs for v2 backwards compatibility
This commit is contained in:
43
js/v2.ts
Normal file
43
js/v2.ts
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import { Header, Cache, RangeResponse } from './v3';
|
||||||
|
|
||||||
|
async function getHeaderAndRoot(a:ArrayBuffer, etag?:string): Promise<[Header, [string, number, ArrayBuffer]]> {
|
||||||
|
const header = {
|
||||||
|
specVersion: 2,
|
||||||
|
rootDirectoryOffset: 0,
|
||||||
|
rootDirectoryLength: 0,
|
||||||
|
jsonMetadataOffset: 0,
|
||||||
|
jsonMetadataLength: 0,
|
||||||
|
leafDirectoryOffset: 0,
|
||||||
|
leafDirectoryLength: undefined,
|
||||||
|
tileDataOffset: 512000,
|
||||||
|
tileDataLength: undefined,
|
||||||
|
numAddressedTiles: 0,
|
||||||
|
numTileEntries: 0,
|
||||||
|
numTileContents: 0,
|
||||||
|
clustered: false,
|
||||||
|
internalCompression: 0,
|
||||||
|
tileCompression: 0,
|
||||||
|
tileType: 0,
|
||||||
|
minZoom: 0,
|
||||||
|
maxZoom: 0,
|
||||||
|
minLon: 0,
|
||||||
|
minLat: 0,
|
||||||
|
maxLon: 0,
|
||||||
|
maxLat: 0,
|
||||||
|
centerZoom: 0,
|
||||||
|
centerLon: 0,
|
||||||
|
centerLat: 0,
|
||||||
|
etag: etag,
|
||||||
|
};
|
||||||
|
return [header, ["",0,new ArrayBuffer(0)]];
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getZxy(header:Header,cache:Cache): Promise<RangeResponse | undefined> {
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
getHeaderAndRoot: getHeaderAndRoot,
|
||||||
|
getZxy: getZxy
|
||||||
|
};
|
||||||
|
|
||||||
76
js/v3.ts
76
js/v3.ts
@@ -1,4 +1,5 @@
|
|||||||
import { decompressSync } from "fflate";
|
import { decompressSync } from "fflate";
|
||||||
|
import v2 from "./v2";
|
||||||
|
|
||||||
export interface BufferPosition {
|
export interface BufferPosition {
|
||||||
buf: Uint8Array;
|
buf: Uint8Array;
|
||||||
@@ -159,14 +160,15 @@ enum TileType {
|
|||||||
const HEADER_SIZE_BYTES = 122;
|
const HEADER_SIZE_BYTES = 122;
|
||||||
|
|
||||||
export interface Header {
|
export interface Header {
|
||||||
|
specVersion: number;
|
||||||
rootDirectoryOffset: number;
|
rootDirectoryOffset: number;
|
||||||
rootDirectoryLength: number;
|
rootDirectoryLength: number;
|
||||||
jsonMetadataOffset: number;
|
jsonMetadataOffset: number;
|
||||||
jsonMetadataLength: number;
|
jsonMetadataLength: number;
|
||||||
leafDirectoryOffset: number;
|
leafDirectoryOffset: number;
|
||||||
leafDirectoryLength: number;
|
leafDirectoryLength?: number;
|
||||||
tileDataOffset: number;
|
tileDataOffset: number;
|
||||||
tileDataLength: number;
|
tileDataLength?: number;
|
||||||
numAddressedTiles: number;
|
numAddressedTiles: number;
|
||||||
numTileEntries: number;
|
numTileEntries: number;
|
||||||
numTileContents: number;
|
numTileContents: number;
|
||||||
@@ -301,6 +303,7 @@ export function bytesToHeader(bytes: ArrayBuffer, etag?: string): Header {
|
|||||||
throw new Error("Wrong magic number for PMTiles archive");
|
throw new Error("Wrong magic number for PMTiles archive");
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
specVersion: 3,
|
||||||
rootDirectoryOffset: Number(v.getBigUint64(3, true)),
|
rootDirectoryOffset: Number(v.getBigUint64(3, true)),
|
||||||
rootDirectoryLength: Number(v.getBigUint64(11, true)),
|
rootDirectoryLength: Number(v.getBigUint64(11, true)),
|
||||||
jsonMetadataOffset: Number(v.getBigUint64(19, true)),
|
jsonMetadataOffset: Number(v.getBigUint64(19, true)),
|
||||||
@@ -362,6 +365,10 @@ function deserializeIndex(buffer: ArrayBuffer): Entry[] {
|
|||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function detectVersion(a: ArrayBuffer): number {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
export class VersionMismatch extends Error {}
|
export class VersionMismatch extends Error {}
|
||||||
|
|
||||||
export interface Cache {
|
export interface Cache {
|
||||||
@@ -387,36 +394,37 @@ async function getHeaderAndRoot(
|
|||||||
): Promise<[Header, [string, number, Entry[] | ArrayBuffer]?]> {
|
): Promise<[Header, [string, number, Entry[] | ArrayBuffer]?]> {
|
||||||
let resp = await source.getBytes(0, 16384);
|
let resp = await source.getBytes(0, 16384);
|
||||||
|
|
||||||
// check spec revision
|
// V2 COMPATIBILITY
|
||||||
if (false) {
|
if (detectVersion(resp.data) < 2) {
|
||||||
} else {
|
return v2.getHeaderAndRoot(resp.data, resp.etag);
|
||||||
const headerData = resp.data.slice(0, HEADER_SIZE_BYTES);
|
|
||||||
const header = bytesToHeader(headerData, resp.etag);
|
|
||||||
|
|
||||||
// optimistically set the root directory
|
|
||||||
// TODO check root bounds
|
|
||||||
if (prefetch) {
|
|
||||||
const rootDirData = resp.data.slice(
|
|
||||||
header.rootDirectoryOffset,
|
|
||||||
header.rootDirectoryOffset + header.rootDirectoryLength
|
|
||||||
);
|
|
||||||
const dirKey =
|
|
||||||
source.getKey() +
|
|
||||||
"|" +
|
|
||||||
(header.etag || "") +
|
|
||||||
"|" +
|
|
||||||
header.rootDirectoryOffset +
|
|
||||||
"|" +
|
|
||||||
header.rootDirectoryLength;
|
|
||||||
|
|
||||||
const rootDir = deserializeIndex(
|
|
||||||
tryDecompress(rootDirData, header.internalCompression)
|
|
||||||
);
|
|
||||||
return [header, [dirKey, ENTRY_SIZE_BYTES * rootDir.length, rootDir]];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [header, undefined];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const headerData = resp.data.slice(0, HEADER_SIZE_BYTES);
|
||||||
|
const header = bytesToHeader(headerData, resp.etag);
|
||||||
|
|
||||||
|
// optimistically set the root directory
|
||||||
|
// TODO check root bounds
|
||||||
|
if (prefetch) {
|
||||||
|
const rootDirData = resp.data.slice(
|
||||||
|
header.rootDirectoryOffset,
|
||||||
|
header.rootDirectoryOffset + header.rootDirectoryLength
|
||||||
|
);
|
||||||
|
const dirKey =
|
||||||
|
source.getKey() +
|
||||||
|
"|" +
|
||||||
|
(header.etag || "") +
|
||||||
|
"|" +
|
||||||
|
header.rootDirectoryOffset +
|
||||||
|
"|" +
|
||||||
|
header.rootDirectoryLength;
|
||||||
|
|
||||||
|
const rootDir = deserializeIndex(
|
||||||
|
tryDecompress(rootDirData, header.internalCompression)
|
||||||
|
);
|
||||||
|
return [header, [dirKey, ENTRY_SIZE_BYTES * rootDir.length, rootDir]];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [header, undefined];
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getDirectory(
|
async function getDirectory(
|
||||||
@@ -749,6 +757,11 @@ export class PMTiles {
|
|||||||
const tile_id = zxyToTileId(z, x, y);
|
const tile_id = zxyToTileId(z, x, y);
|
||||||
const header = await this.cache.getHeader(this.source);
|
const header = await this.cache.getHeader(this.source);
|
||||||
|
|
||||||
|
// V2 COMPATIBILITY
|
||||||
|
if (header.specVersion < 3) {
|
||||||
|
return v2.getZxy(header, this.cache);
|
||||||
|
}
|
||||||
|
|
||||||
if (z < header.minZoom || z > header.maxZoom) {
|
if (z < header.minZoom || z > header.maxZoom) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@@ -809,6 +822,7 @@ export class PMTiles {
|
|||||||
|
|
||||||
async getMetadataAttempt(): Promise<any> {
|
async getMetadataAttempt(): Promise<any> {
|
||||||
const header = await this.cache.getHeader(this.source);
|
const header = await this.cache.getHeader(this.source);
|
||||||
|
|
||||||
const resp = await this.source.getBytes(
|
const resp = await this.source.getBytes(
|
||||||
header.jsonMetadataOffset,
|
header.jsonMetadataOffset,
|
||||||
header.jsonMetadataLength
|
header.jsonMetadataLength
|
||||||
|
|||||||
Reference in New Issue
Block a user