UNPKG

@convex-dev/geospatial

Version:
55 lines 2.02 kB
// Encode (sortKey: number, pointId: Id<"points">) as an order preserving string. import * as d64 from "./d64.js"; export function encodeTupleKey(sortKey, pointId) { const buf = new ArrayBuffer(9); const view = new DataView(buf); // Write `0x0D` as the header. view.setUint8(0, 0x0d); const littleEndian = true; view.setFloat64(1, sortKey, littleEndian); let sortKeyUint64 = view.getBigUint64(1, littleEndian); // Flip all of the bits if the sign bit is set. if ((sortKeyUint64 & (1n << 63n)) !== 0n) { sortKeyUint64 = ~sortKeyUint64; } // Otherwise, just flip the sign bit. else { sortKeyUint64 |= 1n << 63n; } view.setBigUint64(1, sortKeyUint64, littleEndian); let out = d64.encode(buf); out += `:${pointId}`; return out; } export function decodeTupleKey(key) { const pieces = key.split(":"); if (pieces.length !== 2) { throw new Error(`Invalid tuple key ${key}: Expected two parts separated by a colon`); } const [encodedSortKey, pointId] = pieces; const buf = d64.decode(encodedSortKey); if (buf.byteLength !== 9) { throw new Error(`Invalid tuple key ${key}: Expected 9 bytes, got ${buf.byteLength}`); } const view = new DataView(buf); if (view.getUint8(0) !== 0x0d) { throw new Error(`Invalid tuple key ${key}: Expected header 0x0D, got ${view.getUint8(0)}`); } const littleEndian = true; let encodedUint64 = view.getBigUint64(1, littleEndian); // If the sign bit was set, just turn it off. if ((encodedUint64 & (1n << 63n)) !== 0n) { encodedUint64 &= ~(1n << 63n); } // Otherwise, flip all of the bits. else { encodedUint64 = ~encodedUint64; } view.setBigUint64(1, encodedUint64, littleEndian); const sortKey = view.getFloat64(1, littleEndian); return { sortKey, pointId: pointId }; } export function encodeBound(sortKey) { return encodeTupleKey(sortKey, ""); } //# sourceMappingURL=tupleKey.js.map