@uwdata/flechette
Advanced tools
Comparing version 0.0.7 to 0.0.8
@@ -243,4 +243,2 @@ // src/constants.js | ||
* array ends. Like list/struct types, the value array can be of any type. | ||
* | ||
* Not currently supported by Flechette. | ||
*/ | ||
@@ -256,4 +254,2 @@ RunEndEncoded: 22, | ||
* must have a corresponding entry in `variadicBufferCounts`. | ||
* | ||
* Not currently supported by Flechette. | ||
*/ | ||
@@ -269,4 +265,2 @@ BinaryView: 23, | ||
* must have a corresponding entry in `variadicBufferCounts`. | ||
* | ||
* Not currently supported by Flechette. | ||
*/ | ||
@@ -278,4 +272,2 @@ Utf8View: 24, | ||
* list values. | ||
* | ||
* Not currently supported by Flechette. | ||
*/ | ||
@@ -286,4 +278,2 @@ ListView: 25, | ||
* extremely large data values. | ||
* | ||
* Not currently supported by Flechette. | ||
*/ | ||
@@ -405,11 +395,19 @@ LargeListView: 26 | ||
} | ||
function bisectOffsets(offsets, index) { | ||
function bisect(offsets, index) { | ||
let a = 0; | ||
let b = offsets.length; | ||
do { | ||
const mid = a + b >>> 1; | ||
if (offsets[mid] <= index) a = mid + 1; | ||
else b = mid; | ||
} while (a < b); | ||
return --a; | ||
if (b <= 2147483648) { | ||
do { | ||
const mid = a + b >>> 1; | ||
if (offsets[mid] <= index) a = mid + 1; | ||
else b = mid; | ||
} while (a < b); | ||
} else { | ||
do { | ||
const mid = Math.trunc((a + b) / 2); | ||
if (offsets[mid] <= index) a = mid + 1; | ||
else b = mid; | ||
} while (a < b); | ||
} | ||
return a; | ||
} | ||
@@ -467,7 +465,7 @@ function table(buf, index) { | ||
} | ||
function readVector(buf, offset) { | ||
return { | ||
length: readInt32(buf, offset + readInt32(buf, offset)), | ||
base: offset + readInt32(buf, offset) + SIZEOF_INT | ||
}; | ||
function readVector(buf, offset, stride, extract) { | ||
if (!offset) return []; | ||
const length = readInt32(buf, offset + readInt32(buf, offset)); | ||
const base = offset + readInt32(buf, offset) + SIZEOF_INT; | ||
return Array.from({ length }, (_, i) => extract(buf, base + i * stride)); | ||
} | ||
@@ -495,2 +493,3 @@ | ||
* @param {import('./types.js').OffsetArray} [options.offsets] Offsets buffer | ||
* @param {import('./types.js').OffsetArray} [options.sizes] Sizes buffer | ||
* @param {Batch[]} [options.children] Children batches | ||
@@ -504,2 +503,3 @@ */ | ||
offsets, | ||
sizes, | ||
children | ||
@@ -512,2 +512,3 @@ }) { | ||
this.offsets = offsets; | ||
this.sizes = sizes; | ||
this.children = children; | ||
@@ -886,2 +887,32 @@ if (!nullCount) { | ||
}; | ||
var ListViewBatch = class extends ArrayBatch { | ||
/** | ||
* @param {number} index | ||
* @returns {import('./types.js').ValueArray<V>} | ||
*/ | ||
value(index) { | ||
const a = ( | ||
/** @type {number} */ | ||
this.offsets[index] | ||
); | ||
const b = a + /** @type {number} */ | ||
this.sizes[index]; | ||
return this.children[0].slice(a, b); | ||
} | ||
}; | ||
var LargeListViewBatch = class extends ArrayBatch { | ||
/** | ||
* @param {number} index | ||
* @returns {import('./types.js').ValueArray<V>} | ||
*/ | ||
value(index) { | ||
const a = ( | ||
/** @type {bigint} */ | ||
this.offsets[index] | ||
); | ||
const b = a + /** @type {bigint} */ | ||
this.sizes[index]; | ||
return this.children[0].slice(toNumber(a), toNumber(b)); | ||
} | ||
}; | ||
var FixedBatch = class extends ArrayBatch { | ||
@@ -1026,2 +1057,17 @@ /** | ||
}; | ||
var RunEndEncodedBatch = class extends ArrayBatch { | ||
/** | ||
* @param {number} index The value index. | ||
*/ | ||
value(index) { | ||
const [{ values: runs }, vals] = this.children; | ||
return vals.at( | ||
bisect( | ||
/** @type {import('./types.js').IntegerArray} */ | ||
runs, | ||
index | ||
) | ||
); | ||
} | ||
}; | ||
var DictionaryBatch = class extends ArrayBatch { | ||
@@ -1059,2 +1105,53 @@ /** | ||
}; | ||
var ViewBatch = class extends ArrayBatch { | ||
/** | ||
* Create a new view batch. | ||
* @param {object} options Batch options. | ||
* @param {number} options.length The length of the batch | ||
* @param {number} options.nullCount The null value count | ||
* @param {Uint8Array} [options.validity] Validity bitmap buffer | ||
* @param {Uint8Array} options.values Values buffer | ||
* @param {Uint8Array[]} options.data View data buffers | ||
*/ | ||
constructor({ data, ...rest }) { | ||
super(rest); | ||
this.data = data; | ||
} | ||
/** | ||
* Get the binary data at the provided index. | ||
* @param {number} index The value index. | ||
* @returns {Uint8Array} | ||
*/ | ||
view(index) { | ||
const { values, data } = this; | ||
const offset = index << 4; | ||
let start = offset + 4; | ||
let buf = ( | ||
/** @type {Uint8Array} */ | ||
values | ||
); | ||
const length = readInt32(buf, offset); | ||
if (length > 12) { | ||
start = readInt32(buf, offset + 12); | ||
buf = data[readInt32(buf, offset + 8)]; | ||
} | ||
return buf.subarray(start, start + length); | ||
} | ||
}; | ||
var BinaryViewBatch = class extends ViewBatch { | ||
/** | ||
* @param {number} index The value index. | ||
*/ | ||
value(index) { | ||
return this.view(index); | ||
} | ||
}; | ||
var Utf8ViewBatch = class extends ViewBatch { | ||
/** | ||
* @param {number} index The value index. | ||
*/ | ||
value(index) { | ||
return decodeUtf8(this.view(index)); | ||
} | ||
}; | ||
@@ -1123,3 +1220,3 @@ // src/column.js | ||
const { data, offsets } = this; | ||
const i = bisectOffsets(offsets, index); | ||
const i = bisect(offsets, index) - 1; | ||
return data[i]?.at(index - offsets[i]); | ||
@@ -1193,2 +1290,4 @@ } | ||
case Type.Bool: | ||
case Type.BinaryView: | ||
case Type.Utf8View: | ||
return { typeId }; | ||
@@ -1202,6 +1301,9 @@ case Type.Binary: | ||
case Type.List: | ||
return { typeId, children: [children?.[0] ?? null], offsets: int32 }; | ||
case Type.ListView: | ||
return { typeId, children: [children?.[0]], offsets: int32 }; | ||
case Type.LargeList: | ||
return { typeId, children: [children?.[0] ?? null], offsets: int64 }; | ||
case Type.LargeListView: | ||
return { typeId, children: [children?.[0]], offsets: int64 }; | ||
case Type.Struct: | ||
case Type.RunEndEncoded: | ||
return { typeId, children }; | ||
@@ -1368,3 +1470,2 @@ case Type.Int: | ||
const get = table(buf, index); | ||
const { length, base } = readVector(buf, get(6, readOffset)); | ||
return { | ||
@@ -1376,3 +1477,3 @@ typeId: Type.Union, | ||
), | ||
typeIds: new int32(buf.buffer, buf.byteOffset + base, length), | ||
typeIds: readVector(buf, get(6, readOffset), 4, readInt32), | ||
children: children ?? [], | ||
@@ -1385,11 +1486,15 @@ offsets: int32 | ||
function decodeMetadata(buf, index) { | ||
const { length, base } = readVector(buf, index); | ||
const metadata = length > 0 ? /* @__PURE__ */ new Map() : null; | ||
for (let i = 0; i < length; ++i) { | ||
const get = table(buf, base + i * 4); | ||
const key = get(4, readString); | ||
const val = get(6, readString); | ||
if (key || val) metadata.set(key, val); | ||
} | ||
return metadata?.size ? metadata : null; | ||
const entries = readVector(buf, index, 4, (buf2, pos) => { | ||
const get = table(buf2, pos); | ||
return ( | ||
/** @type {[string, string]} */ | ||
[ | ||
get(4, readString), | ||
// 4: key (string) | ||
get(6, readString) | ||
// 6: key (string) | ||
] | ||
); | ||
}); | ||
return entries.length ? new Map(entries) : null; | ||
} | ||
@@ -1413,8 +1518,8 @@ | ||
function decodeSchemaFields(buf, fieldsOffset, dictionaryTypes) { | ||
const { length, base } = readVector(buf, fieldsOffset); | ||
const fields = []; | ||
for (let i = 0; i < length; ++i) { | ||
fields.push(decodeField(buf, base + i * 4, dictionaryTypes)); | ||
} | ||
return fields; | ||
return readVector( | ||
buf, | ||
fieldsOffset, | ||
4, | ||
(buf2, pos) => decodeField(buf2, pos, dictionaryTypes) | ||
); | ||
} | ||
@@ -1425,4 +1530,4 @@ function decodeField(buf, index, dictionaryTypes) { | ||
const typeOffset = get(10, readOffset, 0); | ||
const dict = get(12, (buf2, off) => decodeDictionary(buf2, off)); | ||
const children = get(14, decodeFieldChildren); | ||
const dict = get(12, decodeDictionary); | ||
const children = get(14, (buf2, off) => decodeFieldChildren(buf2, off, dictionaryTypes)); | ||
let type; | ||
@@ -1448,9 +1553,9 @@ if (dict) { | ||
} | ||
function decodeFieldChildren(buf, fieldOffset, dictionaries) { | ||
const { length, base } = readVector(buf, fieldOffset); | ||
const children = []; | ||
for (let i = 0; i < length; ++i) { | ||
const pos = base + i * 4; | ||
children.push(decodeField(buf, pos, dictionaries)); | ||
} | ||
function decodeFieldChildren(buf, fieldOffset, dictionaryTypes) { | ||
const children = readVector( | ||
buf, | ||
fieldOffset, | ||
4, | ||
(buf2, pos) => decodeField(buf2, pos, dictionaryTypes) | ||
); | ||
return children.length ? children : null; | ||
@@ -1478,31 +1583,14 @@ } | ||
} | ||
const nodes = []; | ||
const nodeVector = get(6, readVector); | ||
if (nodeVector) { | ||
const { length, base } = nodeVector; | ||
for (let i = 0; i < length; ++i) { | ||
const pos = base + i * 16; | ||
nodes.push({ | ||
length: readInt64AsNum(buf, pos), | ||
nullCount: readInt64AsNum(buf, pos + 8) | ||
}); | ||
} | ||
} | ||
const buffers = []; | ||
const bufferVector = get(8, readVector); | ||
if (bufferVector) { | ||
const { length, base } = bufferVector; | ||
const adjust = version < Version.V4; | ||
for (let i = 0; i < length; ++i) { | ||
const pos = base + i * 16 + (adjust ? 8 * (i + 1) : 0); | ||
buffers.push({ | ||
offset: readInt64AsNum(buf, pos), | ||
length: readInt64AsNum(buf, pos + 8) | ||
}); | ||
} | ||
} | ||
const offset = version < Version.V4 ? 8 : 0; | ||
return { | ||
length: get(4, readInt64AsNum, 0), | ||
nodes, | ||
buffers | ||
nodes: readVector(buf, get(6, readOffset), 16, (buf2, pos) => ({ | ||
length: readInt64AsNum(buf2, pos), | ||
nullCount: readInt64AsNum(buf2, pos + 8) | ||
})), | ||
buffers: readVector(buf, get(8, readOffset), 16 + offset, (buf2, pos) => ({ | ||
offset: readInt64AsNum(buf2, pos + offset), | ||
length: readInt64AsNum(buf2, pos + offset + 8) | ||
})), | ||
variadic: readVector(buf, get(12, readOffset), 8, readInt64AsNum) | ||
}; | ||
@@ -1578,8 +1666,3 @@ } | ||
function decodeBlocks(buf, index) { | ||
const { length, base } = readVector(buf, index); | ||
const batches = []; | ||
for (let i = 0; i < length; ++i) { | ||
batches.push(decodeBlock(buf, base + i * 24)); | ||
} | ||
return batches; | ||
return readVector(buf, index, 24, decodeBlock); | ||
} | ||
@@ -1778,3 +1861,3 @@ | ||
const [{ offsets }] = children; | ||
const i = bisectOffsets(offsets, index); | ||
const i = bisect(offsets, index) - 1; | ||
return rowObject(names, children, i, index - offsets[i]); | ||
@@ -1843,5 +1926,6 @@ } | ||
return (batch) => { | ||
const { length, nodes, buffers, body } = batch; | ||
const { length, nodes, buffers, variadic, body } = batch; | ||
let nodeIndex = -1; | ||
let bufferIndex = -1; | ||
let variadicIndex = -1; | ||
return { | ||
@@ -1855,2 +1939,3 @@ ...base, | ||
}, | ||
variadic: () => variadic[++variadicIndex], | ||
visitAll(list) { | ||
@@ -1882,2 +1967,10 @@ return list.map((x) => visit(x.type, this)); | ||
}); | ||
const view = (BatchType) => new BatchType({ | ||
...node, | ||
validity: ctx.buffer(), | ||
values: ctx.buffer(), | ||
// views buffer | ||
data: Array.from({ length: ctx.variadic() }, () => ctx.buffer()) | ||
// data buffers | ||
}); | ||
const list = (BatchType) => new BatchType({ | ||
@@ -1889,2 +1982,9 @@ ...node, | ||
}); | ||
const listview = (BatchType) => new BatchType({ | ||
...node, | ||
validity: ctx.buffer(), | ||
offsets: ctx.buffer(type.offsets), | ||
sizes: ctx.buffer(type.offsets), | ||
children: ctx.visitAll(type.children) | ||
}); | ||
const kids = (BatchType, opt) => new BatchType({ | ||
@@ -1926,2 +2026,7 @@ ...node, | ||
return offset(LargeBinaryBatch); | ||
// views with variadic buffers | ||
case Type.BinaryView: | ||
return view(BinaryViewBatch); | ||
case Type.Utf8View: | ||
return view(Utf8ViewBatch); | ||
// validity, offset, and list child | ||
@@ -1934,2 +2039,7 @@ case Type.List: | ||
return list(useMap ? MapBatch : MapEntryBatch); | ||
// validity, offset, size, and list child | ||
case Type.ListView: | ||
return listview(ListViewBatch); | ||
case Type.LargeListView: | ||
return listview(LargeListViewBatch); | ||
// validity and children | ||
@@ -1942,2 +2052,8 @@ case Type.FixedSizeList: | ||
}); | ||
// children only | ||
case Type.RunEndEncoded: | ||
return new RunEndEncodedBatch({ | ||
...node, | ||
children: ctx.visitAll(type.children) | ||
}); | ||
// dictionary | ||
@@ -1959,12 +2075,13 @@ case Type.Dictionary: { | ||
const isSparse = type.mode === UnionMode.Sparse; | ||
const typeIds = ctx.buffer(int8); | ||
const offsets = isSparse ? null : ctx.buffer(type.offsets); | ||
const children = ctx.visitAll(type.children); | ||
const map = type.typeIds.reduce((map2, id, i) => (map2[id] = i, map2), {}); | ||
const options = { ...node, map, typeIds, offsets, children }; | ||
return isSparse ? new SparseUnionBatch(options) : new DenseUnionBatch(options); | ||
return new (isSparse ? SparseUnionBatch : DenseUnionBatch)({ | ||
...node, | ||
map: type.typeIds.reduce((map, id, i) => (map[id] = i, map), {}), | ||
typeIds: ctx.buffer(int8), | ||
offsets: isSparse ? null : ctx.buffer(type.offsets), | ||
children: ctx.visitAll(type.children) | ||
}); | ||
} | ||
// unsupported type | ||
default: | ||
throw new Error(`Unsupported type: ${typeId}, (${keyFor(Type, typeId)})`); | ||
throw new Error(`Unsupported type: ${typeId} ${keyFor(Type, typeId)}`); | ||
} | ||
@@ -1971,0 +2088,0 @@ } |
@@ -1,1 +0,1 @@ | ||
var E={V1:0,V2:1,V3:2,V4:3,V5:4},ie={Little:0,Big:1},S={NONE:0,Schema:1,DictionaryBatch:2,RecordBatch:3,Tensor:4,SparseTensor:5},i={Dictionary:-1,NONE:0,Null:1,Int:2,Float:3,Binary:4,Utf8:5,Bool:6,Decimal:7,Date:8,Time:9,Timestamp:10,Interval:11,List:12,Struct:13,Union:14,FixedSizeBinary:15,FixedSizeList:16,Map:17,Duration:18,LargeBinary:19,LargeUtf8:20,LargeList:21,RunEndEncoded:22,BinaryView:23,Utf8View:24,ListView:25,LargeListView:26},F={HALF:0,SINGLE:1,DOUBLE:2},_={DAY:0,MILLISECOND:1},w={SECOND:0,MILLISECOND:1,MICROSECOND:2,NANOSECOND:3},C={YEAR_MONTH:0,DAY_TIME:1,MONTH_DAY_NANO:2},H={Sparse:0,Dense:1};var ce=Uint8Array,wt=Uint16Array,Mt=Uint32Array,le=BigUint64Array,Tt=Int8Array,ue=Int16Array,D=Int32Array,T=BigInt64Array,Pt=Float32Array,W=Float64Array;function Yt(e,t){let r=Math.log2(e)-3;return(t?[Tt,ue,D,T]:[ce,wt,Mt,le])[r]}function Bt(e,t){return(e[t>>3]&1<<t%8)!==0}var de=new TextDecoder("utf-8");function X(e){return de.decode(e)}function k(e,t){for(let[r,n]of Object.entries(e))if(n===t)return r;return"<Unknown>"}function N(e){if(e>Number.MAX_SAFE_INTEGER||e<Number.MIN_SAFE_INTEGER)throw Error(`BigInt exceeds integer number representation: ${e}`);return Number(e)}function Lt(e,t){return N(e/t)+N(e%t)/N(t)}function q(e,t){let r=0,n=e.length;do{let o=r+n>>>1;e[o]<=t?r=o+1:n=o}while(r<n);return--r}function d(e,t){let r=t+p(e,t),n=r-p(e,r),o=x(e,n);return(s,a,c=null)=>{if(s<o){let l=x(e,n+s);if(l)return a(e,r+l)}return c}}function B(e,t){return t}function L(e,t){return!!fe(e,t)}function fe(e,t){return P(e,t)<<24>>24}function P(e,t){return e[t]}function x(e,t){return pe(e,t)<<16>>16}function pe(e,t){return e[t]|e[t+1]<<8}function p(e,t){return e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24}function $t(e,t){return p(e,t)>>>0}function he(e,t){return BigInt.asIntN(64,BigInt($t(e,t))+(BigInt($t(e,t+4))<<BigInt(32)))}function v(e,t){return N(he(e,t))}function V(e,t){let r=t+p(e,t),n=p(e,r);return r+=4,X(e.subarray(r,r+n))}function b(e,t){return{length:p(e,t+p(e,t)),base:t+p(e,t)+4}}function jt(e){return e instanceof R}var Y=class{static ArrayType=null;constructor({length:t,nullCount:r,validity:n,values:o,offsets:s,children:a}){this.length=t,this.nullCount=r,this.validity=n,this.values=o,this.offsets=s,this.children=a,r||(this.at=c=>this.value(c))}get[Symbol.toStringTag](){return"Batch"}at(t){return this.isValid(t)?this.value(t):null}isValid(t){return Bt(this.validity,t)}value(t){return this.values[t]}slice(t,r){let n=r-t,o=Array(n);for(let s=0;s<n;++s)o[s]=this.at(t+s);return o}*[Symbol.iterator](){for(let t=0;t<this.length;++t)yield this.at(t)}},R=class extends Y{constructor(t){super(t);let{length:r,values:n}=this;this.values=n.subarray(0,r)}slice(t,r){return this.nullCount?super.slice(t,r):this.values.subarray(t,r)}[Symbol.iterator](){return this.nullCount?super[Symbol.iterator]():this.values[Symbol.iterator]()}},z=class extends Y{static ArrayType=W},y=class extends Y{static ArrayType=Array},J=class extends y{value(t){return null}},M=class extends z{value(t){return N(this.values[t])}},K=class extends z{value(t){let r=this.values[t],n=(r&31744)>>10,o=(r&1023)/1024,s=(-1)**((r&32768)>>15);switch(n){case 31:return s*(o?Number.NaN:1/0);case 0:return s*(o?6103515625e-14*o:0)}return s*2**(n-15)*(1+o)}},Q=class extends y{value(t){return Bt(this.values,t)}},Gt=Array.from({length:8},(e,t)=>Math.pow(2,t*32)),tt=class extends z{constructor({bitWidth:t,scale:r,...n}){super(n),this.stride=t>>5,this.scale=Math.pow(10,r)}value(t){let r=this.values,n=this.stride,o=t<<2,s=0;if((r[n-1]|0)<0){for(let a=0;a<n;++a)s+=~r[a+o]*Gt[a];s=-(s+1)}else for(let a=0;a<n;++a)s+=r[a+o]*Gt[a];return s/this.scale}},et=class extends y{constructor(t){super(t),this.source=t}value(t){return new Date(this.source.value(t))}},rt=class extends z{value(t){return 864e5*this.values[t]}},Zt=M,nt=class extends M{value(t){return super.value(t)*1e3}},Wt=M,st=class extends M{value(t){return Lt(this.values[t],1000n)}},ot=class extends M{value(t){return Lt(this.values[t],1000000n)}},at=class extends y{value(t){return this.values.subarray(t<<1,t+1<<1)}},it=class extends y{value(t){let r=this.values[t];return Int32Array.of(Math.trunc(r/12),Math.trunc(r%12))}},ct=class extends y{value(t){let r=this.values,n=t<<2;return Float64Array.of(p(r,n),p(r,n+4),v(r,n+8))}},Xt=({values:e,offsets:t},r)=>e.subarray(t[r],t[r+1]),qt=({values:e,offsets:t},r)=>e.subarray(N(t[r]),N(t[r+1])),lt=class extends y{value(t){return Xt(this,t)}},ut=class extends y{value(t){return qt(this,t)}},dt=class extends y{value(t){return X(Xt(this,t))}},ft=class extends y{value(t){return X(qt(this,t))}},pt=class extends y{value(t){let r=this.offsets;return this.children[0].slice(r[t],r[t+1])}},ht=class extends y{value(t){let r=this.offsets;return this.children[0].slice(N(r[t]),N(r[t+1]))}},mt=class extends y{constructor({stride:t,...r}){super(r),this.stride=t}},yt=class extends mt{value(t){let{stride:r,values:n}=this;return n.subarray(t*r,(t+1)*r)}},gt=class extends mt{value(t){let{children:r,stride:n}=this;return r[0].slice(t*n,(t+1)*n)}};function Jt({children:e,offsets:t},r){let[n,o]=e[0].children,s=t[r],a=t[r+1],c=[];for(let l=s;l<a;++l)c.push([n.at(l),o.at(l)]);return c}var It=class extends y{value(t){return Jt(this,t)}},vt=class extends y{value(t){return new Map(Jt(this,t))}},$=class extends y{constructor({typeIds:t,map:r,...n}){super(n),this.typeIds=t,this.map=r}value(t){let{typeIds:r,children:n,map:o}=this;return n[o[r[t]]].at(t)}},xt=class extends ${value(t){return super.value(this.offsets[t])}},bt=class extends y{constructor({names:t,...r}){super(r),this.names=t}value(t){let{children:r,names:n}=this,o=n.length,s={};for(let a=0;a<o;++a)s[n[a]]=r[a].at(t);return s}},At=class extends y{constructor({dictionary:t,...r}){super(r),this.cache=t.cache()}value(t){return this.cache[this.key(t)]}key(t){return this.values[t]}};function Ut(e){let t=[];return{add(r){return t.push(r),this},clear:()=>t=[],done:()=>new Ot(e,t)}}var Ot=class{constructor(t,r){this.type=t,this.length=r.reduce((s,a)=>s+a.length,0),this.nullCount=r.reduce((s,a)=>s+a.nullCount,0),this.data=r;let n=r.length,o=new Int32Array(n+1);if(n===1){let[s]=r;o[1]=s.length,this.at=a=>s.at(a)}else for(let s=0,a=0;s<n;++s)o[s+1]=a+=r[s].length;this.offsets=o}get[Symbol.toStringTag](){return"Column"}[Symbol.iterator](){let t=this.data;return t.length===1?t[0][Symbol.iterator]():me(t)}at(t){let{data:r,offsets:n}=this,o=q(n,t);return r[o]?.at(t-n[o])}get(t){return this.at(t)}toArray(){let{length:t,nullCount:r,data:n}=this,o=!r&&jt(n[0]),s=n.length;if(o&&s===1)return n[0].values;let a=!s||r>0?Array:n[0].constructor.ArrayType??n[0].values.constructor,c=new a(t);return o?ye(c,n):ge(c,n)}cache(){return this._cache??(this._cache=this.toArray())}};function*me(e){for(let t=0;t<e.length;++t){let r=e[t][Symbol.iterator]();for(let n=r.next();!n.done;n=r.next())yield n.value}}function ye(e,t){for(let r=0,n=0;r<t.length;++r){let{values:o}=t[r];e.set(o,n),n+=o.length}return e}function ge(e,t){let r=-1;for(let n=0;n<t.length;++n){let o=t[n];for(let s=0;s<o.length;++s)e[++r]=o.at(s)}return e}function Ft(e,t,r,n){switch(r){case i.NONE:case i.Null:case i.Bool:return{typeId:r};case i.Binary:case i.Utf8:return{typeId:r,offsets:D};case i.LargeBinary:case i.LargeUtf8:return{typeId:r,offsets:T};case i.List:return{typeId:r,children:[n?.[0]??null],offsets:D};case i.LargeList:return{typeId:r,children:[n?.[0]??null],offsets:T};case i.Struct:return{typeId:r,children:n};case i.Int:return Vt(e,t);case i.Float:return Ie(e,t);case i.Decimal:return ve(e,t);case i.Date:return xe(e,t);case i.Time:return be(e,t);case i.Timestamp:return Ae(e,t);case i.Interval:return Se(e,t);case i.Duration:return De(e,t);case i.FixedSizeBinary:return Ne(e,t);case i.FixedSizeList:return Ee(e,t,n);case i.Map:return we(e,t,n);case i.Union:return Me(e,t,n)}throw new Error(`Unrecognized type: "${k(i,r)}" (id ${r})`)}function Ct(e,t){return{typeId:i.Int,bitWidth:e,signed:t,values:Yt(e,t)}}function Vt(e,t){let r=d(e,t);return Ct(r(4,p,0),r(6,L,!1))}function Ie(e,t){let n=d(e,t)(4,x,F.HALF);return{typeId:i.Float,precision:n,values:n===F.HALF?wt:n===F.SINGLE?Pt:W}}function ve(e,t){let r=d(e,t),n=r(8,p,128);return{typeId:i.Decimal,precision:r(4,p,0),scale:r(6,p,0),bitWidth:n,values:Mt}}function xe(e,t){let n=d(e,t)(4,x,_.MILLISECOND);return{typeId:i.Date,unit:n,values:n===_.DAY?D:T}}function be(e,t){let r=d(e,t),n=r(6,p,32);return{typeId:i.Time,unit:r(4,x,w.MILLISECOND),bitWidth:n,values:n===32?D:T}}function Ae(e,t){let r=d(e,t);return{typeId:i.Timestamp,unit:r(4,x,w.SECOND),timezone:r(6,V),values:T}}function Se(e,t){let n=d(e,t)(4,x,C.YEAR_MONTH);return{typeId:i.Interval,unit:n,values:n===C.MONTH_DAY_NANO?void 0:D}}function De(e,t){let r=d(e,t);return{typeId:i.Duration,unit:r(4,x,w.MILLISECOND),values:T}}function Ne(e,t){let r=d(e,t);return{typeId:i.FixedSizeBinary,stride:r(4,p,0)}}function Ee(e,t,r){let n=d(e,t);return{typeId:i.FixedSizeList,stride:n(4,p,0),children:[r?.[0]??null]}}function we(e,t,r){let n=d(e,t);return{typeId:i.Map,keysSorted:n(4,L,!1),children:r,offsets:D}}function Me(e,t,r){let n=d(e,t),{length:o,base:s}=b(e,n(6,B));return{typeId:i.Union,mode:n(4,x,H.Sparse),typeIds:new D(e.buffer,e.byteOffset+s,o),children:r??[],offsets:D}}function G(e,t){let{length:r,base:n}=b(e,t),o=r>0?new Map:null;for(let s=0;s<r;++s){let a=d(e,n+s*4),c=a(4,V),l=a(6,V);(c||l)&&o.set(c,l)}return o?.size?o:null}function St(e,t,r){let n=new Map,o=d(e,t);return{version:r,endianness:o(4,x,0),fields:o(6,(s,a)=>Te(s,a,n),[]),metadata:o(8,G),dictionaryTypes:n}}function Te(e,t,r){let{length:n,base:o}=b(e,t),s=[];for(let a=0;a<n;++a)s.push(Kt(e,o+a*4,r));return s}function Kt(e,t,r){let n=d(e,t),o=n(8,P,i.NONE),s=n(10,B,0),a=n(12,(g,h)=>Le(g,h)),c=n(14,Be),l;if(a){let{id:g}=a,h=r.get(g);h||(h=Ft(e,s,o,c),r.set(g,h)),a.type=h,l=a}else l=Ft(e,s,o,c);return{name:n(4,V),type:l,nullable:n(6,L,!1),metadata:n(16,G)}}function Be(e,t,r){let{length:n,base:o}=b(e,t),s=[];for(let a=0;a<n;++a){let c=o+a*4;s.push(Kt(e,c,r))}return s.length?s:null}function Le(e,t){if(!t)return null;let r=d(e,t);return{type:null,typeId:i.Dictionary,id:r(4,v,0),keys:r(6,Vt,Ct(32,!0)),ordered:r(8,L,!1)}}function Dt(e,t,r){let n=d(e,t);if(n(10,B,0))throw new Error("Record batch compression not implemented");let o=[],s=n(6,b);if(s){let{length:l,base:g}=s;for(let h=0;h<l;++h){let u=g+h*16;o.push({length:v(e,u),nullCount:v(e,u+8)})}}let a=[],c=n(8,b);if(c){let{length:l,base:g}=c,h=r<E.V4;for(let u=0;u<l;++u){let f=g+u*16+(h?8*(u+1):0);a.push({offset:v(e,f),length:v(e,f+8)})}}return{length:n(4,v,0),nodes:o,buffers:a}}function Qt(e,t,r){let n=d(e,t);return{id:n(4,v,0),data:n(6,(o,s)=>Dt(o,s,r)),isDelta:n(8,L,!1)}}var Oe=(e,t)=>`Expected to read ${e} metadata bytes, but only read ${t}.`,Ue=(e,t)=>`Expected to read ${e} bytes for message body, but only read ${t}.`,Fe=e=>`Unsupported message type: ${e} (${k(S,e)})`;function Nt(e,t){let r=p(e,t)||0;if(t+=4,r===-1&&(r=p(e,t)||0,t+=4),r===0)return null;let n=e.subarray(t,t+=r);if(n.byteLength<r)throw new Error(Oe(r,n.byteLength));let o=d(n,0),s=o(4,x,E.V1),a=o(6,P,S.NONE),c=o(8,B,0),l=o(10,v,0),g;if(c){let h=a===S.Schema?St:a===S.DictionaryBatch?Qt:a===S.RecordBatch?Dt:null;if(!h)throw new Error(Fe(a));if(g=h(n,c,s),l>0){let u=e.subarray(t,t+=l);if(u.byteLength<l)throw new Error(Ue(l,u.byteLength));g.body=u}}return{version:s,type:a,index:t,content:g}}function Ce(e,t){return{offset:v(e,t),metadataLength:p(e,t+8),bodyLength:v(e,t+16)}}function _t(e,t){let{length:r,base:n}=b(e,t),o=[];for(let s=0;s<r;++s)o.push(Ce(e,n+s*24));return o}function ee(e){let t=e instanceof ArrayBuffer?new Uint8Array(e):e;return!Array.isArray(t)&&Ve(t)?ke(t):_e(t)}var re=Uint8Array.of(65,82,82,79,87,49);function Ve(e){if(!e||e.length<4)return!1;for(let t=0;t<6;++t)if(re[t]!==e[t])return!1;return!0}function _e(e){let t=[e].flat(),r,n=[],o=[];for(let s of t){let a=0;for(;;){let c=Nt(s,a);if(c===null)break;if(a=c.index,!!c.content)switch(c.type){case S.Schema:r||(r=c.content);break;case S.RecordBatch:n.push(c.content);break;case S.DictionaryBatch:o.push(c.content);break}}}return{schema:r,dictionaries:o,records:n,metadata:null}}function ke(e){let t=e.byteLength-(re.length+4),r=p(e,t),n=d(e,t-r),o=n(4,x,E.V1),s=n(8,_t,[]),a=n(10,_t,[]);return{schema:n(6,(c,l)=>St(c,l,o)),dictionaries:s.map(({offset:c})=>Nt(e,c).content),records:a.map(({offset:c})=>Nt(e,c).content),metadata:n(12,G)}}var Et=class e{constructor(t,r){this.schema=t,this.names=t.fields.map(n=>n.name),this.children=r}get[Symbol.toStringTag](){return"Table"}get numCols(){return this.names.length}get numRows(){return this.children[0]?.length??0}getChildAt(t){return this.children[t]}getChild(t){let r=this.names.findIndex(n=>n===t);return r>-1?this.children[r]:void 0}selectAt(t,r=[]){let{children:n,schema:o}=this,{fields:s}=o;return new e({...o,fields:t.map((a,c)=>Re(s[a],r[c]))},t.map(a=>n[a]))}select(t,r){let n=this.names,o=t.map(s=>n.indexOf(s));return this.selectAt(o,r)}toColumns(){let{children:t,names:r}=this,n={};return r.forEach((o,s)=>n[o]=t[s]?.toArray()??[]),n}toArray(){let{children:t,numRows:r,names:n}=this,o=t[0]?.data??[],s=Array(r);for(let a=0,c=-1;a<o.length;++a)for(let l=0;l<o[a].length;++l)s[++c]=kt(n,t,a,l);return s}*[Symbol.iterator](){let{children:t,names:r}=this,n=t[0]?.data??[];for(let o=0;o<n.length;++o)for(let s=0;s<n[o].length;++s)yield kt(r,t,o,s)}at(t){let{names:r,children:n,numRows:o}=this;if(t<0||t>=o)return null;let[{offsets:s}]=n,a=q(s,t);return kt(r,n,a,t-s[a])}get(t){return this.at(t)}};function Re(e,t){return t!=null&&t!==e.name?{...e,name:t}:e}function kt(e,t,r,n){let o={};for(let s=0;s<e.length;++s)o[e[s]]=t[s].data[r].at(n);return o}function ze(e,t){return He(ee(e),t)}function He(e,t={}){let{schema:r={fields:[]},dictionaries:n,records:o}=e,{version:s,fields:a,dictionaryTypes:c}=r,l=new Map,g=Pe(t,s,l),h=new Map;for(let f of n){let{id:I,data:O,isDelta:U,body:j}=f,m=c.get(I),A=Rt(m,g({...O,body:j}));if(h.has(I)){let Z=h.get(I);U||Z.clear(),Z.add(A)}else{if(U)throw new Error("Delta update can not be first dictionary batch.");h.set(I,Ut(m).add(A))}}h.forEach((f,I)=>l.set(I,f.done()));let u=a.map(f=>Ut(f.type));for(let f of o){let I=g(f);a.forEach((O,U)=>u[U].add(Rt(O.type,I)))}return new Et(r,u.map(f=>f.done()))}function Pe(e,t,r){let n={version:t,options:e,dictionary:o=>r.get(o)};return o=>{let{length:s,nodes:a,buffers:c,body:l}=o,g=-1,h=-1;return{...n,length:s,node:()=>a[++g],buffer:u=>{let{length:f,offset:I}=c[++h];return u?new u(l.buffer,l.byteOffset+I,f/u.BYTES_PER_ELEMENT):l.subarray(I,I+f)},visitAll(u){return u.map(f=>Rt(f.type,this))}}}}function Rt(e,t){let{typeId:r,bitWidth:n,precision:o,scale:s,stride:a,unit:c}=e,{useBigInt:l,useDate:g,useMap:h}=t.options;if(r===i.Null){let{length:m}=t;return new J({length:m,nullCount:m})}let u=t.node(),f=(m,A)=>new m({...u,...A,validity:t.buffer(),values:t.buffer(e.values)}),I=m=>new m({...u,validity:t.buffer(),offsets:t.buffer(e.offsets),values:t.buffer()}),O=m=>new m({...u,validity:t.buffer(),offsets:t.buffer(e.offsets),children:t.visitAll(e.children)}),U=(m,A)=>new m({...u,...A,validity:t.buffer(),children:t.visitAll(e.children)}),j=g?m=>new et(f(m)):f;switch(r){case i.Bool:return f(Q);case i.Int:case i.Time:case i.Duration:return f(n===64&&!l?M:R);case i.Float:return f(o===F.HALF?K:R);case i.Date:return j(c===_.DAY?rt:Zt);case i.Timestamp:return j(c===w.SECOND?nt:c===w.MILLISECOND?Wt:c===w.MICROSECOND?st:ot);case i.Decimal:return f(tt,{bitWidth:n,scale:s});case i.Interval:return f(c===C.DAY_TIME?at:c===C.YEAR_MONTH?it:ct);case i.FixedSizeBinary:return f(yt,{stride:a});case i.Utf8:return I(dt);case i.LargeUtf8:return I(ft);case i.Binary:return I(lt);case i.LargeBinary:return I(ut);case i.List:return O(pt);case i.LargeList:return O(ht);case i.Map:return O(h?vt:It);case i.FixedSizeList:return U(gt,{stride:a});case i.Struct:return U(bt,{names:e.children.map(m=>m.name)});case i.Dictionary:{let{id:m,keys:A}=e;return new At({...u,validity:t.buffer(),values:t.buffer(A.values),dictionary:t.dictionary(m)})}case i.Union:{t.version<E.V5&&t.buffer();let m=e.mode===H.Sparse,A=t.buffer(Tt),Z=m?null:t.buffer(e.offsets),ne=t.visitAll(e.children),se=e.typeIds.reduce((Ht,oe,ae)=>(Ht[oe]=ae,Ht),{}),zt={...u,map:se,typeIds:A,offsets:Z,children:ne};return m?new $(zt):new xt(zt)}default:throw new Error(`Unsupported type: ${r}, (${k(i,r)})`)}}export{_ as DateUnit,ie as Endianness,C as IntervalUnit,F as Precision,w as TimeUnit,i as Type,H as UnionMode,E as Version,ze as tableFromIPC}; | ||
var N={V1:0,V2:1,V3:2,V4:3,V5:4},ut={Little:0,Big:1},E={NONE:0,Schema:1,DictionaryBatch:2,RecordBatch:3,Tensor:4,SparseTensor:5},i={Dictionary:-1,NONE:0,Null:1,Int:2,Float:3,Binary:4,Utf8:5,Bool:6,Decimal:7,Date:8,Time:9,Timestamp:10,Interval:11,List:12,Struct:13,Union:14,FixedSizeBinary:15,FixedSizeList:16,Map:17,Duration:18,LargeBinary:19,LargeUtf8:20,LargeList:21,RunEndEncoded:22,BinaryView:23,Utf8View:24,ListView:25,LargeListView:26},O={HALF:0,SINGLE:1,DOUBLE:2},_={DAY:0,MILLISECOND:1},L={SECOND:0,MILLISECOND:1,MICROSECOND:2,NANOSECOND:3},C={YEAR_MONTH:0,DAY_TIME:1,MONTH_DAY_NANO:2},$={Sparse:0,Dense:1};var dt=Uint8Array,Oe=Uint16Array,Ce=Uint32Array,ft=BigUint64Array,Ve=Int8Array,ht=Int16Array,M=Int32Array,U=BigInt64Array,je=Float32Array,J=Float64Array;function We(t,e){let r=Math.log2(t)-3;return(e?[Ve,ht,M,U]:[dt,Oe,Ce,ft])[r]}function _e(t,e){return(t[e>>3]&1<<e%8)!==0}var pt=new TextDecoder("utf-8");function G(t){return pt.decode(t)}function R(t,e){for(let[r,n]of Object.entries(t))if(n===e)return r;return"<Unknown>"}function A(t){if(t>Number.MAX_SAFE_INTEGER||t<Number.MIN_SAFE_INTEGER)throw Error(`BigInt exceeds integer number representation: ${t}`);return Number(t)}function Re(t,e){return A(t/e)+A(t%e)/A(e)}function k(t,e){let r=0,n=t.length;if(n<=2147483648)do{let s=r+n>>>1;t[s]<=e?r=s+1:n=s}while(r<n);else do{let s=Math.trunc((r+n)/2);t[s]<=e?r=s+1:n=s}while(r<n);return r}function d(t,e){let r=e+u(t,e),n=r-u(t,r),s=x(t,n);return(o,a,c=null)=>{if(o<s){let l=x(t,n+o);if(l)return a(t,r+l)}return c}}function D(t,e){return e}function F(t,e){return!!mt(t,e)}function mt(t,e){return Z(t,e)<<24>>24}function Z(t,e){return t[e]}function x(t,e){return yt(t,e)<<16>>16}function yt(t,e){return t[e]|t[e+1]<<8}function u(t,e){return t[e]|t[e+1]<<8|t[e+2]<<16|t[e+3]<<24}function Xe(t,e){return u(t,e)>>>0}function gt(t,e){return BigInt.asIntN(64,BigInt(Xe(t,e))+(BigInt(Xe(t,e+4))<<BigInt(32)))}function v(t,e){return A(gt(t,e))}function V(t,e){let r=e+u(t,e),n=u(t,r);return r+=4,G(t.subarray(r,r+n))}function b(t,e,r,n){if(!e)return[];let s=u(t,e+u(t,e)),o=e+u(t,e)+4;return Array.from({length:s},(a,c)=>n(t,o+c*r))}function Je(t){return t instanceof z}var j=class{static ArrayType=null;constructor({length:e,nullCount:r,validity:n,values:s,offsets:o,sizes:a,children:c}){this.length=e,this.nullCount=r,this.validity=n,this.values=s,this.offsets=o,this.sizes=a,this.children=c,r||(this.at=l=>this.value(l))}get[Symbol.toStringTag](){return"Batch"}at(e){return this.isValid(e)?this.value(e):null}isValid(e){return _e(this.validity,e)}value(e){return this.values[e]}slice(e,r){let n=r-e,s=Array(n);for(let o=0;o<n;++o)s[o]=this.at(e+o);return s}*[Symbol.iterator](){for(let e=0;e<this.length;++e)yield this.at(e)}},z=class extends j{constructor(e){super(e);let{length:r,values:n}=this;this.values=n.subarray(0,r)}slice(e,r){return this.nullCount?super.slice(e,r):this.values.subarray(e,r)}[Symbol.iterator](){return this.nullCount?super[Symbol.iterator]():this.values[Symbol.iterator]()}},H=class extends j{static ArrayType=J},h=class extends j{static ArrayType=Array},K=class extends h{value(e){return null}},B=class extends H{value(e){return A(this.values[e])}},Q=class extends H{value(e){let r=this.values[e],n=(r&31744)>>10,s=(r&1023)/1024,o=(-1)**((r&32768)>>15);switch(n){case 31:return o*(s?Number.NaN:1/0);case 0:return o*(s?6103515625e-14*s:0)}return o*2**(n-15)*(1+s)}},ee=class extends h{value(e){return _e(this.values,e)}},qe=Array.from({length:8},(t,e)=>Math.pow(2,e*32)),te=class extends H{constructor({bitWidth:e,scale:r,...n}){super(n),this.stride=e>>5,this.scale=Math.pow(10,r)}value(e){let r=this.values,n=this.stride,s=e<<2,o=0;if((r[n-1]|0)<0){for(let a=0;a<n;++a)o+=~r[a+s]*qe[a];o=-(o+1)}else for(let a=0;a<n;++a)o+=r[a+s]*qe[a];return o/this.scale}},re=class extends h{constructor(e){super(e),this.source=e}value(e){return new Date(this.source.value(e))}},ne=class extends H{value(e){return 864e5*this.values[e]}},Ke=B,se=class extends B{value(e){return super.value(e)*1e3}},Qe=B,oe=class extends B{value(e){return Re(this.values[e],1000n)}},ae=class extends B{value(e){return Re(this.values[e],1000000n)}},ie=class extends h{value(e){return this.values.subarray(e<<1,e+1<<1)}},ce=class extends h{value(e){let r=this.values[e];return Int32Array.of(Math.trunc(r/12),Math.trunc(r%12))}},le=class extends h{value(e){let r=this.values,n=e<<2;return Float64Array.of(u(r,n),u(r,n+4),v(r,n+8))}},et=({values:t,offsets:e},r)=>t.subarray(e[r],e[r+1]),tt=({values:t,offsets:e},r)=>t.subarray(A(e[r]),A(e[r+1])),ue=class extends h{value(e){return et(this,e)}},de=class extends h{value(e){return tt(this,e)}},fe=class extends h{value(e){return G(et(this,e))}},he=class extends h{value(e){return G(tt(this,e))}},pe=class extends h{value(e){let r=this.offsets;return this.children[0].slice(r[e],r[e+1])}},me=class extends h{value(e){let r=this.offsets;return this.children[0].slice(A(r[e]),A(r[e+1]))}},ye=class extends h{value(e){let r=this.offsets[e],n=r+this.sizes[e];return this.children[0].slice(r,n)}},ge=class extends h{value(e){let r=this.offsets[e],n=r+this.sizes[e];return this.children[0].slice(A(r),A(n))}},ve=class extends h{constructor({stride:e,...r}){super(r),this.stride=e}},Ie=class extends ve{value(e){let{stride:r,values:n}=this;return n.subarray(e*r,(e+1)*r)}},xe=class extends ve{value(e){let{children:r,stride:n}=this;return r[0].slice(e*n,(e+1)*n)}};function rt({children:t,offsets:e},r){let[n,s]=t[0].children,o=e[r],a=e[r+1],c=[];for(let l=o;l<a;++l)c.push([n.at(l),s.at(l)]);return c}var be=class extends h{value(e){return rt(this,e)}},we=class extends h{value(e){return new Map(rt(this,e))}},W=class extends h{constructor({typeIds:e,map:r,...n}){super(n),this.typeIds=e,this.map=r}value(e){let{typeIds:r,children:n,map:s}=this;return n[s[r[e]]].at(e)}},Ae=class extends W{value(e){return super.value(this.offsets[e])}},Se=class extends h{constructor({names:e,...r}){super(r),this.names=e}value(e){let{children:r,names:n}=this,s=n.length,o={};for(let a=0;a<s;++a)o[n[a]]=r[a].at(e);return o}},De=class extends h{value(e){let[{values:r},n]=this.children;return n.at(k(r,e))}},Ee=class extends h{constructor({dictionary:e,...r}){super(r),this.cache=e.cache()}value(e){return this.cache[this.key(e)]}key(e){return this.values[e]}},Ne=class extends h{constructor({data:e,...r}){super(r),this.data=e}view(e){let{values:r,data:n}=this,s=e<<4,o=s+4,a=r,c=u(a,s);return c>12&&(o=u(a,s+12),a=n[u(a,s+8)]),a.subarray(o,o+c)}},Le=class extends Ne{value(e){return this.view(e)}},Me=class extends Ne{value(e){return G(this.view(e))}};function ze(t){let e=[];return{add(r){return e.push(r),this},clear:()=>e=[],done:()=>new ke(t,e)}}var ke=class{constructor(e,r){this.type=e,this.length=r.reduce((o,a)=>o+a.length,0),this.nullCount=r.reduce((o,a)=>o+a.nullCount,0),this.data=r;let n=r.length,s=new Int32Array(n+1);if(n===1){let[o]=r;s[1]=o.length,this.at=a=>o.at(a)}else for(let o=0,a=0;o<n;++o)s[o+1]=a+=r[o].length;this.offsets=s}get[Symbol.toStringTag](){return"Column"}[Symbol.iterator](){let e=this.data;return e.length===1?e[0][Symbol.iterator]():vt(e)}at(e){let{data:r,offsets:n}=this,s=k(n,e)-1;return r[s]?.at(e-n[s])}get(e){return this.at(e)}toArray(){let{length:e,nullCount:r,data:n}=this,s=!r&&Je(n[0]),o=n.length;if(s&&o===1)return n[0].values;let a=!o||r>0?Array:n[0].constructor.ArrayType??n[0].values.constructor,c=new a(e);return s?It(c,n):xt(c,n)}cache(){return this._cache??(this._cache=this.toArray())}};function*vt(t){for(let e=0;e<t.length;++e){let r=t[e][Symbol.iterator]();for(let n=r.next();!n.done;n=r.next())yield n.value}}function It(t,e){for(let r=0,n=0;r<e.length;++r){let{values:s}=e[r];t.set(s,n),n+=s.length}return t}function xt(t,e){let r=-1;for(let n=0;n<e.length;++n){let s=e[n];for(let o=0;o<s.length;++o)t[++r]=s.at(o)}return t}function He(t,e,r,n){switch(r){case i.NONE:case i.Null:case i.Bool:case i.BinaryView:case i.Utf8View:return{typeId:r};case i.Binary:case i.Utf8:return{typeId:r,offsets:M};case i.LargeBinary:case i.LargeUtf8:return{typeId:r,offsets:U};case i.List:case i.ListView:return{typeId:r,children:[n?.[0]],offsets:M};case i.LargeList:case i.LargeListView:return{typeId:r,children:[n?.[0]],offsets:U};case i.Struct:case i.RunEndEncoded:return{typeId:r,children:n};case i.Int:return Ye(t,e);case i.Float:return bt(t,e);case i.Decimal:return wt(t,e);case i.Date:return At(t,e);case i.Time:return St(t,e);case i.Timestamp:return Dt(t,e);case i.Interval:return Et(t,e);case i.Duration:return Nt(t,e);case i.FixedSizeBinary:return Lt(t,e);case i.FixedSizeList:return Mt(t,e,n);case i.Map:return Bt(t,e,n);case i.Union:return Tt(t,e,n)}throw new Error(`Unrecognized type: "${R(i,r)}" (id ${r})`)}function Pe(t,e){return{typeId:i.Int,bitWidth:t,signed:e,values:We(t,e)}}function Ye(t,e){let r=d(t,e);return Pe(r(4,u,0),r(6,F,!1))}function bt(t,e){let n=d(t,e)(4,x,O.HALF);return{typeId:i.Float,precision:n,values:n===O.HALF?Oe:n===O.SINGLE?je:J}}function wt(t,e){let r=d(t,e),n=r(8,u,128);return{typeId:i.Decimal,precision:r(4,u,0),scale:r(6,u,0),bitWidth:n,values:Ce}}function At(t,e){let n=d(t,e)(4,x,_.MILLISECOND);return{typeId:i.Date,unit:n,values:n===_.DAY?M:U}}function St(t,e){let r=d(t,e),n=r(6,u,32);return{typeId:i.Time,unit:r(4,x,L.MILLISECOND),bitWidth:n,values:n===32?M:U}}function Dt(t,e){let r=d(t,e);return{typeId:i.Timestamp,unit:r(4,x,L.SECOND),timezone:r(6,V),values:U}}function Et(t,e){let n=d(t,e)(4,x,C.YEAR_MONTH);return{typeId:i.Interval,unit:n,values:n===C.MONTH_DAY_NANO?void 0:M}}function Nt(t,e){let r=d(t,e);return{typeId:i.Duration,unit:r(4,x,L.MILLISECOND),values:U}}function Lt(t,e){let r=d(t,e);return{typeId:i.FixedSizeBinary,stride:r(4,u,0)}}function Mt(t,e,r){let n=d(t,e);return{typeId:i.FixedSizeList,stride:n(4,u,0),children:[r?.[0]??null]}}function Bt(t,e,r){let n=d(t,e);return{typeId:i.Map,keysSorted:n(4,F,!1),children:r,offsets:M}}function Tt(t,e,r){let n=d(t,e);return{typeId:i.Union,mode:n(4,x,$.Sparse),typeIds:b(t,n(6,D),4,u),children:r??[],offsets:M}}function X(t,e){let r=b(t,e,4,(n,s)=>{let o=d(n,s);return[o(4,V),o(6,V)]});return r.length?new Map(r):null}function Be(t,e,r){let n=new Map,s=d(t,e);return{version:r,endianness:s(4,x,0),fields:s(6,(o,a)=>Ut(o,a,n),[]),metadata:s(8,X),dictionaryTypes:n}}function Ut(t,e,r){return b(t,e,4,(n,s)=>nt(n,s,r))}function nt(t,e,r){let n=d(t,e),s=n(8,Z,i.NONE),o=n(10,D,0),a=n(12,Ot),c=n(14,(I,y)=>Ft(I,y,r)),l;if(a){let{id:I}=a,y=r.get(I);y||(y=He(t,o,s,c),r.set(I,y)),a.type=y,l=a}else l=He(t,o,s,c);return{name:n(4,V),type:l,nullable:n(6,F,!1),metadata:n(16,X)}}function Ft(t,e,r){let n=b(t,e,4,(s,o)=>nt(s,o,r));return n.length?n:null}function Ot(t,e){if(!e)return null;let r=d(t,e);return{type:null,typeId:i.Dictionary,id:r(4,v,0),keys:r(6,Ye,Pe(32,!0)),ordered:r(8,F,!1)}}function Te(t,e,r){let n=d(t,e);if(n(10,D,0))throw new Error("Record batch compression not implemented");let s=r<N.V4?8:0;return{length:n(4,v,0),nodes:b(t,n(6,D),16,(o,a)=>({length:v(o,a),nullCount:v(o,a+8)})),buffers:b(t,n(8,D),16+s,(o,a)=>({offset:v(o,a+s),length:v(o,a+s+8)})),variadic:b(t,n(12,D),8,v)}}function st(t,e,r){let n=d(t,e);return{id:n(4,v,0),data:n(6,(s,o)=>Te(s,o,r)),isDelta:n(8,F,!1)}}var Ct=(t,e)=>`Expected to read ${t} metadata bytes, but only read ${e}.`,Vt=(t,e)=>`Expected to read ${t} bytes for message body, but only read ${e}.`,_t=t=>`Unsupported message type: ${t} (${R(E,t)})`;function Ue(t,e){let r=u(t,e)||0;if(e+=4,r===-1&&(r=u(t,e)||0,e+=4),r===0)return null;let n=t.subarray(e,e+=r);if(n.byteLength<r)throw new Error(Ct(r,n.byteLength));let s=d(n,0),o=s(4,x,N.V1),a=s(6,Z,E.NONE),c=s(8,D,0),l=s(10,v,0),I;if(c){let y=a===E.Schema?Be:a===E.DictionaryBatch?st:a===E.RecordBatch?Te:null;if(!y)throw new Error(_t(a));if(I=y(n,c,o),l>0){let g=t.subarray(e,e+=l);if(g.byteLength<l)throw new Error(Vt(l,g.byteLength));I.body=g}}return{version:o,type:a,index:e,content:I}}function Rt(t,e){return{offset:v(t,e),metadataLength:u(t,e+8),bodyLength:v(t,e+16)}}function $e(t,e){return b(t,e,24,Rt)}function at(t){let e=t instanceof ArrayBuffer?new Uint8Array(t):t;return!Array.isArray(e)&&kt(e)?Ht(e):zt(e)}var it=Uint8Array.of(65,82,82,79,87,49);function kt(t){if(!t||t.length<4)return!1;for(let e=0;e<6;++e)if(it[e]!==t[e])return!1;return!0}function zt(t){let e=[t].flat(),r,n=[],s=[];for(let o of e){let a=0;for(;;){let c=Ue(o,a);if(c===null)break;if(a=c.index,!!c.content)switch(c.type){case E.Schema:r||(r=c.content);break;case E.RecordBatch:n.push(c.content);break;case E.DictionaryBatch:s.push(c.content);break}}}return{schema:r,dictionaries:s,records:n,metadata:null}}function Ht(t){let e=t.byteLength-(it.length+4),r=u(t,e),n=d(t,e-r),s=n(4,x,N.V1),o=n(8,$e,[]),a=n(10,$e,[]);return{schema:n(6,(c,l)=>Be(c,l,s)),dictionaries:o.map(({offset:c})=>Ue(t,c).content),records:a.map(({offset:c})=>Ue(t,c).content),metadata:n(12,X)}}var Fe=class t{constructor(e,r){this.schema=e,this.names=e.fields.map(n=>n.name),this.children=r}get[Symbol.toStringTag](){return"Table"}get numCols(){return this.names.length}get numRows(){return this.children[0]?.length??0}getChildAt(e){return this.children[e]}getChild(e){let r=this.names.findIndex(n=>n===e);return r>-1?this.children[r]:void 0}selectAt(e,r=[]){let{children:n,schema:s}=this,{fields:o}=s;return new t({...s,fields:e.map((a,c)=>Pt(o[a],r[c]))},e.map(a=>n[a]))}select(e,r){let n=this.names,s=e.map(o=>n.indexOf(o));return this.selectAt(s,r)}toColumns(){let{children:e,names:r}=this,n={};return r.forEach((s,o)=>n[s]=e[o]?.toArray()??[]),n}toArray(){let{children:e,numRows:r,names:n}=this,s=e[0]?.data??[],o=Array(r);for(let a=0,c=-1;a<s.length;++a)for(let l=0;l<s[a].length;++l)o[++c]=Ge(n,e,a,l);return o}*[Symbol.iterator](){let{children:e,names:r}=this,n=e[0]?.data??[];for(let s=0;s<n.length;++s)for(let o=0;o<n[s].length;++o)yield Ge(r,e,s,o)}at(e){let{names:r,children:n,numRows:s}=this;if(e<0||e>=s)return null;let[{offsets:o}]=n,a=k(o,e)-1;return Ge(r,n,a,e-o[a])}get(e){return this.at(e)}};function Pt(t,e){return e!=null&&e!==t.name?{...t,name:e}:t}function Ge(t,e,r,n){let s={};for(let o=0;o<t.length;++o)s[t[o]]=e[o].data[r].at(n);return s}function Yt(t,e){return $t(at(t),e)}function $t(t,e={}){let{schema:r={fields:[]},dictionaries:n,records:s}=t,{version:o,fields:a,dictionaryTypes:c}=r,l=new Map,I=Gt(e,o,l),y=new Map;for(let p of n){let{id:m,data:S,isDelta:w,body:q}=p,P=c.get(m),Y=Ze(P,I({...S,body:q}));if(y.has(m)){let f=y.get(m);w||f.clear(),f.add(Y)}else{if(w)throw new Error("Delta update can not be first dictionary batch.");y.set(m,ze(P).add(Y))}}y.forEach((p,m)=>l.set(m,p.done()));let g=a.map(p=>ze(p.type));for(let p of s){let m=I(p);a.forEach((S,w)=>g[w].add(Ze(S.type,m)))}return new Fe(r,g.map(p=>p.done()))}function Gt(t,e,r){let n={version:e,options:t,dictionary:s=>r.get(s)};return s=>{let{length:o,nodes:a,buffers:c,variadic:l,body:I}=s,y=-1,g=-1,p=-1;return{...n,length:o,node:()=>a[++y],buffer:m=>{let{length:S,offset:w}=c[++g];return m?new m(I.buffer,I.byteOffset+w,S/m.BYTES_PER_ELEMENT):I.subarray(w,w+S)},variadic:()=>l[++p],visitAll(m){return m.map(S=>Ze(S.type,this))}}}}function Ze(t,e){let{typeId:r,bitWidth:n,precision:s,scale:o,stride:a,unit:c}=t,{useBigInt:l,useDate:I,useMap:y}=e.options;if(r===i.Null){let{length:f}=e;return new K({length:f,nullCount:f})}let g=e.node(),p=(f,T)=>new f({...g,...T,validity:e.buffer(),values:e.buffer(t.values)}),m=f=>new f({...g,validity:e.buffer(),offsets:e.buffer(t.offsets),values:e.buffer()}),S=f=>new f({...g,validity:e.buffer(),values:e.buffer(),data:Array.from({length:e.variadic()},()=>e.buffer())}),w=f=>new f({...g,validity:e.buffer(),offsets:e.buffer(t.offsets),children:e.visitAll(t.children)}),q=f=>new f({...g,validity:e.buffer(),offsets:e.buffer(t.offsets),sizes:e.buffer(t.offsets),children:e.visitAll(t.children)}),P=(f,T)=>new f({...g,...T,validity:e.buffer(),children:e.visitAll(t.children)}),Y=I?f=>new re(p(f)):p;switch(r){case i.Bool:return p(ee);case i.Int:case i.Time:case i.Duration:return p(n===64&&!l?B:z);case i.Float:return p(s===O.HALF?Q:z);case i.Date:return Y(c===_.DAY?ne:Ke);case i.Timestamp:return Y(c===L.SECOND?se:c===L.MILLISECOND?Qe:c===L.MICROSECOND?oe:ae);case i.Decimal:return p(te,{bitWidth:n,scale:o});case i.Interval:return p(c===C.DAY_TIME?ie:c===C.YEAR_MONTH?ce:le);case i.FixedSizeBinary:return p(Ie,{stride:a});case i.Utf8:return m(fe);case i.LargeUtf8:return m(he);case i.Binary:return m(ue);case i.LargeBinary:return m(de);case i.BinaryView:return S(Le);case i.Utf8View:return S(Me);case i.List:return w(pe);case i.LargeList:return w(me);case i.Map:return w(y?we:be);case i.ListView:return q(ye);case i.LargeListView:return q(ge);case i.FixedSizeList:return P(xe,{stride:a});case i.Struct:return P(Se,{names:t.children.map(f=>f.name)});case i.RunEndEncoded:return new De({...g,children:e.visitAll(t.children)});case i.Dictionary:{let{id:f,keys:T}=t;return new Ee({...g,validity:e.buffer(),values:e.buffer(T.values),dictionary:e.dictionary(f)})}case i.Union:{e.version<N.V5&&e.buffer();let f=t.mode===$.Sparse;return new(f?W:Ae)({...g,map:t.typeIds.reduce((T,ct,lt)=>(T[ct]=lt,T),{}),typeIds:e.buffer(Ve),offsets:f?null:e.buffer(t.offsets),children:e.visitAll(t.children)})}default:throw new Error(`Unsupported type: ${r} ${R(i,r)}`)}}export{_ as DateUnit,ut as Endianness,C as IntervalUnit,O as Precision,L as TimeUnit,i as Type,$ as UnionMode,N as Version,Yt as tableFromIPC}; |
@@ -29,5 +29,6 @@ /** | ||
* @param {import('./types.js').OffsetArray} [options.offsets] Offsets buffer | ||
* @param {import('./types.js').OffsetArray} [options.sizes] Sizes buffer | ||
* @param {Batch[]} [options.children] Children batches | ||
*/ | ||
constructor({ length, nullCount, validity, values, offsets, children }: { | ||
constructor({ length, nullCount, validity, values, offsets, sizes, children }: { | ||
length: number; | ||
@@ -38,2 +39,3 @@ nullCount: number; | ||
offsets?: import("./types.js").OffsetArray; | ||
sizes?: import("./types.js").OffsetArray; | ||
children?: Batch<any>[]; | ||
@@ -46,2 +48,3 @@ }); | ||
offsets: import("./types.js").OffsetArray; | ||
sizes: import("./types.js").OffsetArray; | ||
children: Batch<any>[]; | ||
@@ -122,5 +125,6 @@ /** | ||
* @param {import('./types.js').OffsetArray} [options.offsets] Offsets buffer | ||
* @param {import('./types.js').OffsetArray} [options.sizes] Sizes buffer | ||
* @param {Batch[]} [options.children] Children batches | ||
*/ | ||
constructor({ length, nullCount, validity, values, offsets, children }: { | ||
constructor({ length, nullCount, validity, values, offsets, sizes, children }: { | ||
length: number; | ||
@@ -131,2 +135,3 @@ nullCount: number; | ||
offsets?: import("./types.js").OffsetArray; | ||
sizes?: import("./types.js").OffsetArray; | ||
children?: Batch<any>[]; | ||
@@ -156,5 +161,6 @@ }); | ||
* @param {import('./types.js').OffsetArray} [options.offsets] Offsets buffer | ||
* @param {import('./types.js').OffsetArray} [options.sizes] Sizes buffer | ||
* @param {Batch[]} [options.children] Children batches | ||
*/ | ||
constructor({ length, nullCount, validity, values, offsets, children }: { | ||
constructor({ length, nullCount, validity, values, offsets, sizes, children }: { | ||
length: number; | ||
@@ -165,2 +171,3 @@ nullCount: number; | ||
offsets?: import("./types.js").OffsetArray; | ||
sizes?: import("./types.js").OffsetArray; | ||
children?: Batch<any>[]; | ||
@@ -194,5 +201,6 @@ }); | ||
* @param {import('./types.js').OffsetArray} [options.offsets] Offsets buffer | ||
* @param {import('./types.js').OffsetArray} [options.sizes] Sizes buffer | ||
* @param {Batch[]} [options.children] Children batches | ||
*/ | ||
constructor({ length, nullCount, validity, values, offsets, children }: { | ||
constructor({ length, nullCount, validity, values, offsets, sizes, children }: { | ||
length: number; | ||
@@ -203,2 +211,3 @@ nullCount: number; | ||
offsets?: import("./types.js").OffsetArray; | ||
sizes?: import("./types.js").OffsetArray; | ||
children?: Batch<any>[]; | ||
@@ -290,5 +299,6 @@ }); | ||
* @param {import('./types.js').OffsetArray} [options.offsets] Offsets buffer | ||
* @param {import('./types.js').OffsetArray} [options.sizes] Sizes buffer | ||
* @param {Batch[]} [options.children] Children batches | ||
*/ | ||
constructor({ length, nullCount, validity, values, offsets, children }: { | ||
constructor({ length, nullCount, validity, values, offsets, sizes, children }: { | ||
length: number; | ||
@@ -299,2 +309,3 @@ nullCount: number; | ||
offsets?: import("./types.js").OffsetArray; | ||
sizes?: import("./types.js").OffsetArray; | ||
children?: Batch<any>[]; | ||
@@ -316,5 +327,6 @@ }); | ||
* @param {import('./types.js').OffsetArray} [options.offsets] Offsets buffer | ||
* @param {import('./types.js').OffsetArray} [options.sizes] Sizes buffer | ||
* @param {Batch[]} [options.children] Children batches | ||
*/ | ||
constructor({ length, nullCount, validity, values, offsets, children }: { | ||
constructor({ length, nullCount, validity, values, offsets, sizes, children }: { | ||
length: number; | ||
@@ -325,2 +337,3 @@ nullCount: number; | ||
offsets?: import("./types.js").OffsetArray; | ||
sizes?: import("./types.js").OffsetArray; | ||
children?: Batch<any>[]; | ||
@@ -342,5 +355,6 @@ }); | ||
* @param {import('./types.js').OffsetArray} [options.offsets] Offsets buffer | ||
* @param {import('./types.js').OffsetArray} [options.sizes] Sizes buffer | ||
* @param {Batch[]} [options.children] Children batches | ||
*/ | ||
constructor({ length, nullCount, validity, values, offsets, children }: { | ||
constructor({ length, nullCount, validity, values, offsets, sizes, children }: { | ||
length: number; | ||
@@ -351,2 +365,3 @@ nullCount: number; | ||
offsets?: import("./types.js").OffsetArray; | ||
sizes?: import("./types.js").OffsetArray; | ||
children?: Batch<any>[]; | ||
@@ -369,5 +384,6 @@ }); | ||
* @param {import('./types.js').OffsetArray} [options.offsets] Offsets buffer | ||
* @param {import('./types.js').OffsetArray} [options.sizes] Sizes buffer | ||
* @param {Batch[]} [options.children] Children batches | ||
*/ | ||
constructor({ length, nullCount, validity, values, offsets, children }: { | ||
constructor({ length, nullCount, validity, values, offsets, sizes, children }: { | ||
length: number; | ||
@@ -378,2 +394,3 @@ nullCount: number; | ||
offsets?: import("./types.js").OffsetArray; | ||
sizes?: import("./types.js").OffsetArray; | ||
children?: Batch<any>[]; | ||
@@ -397,5 +414,6 @@ }); | ||
* @param {import('./types.js').OffsetArray} [options.offsets] Offsets buffer | ||
* @param {import('./types.js').OffsetArray} [options.sizes] Sizes buffer | ||
* @param {Batch[]} [options.children] Children batches | ||
*/ | ||
constructor({ length, nullCount, validity, values, offsets, children }: { | ||
constructor({ length, nullCount, validity, values, offsets, sizes, children }: { | ||
length: number; | ||
@@ -406,2 +424,3 @@ nullCount: number; | ||
offsets?: import("./types.js").OffsetArray; | ||
sizes?: import("./types.js").OffsetArray; | ||
children?: Batch<any>[]; | ||
@@ -423,5 +442,6 @@ }); | ||
* @param {import('./types.js').OffsetArray} [options.offsets] Offsets buffer | ||
* @param {import('./types.js').OffsetArray} [options.sizes] Sizes buffer | ||
* @param {Batch[]} [options.children] Children batches | ||
*/ | ||
constructor({ length, nullCount, validity, values, offsets, children }: { | ||
constructor({ length, nullCount, validity, values, offsets, sizes, children }: { | ||
length: number; | ||
@@ -432,2 +452,3 @@ nullCount: number; | ||
offsets?: import("./types.js").OffsetArray; | ||
sizes?: import("./types.js").OffsetArray; | ||
children?: Batch<any>[]; | ||
@@ -450,5 +471,6 @@ }); | ||
* @param {import('./types.js').OffsetArray} [options.offsets] Offsets buffer | ||
* @param {import('./types.js').OffsetArray} [options.sizes] Sizes buffer | ||
* @param {Batch[]} [options.children] Children batches | ||
*/ | ||
constructor({ length, nullCount, validity, values, offsets, children }: { | ||
constructor({ length, nullCount, validity, values, offsets, sizes, children }: { | ||
length: number; | ||
@@ -459,2 +481,3 @@ nullCount: number; | ||
offsets?: import("./types.js").OffsetArray; | ||
sizes?: import("./types.js").OffsetArray; | ||
children?: Batch<any>[]; | ||
@@ -481,2 +504,19 @@ }); | ||
/** | ||
* A batch of list (array) values of variable length. The list offsets and | ||
* sizes are 32-bit ints. | ||
* @template V | ||
* @extends {ArrayBatch<import('./types.js').ValueArray<V>>} | ||
*/ | ||
export class ListViewBatch<V> extends ArrayBatch<import("./types.js").ValueArray<V>> { | ||
} | ||
/** | ||
* A batch of list (array) values of variable length. The list offsets and | ||
* sizes are 64-bit ints. Value extraction will fail if an offset or size | ||
* exceeds `Number.MAX_SAFE_INTEGER`. | ||
* @template V | ||
* @extends {ArrayBatch<import('./types.js').ValueArray<V>>} | ||
*/ | ||
export class LargeListViewBatch<V> extends ArrayBatch<import("./types.js").ValueArray<V>> { | ||
} | ||
/** | ||
* A batch of binary blobs of fixed size, returned as byte buffers of unsigned | ||
@@ -528,5 +568,6 @@ * 8-bit integers. | ||
* @param {import('./types.js').OffsetArray} [options.offsets] Offsets buffer | ||
* @param {import('./types.js').OffsetArray} [options.sizes] Sizes buffer | ||
* @param {Batch[]} [options.children] Children batches | ||
*/ | ||
constructor({ length, nullCount, validity, values, offsets, children }: { | ||
constructor({ length, nullCount, validity, values, offsets, sizes, children }: { | ||
length: number; | ||
@@ -537,2 +578,3 @@ nullCount: number; | ||
offsets?: import("./types.js").OffsetArray; | ||
sizes?: import("./types.js").OffsetArray; | ||
children?: Batch<any>[]; | ||
@@ -556,5 +598,6 @@ }); | ||
* @param {import('./types.js').OffsetArray} [options.offsets] Offsets buffer | ||
* @param {import('./types.js').OffsetArray} [options.sizes] Sizes buffer | ||
* @param {Batch[]} [options.children] Children batches | ||
*/ | ||
constructor({ length, nullCount, validity, values, offsets, children }: { | ||
constructor({ length, nullCount, validity, values, offsets, sizes, children }: { | ||
length: number; | ||
@@ -565,2 +608,3 @@ nullCount: number; | ||
offsets?: import("./types.js").OffsetArray; | ||
sizes?: import("./types.js").OffsetArray; | ||
children?: Batch<any>[]; | ||
@@ -639,2 +683,13 @@ }); | ||
/** | ||
* A batch of run-end-encoded values. | ||
* @template T | ||
* @extends {ArrayBatch<T>} | ||
*/ | ||
export class RunEndEncodedBatch<T> extends ArrayBatch<T> { | ||
/** | ||
* @param {number} index The value index. | ||
*/ | ||
value(index: number): any; | ||
} | ||
/** | ||
* A batch of dictionary-encoded values. | ||
@@ -670,2 +725,47 @@ * @template T | ||
/** | ||
* A batch of binary blobs from variable data buffers, returned as byte | ||
* buffers of unsigned 8-bit integers. | ||
* @extends {ViewBatch<Uint8Array>} | ||
*/ | ||
export class BinaryViewBatch extends ViewBatch<Uint8Array> { | ||
/** | ||
* Create a new view batch. | ||
* @param {object} options Batch options. | ||
* @param {number} options.length The length of the batch | ||
* @param {number} options.nullCount The null value count | ||
* @param {Uint8Array} [options.validity] Validity bitmap buffer | ||
* @param {Uint8Array} options.values Values buffer | ||
* @param {Uint8Array[]} options.data View data buffers | ||
*/ | ||
constructor({ data, ...rest }: { | ||
length: number; | ||
nullCount: number; | ||
validity?: Uint8Array; | ||
values: Uint8Array; | ||
data: Uint8Array[]; | ||
}); | ||
} | ||
/** | ||
* A batch of UTF-8 strings from variable data buffers. | ||
* @extends {ViewBatch<string>} | ||
*/ | ||
export class Utf8ViewBatch extends ViewBatch<string> { | ||
/** | ||
* Create a new view batch. | ||
* @param {object} options Batch options. | ||
* @param {number} options.length The length of the batch | ||
* @param {number} options.nullCount The null value count | ||
* @param {Uint8Array} [options.validity] Validity bitmap buffer | ||
* @param {Uint8Array} options.values Values buffer | ||
* @param {Uint8Array[]} options.data View data buffers | ||
*/ | ||
constructor({ data, ...rest }: { | ||
length: number; | ||
nullCount: number; | ||
validity?: Uint8Array; | ||
values: Uint8Array; | ||
data: Uint8Array[]; | ||
}); | ||
} | ||
/** | ||
* A batch with a fixed stride. | ||
@@ -697,2 +797,31 @@ * @template T | ||
} | ||
/** | ||
* @template T | ||
* @extends {ArrayBatch<T>} | ||
*/ | ||
declare class ViewBatch<T> extends ArrayBatch<T> { | ||
/** | ||
* Create a new view batch. | ||
* @param {object} options Batch options. | ||
* @param {number} options.length The length of the batch | ||
* @param {number} options.nullCount The null value count | ||
* @param {Uint8Array} [options.validity] Validity bitmap buffer | ||
* @param {Uint8Array} options.values Values buffer | ||
* @param {Uint8Array[]} options.data View data buffers | ||
*/ | ||
constructor({ data, ...rest }: { | ||
length: number; | ||
nullCount: number; | ||
validity?: Uint8Array; | ||
values: Uint8Array; | ||
data: Uint8Array[]; | ||
}); | ||
data: Uint8Array[]; | ||
/** | ||
* Get the binary data at the provided index. | ||
* @param {number} index The value index. | ||
* @returns {Uint8Array} | ||
*/ | ||
view(index: number): Uint8Array; | ||
} | ||
export {}; |
@@ -149,3 +149,3 @@ export { tableFromIPC } from "./table-from-ipc.js"; | ||
mode: UnionMode_; | ||
typeIds: Int32Array; | ||
typeIds: number[]; | ||
children: Field[]; | ||
@@ -194,6 +194,31 @@ offsets: Int32ArrayConstructor; | ||
}; | ||
/** RunEndEncoded data type. */ | ||
export type RunEndEncodedType = { | ||
typeId: 22; | ||
children: [Field, Field]; | ||
}; | ||
/** Opaque binary data type with multi-buffer view layout. */ | ||
export type BinaryViewType = { | ||
typeId: 23; | ||
}; | ||
/** UTF-8 encoded string data type with multi-buffer view layout. */ | ||
export type Utf8ViewType = { | ||
typeId: 24; | ||
}; | ||
/** ListView data type. */ | ||
export type ListViewType = { | ||
typeId: 25; | ||
children: [Field]; | ||
offsets: Int32ArrayConstructor; | ||
}; | ||
/** ListView data type with 64-bit integer offsets for larger data. */ | ||
export type LargeListViewType = { | ||
typeId: 26; | ||
children: [Field]; | ||
offsets: BigInt64ArrayConstructor; | ||
}; | ||
/** | ||
* Arrow field data types. | ||
*/ | ||
export type DataType = NoneType | NullType | IntType | FloatType | BinaryType | Utf8Type | BoolType | DecimalType | DateType | TimeType | TimestampType | IntervalType | ListType | StructType | UnionType | FixedSizeBinaryType | FixedSizeListType | MapType | DurationType | LargeBinaryType | LargeUtf8Type | LargeListType | DictionaryType; | ||
export type DataType = NoneType | NullType | IntType | FloatType | BinaryType | Utf8Type | BoolType | DecimalType | DateType | TimeType | TimestampType | IntervalType | ListType | StructType | UnionType | FixedSizeBinaryType | FixedSizeListType | MapType | DurationType | LargeBinaryType | LargeUtf8Type | LargeListType | RunEndEncodedType | BinaryViewType | Utf8ViewType | ListViewType | LargeListViewType | DictionaryType; | ||
/** | ||
@@ -212,2 +237,3 @@ * Arrow IPC record batch message. | ||
}[]; | ||
variadic: number[]; | ||
body?: Uint8Array; | ||
@@ -214,0 +240,0 @@ } |
@@ -147,3 +147,3 @@ import { Version, Endianness, MessageHeader, Precision, DateUnit, TimeUnit, IntervalUnit, UnionMode } from './constants.js'; | ||
mode: UnionMode_; | ||
typeIds: Int32Array; | ||
typeIds: number[]; | ||
children: Field[]; | ||
@@ -192,6 +192,31 @@ offsets: Int32ArrayConstructor; | ||
}; | ||
/** RunEndEncoded data type. */ | ||
export type RunEndEncodedType = { | ||
typeId: 22; | ||
children: [Field, Field]; | ||
}; | ||
/** Opaque binary data type with multi-buffer view layout. */ | ||
export type BinaryViewType = { | ||
typeId: 23; | ||
}; | ||
/** UTF-8 encoded string data type with multi-buffer view layout. */ | ||
export type Utf8ViewType = { | ||
typeId: 24; | ||
}; | ||
/** ListView data type. */ | ||
export type ListViewType = { | ||
typeId: 25; | ||
children: [Field]; | ||
offsets: Int32ArrayConstructor; | ||
}; | ||
/** ListView data type with 64-bit integer offsets for larger data. */ | ||
export type LargeListViewType = { | ||
typeId: 26; | ||
children: [Field]; | ||
offsets: BigInt64ArrayConstructor; | ||
}; | ||
/** | ||
* Arrow field data types. | ||
*/ | ||
export type DataType = NoneType | NullType | IntType | FloatType | BinaryType | Utf8Type | BoolType | DecimalType | DateType | TimeType | TimestampType | IntervalType | ListType | StructType | UnionType | FixedSizeBinaryType | FixedSizeListType | MapType | DurationType | LargeBinaryType | LargeUtf8Type | LargeListType | DictionaryType; | ||
export type DataType = NoneType | NullType | IntType | FloatType | BinaryType | Utf8Type | BoolType | DecimalType | DateType | TimeType | TimestampType | IntervalType | ListType | StructType | UnionType | FixedSizeBinaryType | FixedSizeListType | MapType | DurationType | LargeBinaryType | LargeUtf8Type | LargeListType | RunEndEncodedType | BinaryViewType | Utf8ViewType | ListViewType | LargeListViewType | DictionaryType; | ||
/** | ||
@@ -210,2 +235,3 @@ * Arrow IPC record batch message. | ||
}[]; | ||
variadic: number[]; | ||
body?: Uint8Array; | ||
@@ -212,0 +238,0 @@ } |
@@ -37,7 +37,8 @@ /** | ||
* Determine the correct index into an offset array for a given | ||
* full column row index. | ||
* @param {Int32Array} offsets The offsets array. | ||
* full column row index. Assumes offset indices can be manipulated | ||
* as 32-bit signed integers. | ||
* @param {import("./types.js").IntegerArray} offsets The offsets array. | ||
* @param {number} index The full column row index. | ||
*/ | ||
export function bisectOffsets(offsets: Int32Array, index: number): number; | ||
export function bisect(offsets: import("./types.js").IntegerArray, index: number): number; | ||
/** | ||
@@ -129,11 +130,11 @@ * Lookup helper for flatbuffer table entries. | ||
/** | ||
* Return the length and start of a vector with the given offset. | ||
* Extract a flatbuffer vector to an array. | ||
* @template T | ||
* @param {Uint8Array} buf The byte buffer. | ||
* @param {number} offset The offset location of the vector. | ||
* @returns {{length: number, base: number}} The vector length and base. | ||
* @param {number} stride The stride between vector entries. | ||
* @param {(buf: Uint8Array, pos: number) => T} extract Vector entry extraction function. | ||
* @returns {T[]} The extracted vector entries. | ||
*/ | ||
export function readVector(buf: Uint8Array, offset: number): { | ||
length: number; | ||
base: number; | ||
}; | ||
export function readVector<T>(buf: Uint8Array, offset: number, stride: number, extract: (buf: Uint8Array, pos: number) => T): T[]; | ||
export const SIZEOF_INT: 4; |
{ | ||
"name": "@uwdata/flechette", | ||
"version": "0.0.7", | ||
"version": "0.0.8", | ||
"description": "Fast, lightweight access to Apache Arrow data.", | ||
@@ -37,3 +37,3 @@ "keywords": [ | ||
"esbuild": "^0.23.1", | ||
"eslint": "^9.9.0", | ||
"eslint": "^9.9.1", | ||
"mocha": "^10.7.3", | ||
@@ -40,0 +40,0 @@ "rimraf": "^6.0.1", |
@@ -13,5 +13,5 @@ # Flechette | ||
* _Size_. Flechette is ~16k minified (~6k gzip'd), versus 163k minified (~43k gzip'd) for Arrow JS. | ||
* _Size_. Flechette is ~17k minified (~6k gzip'd), versus 163k minified (~43k gzip'd) for Arrow JS. | ||
* _Coverage_. Flechette supports multiple data types unsupported by the reference implementation at the time of writing, including decimal-to-number conversion and support for month/day/nanosecond time intervals (as used, for example, by DuckDB). | ||
* _Coverage_. Flechette supports data types unsupported by the reference implementation at the time of writing, including decimal-to-number conversion, month/day/nanosecond time intervals (as used by DuckDB, for example), list views, and run-end encoded data. | ||
@@ -18,0 +18,0 @@ * _Flexibility_. Flechette includes options to control data value conversion, such as numerical timestamps vs. Date objects for temporal data, and numbers vs. bigint values for 64-bit integer data. |
125
src/batch.js
import { float64 } from './array-types.js'; | ||
import { decodeBit, decodeUtf8, divide, readInt32, readInt64AsNum, toNumber } from './util.js'; | ||
import { bisect, decodeBit, decodeUtf8, divide, readInt32, readInt64AsNum, toNumber } from './util.js'; | ||
@@ -36,2 +36,3 @@ /** | ||
* @param {import('./types.js').OffsetArray} [options.offsets] Offsets buffer | ||
* @param {import('./types.js').OffsetArray} [options.sizes] Sizes buffer | ||
* @param {Batch[]} [options.children] Children batches | ||
@@ -45,2 +46,3 @@ */ | ||
offsets, | ||
sizes, | ||
children | ||
@@ -53,2 +55,3 @@ }) { | ||
this.offsets = offsets; | ||
this.sizes = sizes; | ||
this.children = children; | ||
@@ -539,2 +542,39 @@ | ||
/** | ||
* A batch of list (array) values of variable length. The list offsets and | ||
* sizes are 32-bit ints. | ||
* @template V | ||
* @extends {ArrayBatch<import('./types.js').ValueArray<V>>} | ||
*/ | ||
export class ListViewBatch extends ArrayBatch { | ||
/** | ||
* @param {number} index | ||
* @returns {import('./types.js').ValueArray<V>} | ||
*/ | ||
value(index) { | ||
const a = /** @type {number} */ (this.offsets[index]); | ||
const b = a + /** @type {number} */ (this.sizes[index]); | ||
return this.children[0].slice(a, b); | ||
} | ||
} | ||
/** | ||
* A batch of list (array) values of variable length. The list offsets and | ||
* sizes are 64-bit ints. Value extraction will fail if an offset or size | ||
* exceeds `Number.MAX_SAFE_INTEGER`. | ||
* @template V | ||
* @extends {ArrayBatch<import('./types.js').ValueArray<V>>} | ||
*/ | ||
export class LargeListViewBatch extends ArrayBatch { | ||
/** | ||
* @param {number} index | ||
* @returns {import('./types.js').ValueArray<V>} | ||
*/ | ||
value(index) { | ||
const a = /** @type {bigint} */ (this.offsets[index]); | ||
const b = a + /** @type {bigint} */ (this.sizes[index]); | ||
return this.children[0].slice(toNumber(a), toNumber(b)); | ||
} | ||
} | ||
/** | ||
* A batch with a fixed stride. | ||
@@ -730,2 +770,19 @@ * @template T | ||
/** | ||
* A batch of run-end-encoded values. | ||
* @template T | ||
* @extends {ArrayBatch<T>} | ||
*/ | ||
export class RunEndEncodedBatch extends ArrayBatch { | ||
/** | ||
* @param {number} index The value index. | ||
*/ | ||
value(index) { | ||
const [ { values: runs }, vals ] = this.children; | ||
return vals.at( | ||
bisect(/** @type {import('./types.js').IntegerArray} */(runs), index) | ||
); | ||
} | ||
} | ||
/** | ||
* A batch of dictionary-encoded values. | ||
@@ -766,1 +823,67 @@ * @template T | ||
} | ||
/** | ||
* @template T | ||
* @extends {ArrayBatch<T>} | ||
*/ | ||
class ViewBatch extends ArrayBatch { | ||
/** | ||
* Create a new view batch. | ||
* @param {object} options Batch options. | ||
* @param {number} options.length The length of the batch | ||
* @param {number} options.nullCount The null value count | ||
* @param {Uint8Array} [options.validity] Validity bitmap buffer | ||
* @param {Uint8Array} options.values Values buffer | ||
* @param {Uint8Array[]} options.data View data buffers | ||
*/ | ||
constructor({ data, ...rest }) { | ||
super(rest); | ||
this.data = data; | ||
} | ||
/** | ||
* Get the binary data at the provided index. | ||
* @param {number} index The value index. | ||
* @returns {Uint8Array} | ||
*/ | ||
view(index) { | ||
const { values, data } = this; | ||
const offset = index << 4; // each entry is 16 bytes | ||
let start = offset + 4; | ||
let buf = /** @type {Uint8Array} */ (values); | ||
const length = readInt32(buf, offset); | ||
if (length > 12) { | ||
// longer strings are in a data buffer | ||
start = readInt32(buf, offset + 12); | ||
buf = data[readInt32(buf, offset + 8)]; | ||
} | ||
return buf.subarray(start, start + length); | ||
} | ||
} | ||
/** | ||
* A batch of binary blobs from variable data buffers, returned as byte | ||
* buffers of unsigned 8-bit integers. | ||
* @extends {ViewBatch<Uint8Array>} | ||
*/ | ||
export class BinaryViewBatch extends ViewBatch { | ||
/** | ||
* @param {number} index The value index. | ||
*/ | ||
value(index) { | ||
return this.view(index); | ||
} | ||
} | ||
/** | ||
* A batch of UTF-8 strings from variable data buffers. | ||
* @extends {ViewBatch<string>} | ||
*/ | ||
export class Utf8ViewBatch extends ViewBatch { | ||
/** | ||
* @param {number} index The value index. | ||
*/ | ||
value(index) { | ||
return decodeUtf8(this.view(index)); | ||
} | ||
} |
import { isDirectBatch } from './batch.js'; | ||
import { bisectOffsets } from './util.js'; | ||
import { bisect } from './util.js'; | ||
@@ -110,3 +110,3 @@ /** | ||
const { data, offsets } = this; | ||
const i = bisectOffsets(offsets, index); | ||
const i = bisect(offsets, index) - 1; | ||
return data[i]?.at(index - offsets[i]); // undefined if out of range | ||
@@ -113,0 +113,0 @@ } |
@@ -247,4 +247,2 @@ /** | ||
* array ends. Like list/struct types, the value array can be of any type. | ||
* | ||
* Not currently supported by Flechette. | ||
*/ | ||
@@ -260,4 +258,2 @@ RunEndEncoded: 22, | ||
* must have a corresponding entry in `variadicBufferCounts`. | ||
* | ||
* Not currently supported by Flechette. | ||
*/ | ||
@@ -273,4 +269,2 @@ BinaryView: 23, | ||
* must have a corresponding entry in `variadicBufferCounts`. | ||
* | ||
* Not currently supported by Flechette. | ||
*/ | ||
@@ -282,4 +276,2 @@ Utf8View: 24, | ||
* list values. | ||
* | ||
* Not currently supported by Flechette. | ||
*/ | ||
@@ -290,4 +282,2 @@ ListView: 25, | ||
* extremely large data values. | ||
* | ||
* Not currently supported by Flechette. | ||
*/ | ||
@@ -294,0 +284,0 @@ LargeListView: 26 |
@@ -27,8 +27,3 @@ import { readInt32, readInt64AsNum, readVector } from '../util.js'; | ||
export function decodeBlocks(buf, index) { | ||
const { length, base } = readVector(buf, index); | ||
const batches = []; | ||
for (let i = 0; i < length; ++i) { | ||
batches.push(decodeBlock(buf, base + i * 24)); | ||
} | ||
return batches; | ||
return readVector(buf, index, 24, decodeBlock); | ||
} |
@@ -18,2 +18,4 @@ import { arrayTypeInt, float32, float64, int32, int64, uint16, uint32 } from '../array-types.js'; | ||
case Type.Bool: | ||
case Type.BinaryView: | ||
case Type.Utf8View: | ||
return { typeId }; | ||
@@ -27,6 +29,10 @@ case Type.Binary: | ||
case Type.List: | ||
return { typeId, children: [children?.[0] ?? null], offsets: int32 }; | ||
case Type.ListView: | ||
return { typeId, children: [children?.[0]], offsets: int32 }; | ||
case Type.LargeList: | ||
return { typeId, children: [children?.[0] ?? null], offsets: int64 }; | ||
case Type.LargeListView: | ||
return { typeId, children: [children?.[0]], offsets: int64 }; | ||
case Type.Struct: | ||
case Type.RunEndEncoded: | ||
// @ts-ignore - suppress children length warning for run-end encoded | ||
return { typeId, children }; | ||
@@ -58,3 +64,2 @@ case Type.Int: | ||
} | ||
// TODO: collect errors, skip failures? | ||
throw new Error(`Unrecognized type: "${keyFor(Type, typeId)}" (id ${typeId})`); | ||
@@ -286,8 +291,6 @@ } | ||
const get = table(buf, index); | ||
const { length, base } = readVector(buf, get(6, readOffset)); | ||
return { | ||
typeId: Type.Union, | ||
mode: /** @type {typeof UnionMode[keyof UnionMode]} */ | ||
(get(4, readInt16, UnionMode.Sparse)), | ||
typeIds: new int32(buf.buffer, buf.byteOffset + base, length), | ||
mode: /** @type {typeof UnionMode[keyof UnionMode]} */ (get(4, readInt16, UnionMode.Sparse)), | ||
typeIds: readVector(buf, get(6, readOffset), 4, readInt32), | ||
children: children ?? [], | ||
@@ -294,0 +297,0 @@ offsets: int32 |
@@ -10,13 +10,10 @@ import { readString, readVector, table } from '../util.js'; | ||
export function decodeMetadata(buf, index) { | ||
const { length, base } = readVector(buf, index); | ||
const metadata = length > 0 ? new Map : null; | ||
for (let i = 0; i < length; ++i) { | ||
// 4: key (string) | ||
// 6: key (string) | ||
const get = table(buf, base + i * 4); | ||
const key = get(4, readString); | ||
const val = get(6, readString); | ||
if (key || val) metadata.set(key, val); | ||
} | ||
return metadata?.size ? metadata : null; | ||
const entries = readVector(buf, index, 4, (buf, pos) => { | ||
const get = table(buf, pos); | ||
return /** @type {[string, string]} */ ([ | ||
get(4, readString), // 4: key (string) | ||
get(6, readString) // 6: key (string) | ||
]); | ||
}); | ||
return entries.length ? new Map(entries) : null; | ||
} |
@@ -16,3 +16,3 @@ import { Version } from '../constants.js'; | ||
// 10: compression (not supported) | ||
// 12: variadicBuffers (for view types, not supported) | ||
// 12: variadicBuffers (buffer counts for view-typed fields) | ||
const get = table(buf, index); | ||
@@ -23,38 +23,18 @@ if (get(10, readOffset, 0)) { | ||
// field nodes | ||
const nodes = []; | ||
const nodeVector = get(6, readVector); | ||
if (nodeVector) { | ||
const { length, base } = nodeVector; | ||
for (let i = 0; i < length; ++i) { | ||
const pos = base + i * 16; | ||
nodes.push({ | ||
length: readInt64AsNum(buf, pos), | ||
nullCount: readInt64AsNum(buf, pos + 8) | ||
}); | ||
} | ||
} | ||
// If an Arrow buffer was written before version 4, | ||
// advance 8 bytes to skip the now-removed page_id field | ||
const offset = version < Version.V4 ? 8 : 0; | ||
// buffers | ||
const buffers = []; | ||
const bufferVector = get(8, readVector); | ||
if (bufferVector) { | ||
const { length, base } = bufferVector; | ||
const adjust = version < Version.V4; | ||
for (let i = 0; i < length; ++i) { | ||
// If this Arrow buffer was written before version 4, | ||
// advance 8 bytes to skip the now-removed page_id field | ||
const pos = base + i * 16 + (adjust ? (8 * (i + 1)) : 0); | ||
buffers.push({ | ||
offset: readInt64AsNum(buf, pos), | ||
length: readInt64AsNum(buf, pos + 8) | ||
}); | ||
} | ||
} | ||
return { | ||
length: get(4, readInt64AsNum, 0), | ||
nodes, | ||
buffers | ||
nodes: readVector(buf, get(6, readOffset), 16, (buf, pos) => ({ | ||
length: readInt64AsNum(buf, pos), | ||
nullCount: readInt64AsNum(buf, pos + 8) | ||
})), | ||
buffers: readVector(buf, get(8, readOffset), 16 + offset, (buf, pos) => ({ | ||
offset: readInt64AsNum(buf, pos + offset), | ||
length: readInt64AsNum(buf, pos + offset + 8) | ||
})), | ||
variadic: readVector(buf, get(12, readOffset), 8, readInt64AsNum) | ||
}; | ||
} |
@@ -22,4 +22,3 @@ import { Type } from '../constants.js'; | ||
version, | ||
endianness: /** @type {import('../types.js').Endianness_} */ | ||
(get(4, readInt16, 0)), | ||
endianness: /** @type {import('../types.js').Endianness_} */ (get(4, readInt16, 0)), | ||
fields: get(6, (buf, off) => decodeSchemaFields(buf, off, dictionaryTypes), []), | ||
@@ -35,8 +34,5 @@ metadata: get(8, decodeMetadata), | ||
function decodeSchemaFields(buf, fieldsOffset, dictionaryTypes) { | ||
const { length, base } = readVector(buf, fieldsOffset); | ||
const fields = []; | ||
for (let i = 0; i < length; ++i) { | ||
fields.push(decodeField(buf, base + i * 4, dictionaryTypes)); | ||
} | ||
return fields; | ||
return readVector(buf, fieldsOffset, 4, | ||
(buf, pos) => decodeField(buf, pos, dictionaryTypes) | ||
); | ||
} | ||
@@ -58,4 +54,4 @@ | ||
const typeOffset = get(10, readOffset, 0); | ||
const dict = get(12, (buf, off) => decodeDictionary(buf, off)); | ||
const children = get(14, decodeFieldChildren); | ||
const dict = get(12, decodeDictionary); | ||
const children = get(14, (buf, off) => decodeFieldChildren(buf, off, dictionaryTypes)); | ||
@@ -89,9 +85,6 @@ let type; | ||
*/ | ||
function decodeFieldChildren(buf, fieldOffset, dictionaries) { | ||
const { length, base } = readVector(buf, fieldOffset); | ||
const children = []; | ||
for (let i = 0; i < length; ++i) { | ||
const pos = base + i * 4; | ||
children.push(decodeField(buf, pos, dictionaries)); | ||
} | ||
function decodeFieldChildren(buf, fieldOffset, dictionaryTypes) { | ||
const children = readVector(buf, fieldOffset, 4, | ||
(buf, pos) => decodeField(buf, pos, dictionaryTypes) | ||
); | ||
return children.length ? children : null; | ||
@@ -98,0 +91,0 @@ } |
import { int8 } from './array-types.js'; | ||
import { | ||
BinaryBatch, BoolBatch, DateBatch, DateDayBatch, DateDayMillisecondBatch, | ||
DecimalBatch, DenseUnionBatch, DictionaryBatch, DirectBatch, | ||
FixedBinaryBatch, FixedListBatch, Float16Batch, Int64Batch, | ||
IntervalDayTimeBatch, IntervalMonthDayNanoBatch, IntervalYearMonthBatch, | ||
LargeBinaryBatch, LargeListBatch, LargeUtf8Batch, ListBatch, MapBatch, | ||
MapEntryBatch, NullBatch, SparseUnionBatch, StructBatch, | ||
TimestampMicrosecondBatch, TimestampMillisecondBatch, | ||
TimestampNanosecondBatch, TimestampSecondBatch, Utf8Batch | ||
BinaryBatch, | ||
BinaryViewBatch, | ||
BoolBatch, | ||
DateBatch, | ||
DateDayBatch, | ||
DateDayMillisecondBatch, | ||
DecimalBatch, | ||
DenseUnionBatch, | ||
DictionaryBatch, | ||
DirectBatch, | ||
FixedBinaryBatch, | ||
FixedListBatch, | ||
Float16Batch, | ||
Int64Batch, | ||
IntervalDayTimeBatch, | ||
IntervalMonthDayNanoBatch, | ||
IntervalYearMonthBatch, | ||
LargeBinaryBatch, | ||
LargeListBatch, | ||
LargeListViewBatch, | ||
LargeUtf8Batch, | ||
ListBatch, | ||
ListViewBatch, | ||
MapBatch, | ||
MapEntryBatch, | ||
NullBatch, | ||
RunEndEncodedBatch, | ||
SparseUnionBatch, | ||
StructBatch, | ||
TimestampMicrosecondBatch, | ||
TimestampMillisecondBatch, | ||
TimestampNanosecondBatch, | ||
TimestampSecondBatch, | ||
Utf8Batch, | ||
Utf8ViewBatch | ||
} from './batch.js'; | ||
@@ -96,5 +123,6 @@ import { columnBuilder } from './column.js'; | ||
return batch => { | ||
const { length, nodes, buffers, body } = batch; | ||
const { length, nodes, buffers, variadic, body } = batch; | ||
let nodeIndex = -1; | ||
let bufferIndex = -1; | ||
let variadicIndex = -1; | ||
return { | ||
@@ -110,2 +138,3 @@ ...base, | ||
}, | ||
variadic: () => variadic[++variadicIndex], | ||
visitAll(list) { return list.map(x => visit(x.type, this)); } | ||
@@ -145,2 +174,8 @@ }; | ||
}); | ||
const view = (BatchType) => new BatchType({ | ||
...node, | ||
validity: ctx.buffer(), | ||
values: ctx.buffer(), // views buffer | ||
data: Array.from({ length: ctx.variadic() }, () => ctx.buffer()) // data buffers | ||
}); | ||
const list = (BatchType) => new BatchType({ | ||
@@ -152,2 +187,9 @@ ...node, | ||
}); | ||
const listview = (BatchType) => new BatchType({ | ||
...node, | ||
validity: ctx.buffer(), | ||
offsets: ctx.buffer(type.offsets), | ||
sizes: ctx.buffer(type.offsets), | ||
children: ctx.visitAll(type.children) | ||
}); | ||
const kids = (BatchType, opt) => new BatchType({ | ||
@@ -195,2 +237,6 @@ ...node, | ||
// views with variadic buffers | ||
case Type.BinaryView: return view(BinaryViewBatch); | ||
case Type.Utf8View: return view(Utf8ViewBatch); | ||
// validity, offset, and list child | ||
@@ -201,2 +247,6 @@ case Type.List: return list(ListBatch); | ||
// validity, offset, size, and list child | ||
case Type.ListView: return listview(ListViewBatch); | ||
case Type.LargeListView: return listview(LargeListViewBatch); | ||
// validity and children | ||
@@ -208,2 +258,8 @@ case Type.FixedSizeList: return kids(FixedListBatch, { stride }); | ||
// children only | ||
case Type.RunEndEncoded: return new RunEndEncodedBatch({ | ||
...node, | ||
children: ctx.visitAll(type.children) | ||
}); | ||
// dictionary | ||
@@ -226,8 +282,9 @@ case Type.Dictionary: { | ||
const isSparse = type.mode === UnionMode.Sparse; | ||
const typeIds = ctx.buffer(int8); | ||
const offsets = isSparse ? null : ctx.buffer(type.offsets); | ||
const children = ctx.visitAll(type.children); | ||
const map = type.typeIds.reduce((map, id, i) => ((map[id] = i), map), {}); | ||
const options = { ...node, map, typeIds, offsets, children }; | ||
return isSparse ? new SparseUnionBatch(options) : new DenseUnionBatch(options); | ||
return new (isSparse ? SparseUnionBatch : DenseUnionBatch)({ | ||
...node, | ||
map: type.typeIds.reduce((map, id, i) => ((map[id] = i), map), {}), | ||
typeIds: ctx.buffer(int8), | ||
offsets: isSparse ? null : ctx.buffer(type.offsets), | ||
children: ctx.visitAll(type.children) | ||
}); | ||
} | ||
@@ -237,4 +294,4 @@ | ||
default: | ||
throw new Error(`Unsupported type: ${typeId}, (${keyFor(Type, typeId)})`); | ||
throw new Error(`Unsupported type: ${typeId} ${keyFor(Type, typeId)}`); | ||
} | ||
} |
@@ -1,2 +0,2 @@ | ||
import { bisectOffsets } from './util.js'; | ||
import { bisect } from './util.js'; | ||
@@ -154,3 +154,3 @@ /** | ||
const [{ offsets }] = children; | ||
const i = bisectOffsets(offsets, index); | ||
const i = bisect(offsets, index) - 1; | ||
return rowObject(names, children, i, index - offsets[i]); | ||
@@ -157,0 +157,0 @@ } |
@@ -169,3 +169,3 @@ import { | ||
/** Union data type. */ | ||
export type UnionType = { typeId: 14, mode: UnionMode_, typeIds: Int32Array, children: Field[], offsets: Int32ArrayConstructor }; | ||
export type UnionType = { typeId: 14, mode: UnionMode_, typeIds: number[], children: Field[], offsets: Int32ArrayConstructor }; | ||
@@ -193,2 +193,17 @@ /** Fixed-size opaque binary data type. */ | ||
/** RunEndEncoded data type. */ | ||
export type RunEndEncodedType = { typeId: 22, children: [Field, Field] }; | ||
/** Opaque binary data type with multi-buffer view layout. */ | ||
export type BinaryViewType = { typeId: 23 }; | ||
/** UTF-8 encoded string data type with multi-buffer view layout. */ | ||
export type Utf8ViewType = { typeId: 24 }; | ||
/** ListView data type. */ | ||
export type ListViewType = { typeId: 25, children: [Field], offsets: Int32ArrayConstructor }; | ||
/** ListView data type with 64-bit integer offsets for larger data. */ | ||
export type LargeListViewType = { typeId: 26, children: [Field], offsets: BigInt64ArrayConstructor }; | ||
/** | ||
@@ -220,2 +235,7 @@ * Arrow field data types. | ||
| LargeListType | ||
| RunEndEncodedType | ||
| BinaryViewType | ||
| Utf8ViewType | ||
| ListViewType | ||
| LargeListViewType | ||
| DictionaryType; | ||
@@ -230,2 +250,3 @@ | ||
buffers: {offset: number, length: number}[]; | ||
variadic: number[]; | ||
body?: Uint8Array; | ||
@@ -232,0 +253,0 @@ } |
@@ -62,21 +62,28 @@ export const SIZEOF_INT = 4; | ||
* Determine the correct index into an offset array for a given | ||
* full column row index. | ||
* @param {Int32Array} offsets The offsets array. | ||
* full column row index. Assumes offset indices can be manipulated | ||
* as 32-bit signed integers. | ||
* @param {import("./types.js").IntegerArray} offsets The offsets array. | ||
* @param {number} index The full column row index. | ||
*/ | ||
export function bisectOffsets(offsets, index) { | ||
// binary search for batch index | ||
// we use a fast unsigned bit shift for division by two | ||
// this assumes offsets.length <= Math.pow(2, 31), which seems safe | ||
// otherwise that is a whole lotta record batches to handle in JS... | ||
export function bisect(offsets, index) { | ||
let a = 0; | ||
let b = offsets.length; | ||
do { | ||
const mid = (a + b) >>> 1; | ||
if (offsets[mid] <= index) a = mid + 1; | ||
else b = mid; | ||
} while (a < b); | ||
// decrement to the desired offset array index | ||
return --a; | ||
if (b <= 2147483648) { // 2 ** 31 | ||
// fast version, use unsigned bit shift | ||
// array length fits within 32-bit signed integer | ||
do { | ||
const mid = (a + b) >>> 1; | ||
if (offsets[mid] <= index) a = mid + 1; | ||
else b = mid; | ||
} while (a < b); | ||
} else { | ||
// slow version, use division and truncate | ||
// array length exceeds 32-bit signed integer | ||
do { | ||
const mid = Math.trunc((a + b) / 2); | ||
if (offsets[mid] <= index) a = mid + 1; | ||
else b = mid; | ||
} while (a < b); | ||
} | ||
return a; | ||
} | ||
@@ -234,12 +241,15 @@ | ||
/** | ||
* Return the length and start of a vector with the given offset. | ||
* Extract a flatbuffer vector to an array. | ||
* @template T | ||
* @param {Uint8Array} buf The byte buffer. | ||
* @param {number} offset The offset location of the vector. | ||
* @returns {{length: number, base: number}} The vector length and base. | ||
* @param {number} stride The stride between vector entries. | ||
* @param {(buf: Uint8Array, pos: number) => T} extract Vector entry extraction function. | ||
* @returns {T[]} The extracted vector entries. | ||
*/ | ||
export function readVector(buf, offset) { | ||
return { | ||
length: readInt32(buf, offset + readInt32(buf, offset)), | ||
base: offset + readInt32(buf, offset) + SIZEOF_INT | ||
}; | ||
export function readVector(buf, offset, stride, extract) { | ||
if (!offset) return []; | ||
const length = readInt32(buf, offset + readInt32(buf, offset)); | ||
const base = offset + readInt32(buf, offset) + SIZEOF_INT; | ||
return Array.from({ length }, (_, i) => extract(buf, base + i * stride)) | ||
} |
254185
7062