hyparquet-writer/src/bytewriter.js

154 lines
3.4 KiB
JavaScript
Raw Normal View History

2025-03-25 17:27:15 +00:00
/**
2025-04-08 06:14:48 +00:00
* Generic buffered writer.
2025-04-08 10:22:30 +00:00
* Writes data to an auto-expanding ArrayBuffer.
2025-03-25 17:27:15 +00:00
*
2025-04-08 06:14:48 +00:00
* @import {Writer} from '../src/types.js'
* @returns {Writer}
2025-03-25 17:27:15 +00:00
*/
2025-04-08 06:14:48 +00:00
export function ByteWriter() {
2025-03-25 17:27:15 +00:00
this.buffer = new ArrayBuffer(1024)
this.view = new DataView(this.buffer)
2025-04-16 05:21:52 +00:00
this.offset = 0 // bytes written
this.index = 0 // index in buffer
2025-03-25 17:27:15 +00:00
return this
}
/**
* @param {number} size
*/
2025-04-08 06:14:48 +00:00
ByteWriter.prototype.ensure = function(size) {
// auto-expanding buffer
2025-04-16 05:21:52 +00:00
if (this.index + size > this.buffer.byteLength) {
const newSize = Math.max(this.buffer.byteLength * 2, this.index + size)
2025-03-25 17:27:15 +00:00
const newBuffer = new ArrayBuffer(newSize)
2025-04-08 06:14:48 +00:00
// TODO: save buffers until later and merge once?
2025-03-25 17:27:15 +00:00
new Uint8Array(newBuffer).set(new Uint8Array(this.buffer))
this.buffer = newBuffer
this.view = new DataView(this.buffer)
}
}
2025-04-08 06:14:48 +00:00
ByteWriter.prototype.finish = function() {
}
ByteWriter.prototype.getBuffer = function() {
2025-04-16 05:21:52 +00:00
return this.buffer.slice(0, this.index)
2025-03-25 20:36:18 +00:00
}
2025-03-25 17:27:15 +00:00
/**
* @param {number} value
*/
2025-04-08 06:14:48 +00:00
ByteWriter.prototype.appendUint8 = function(value) {
2025-04-16 05:21:52 +00:00
this.ensure(this.index + 1)
this.view.setUint8(this.index, value)
2025-03-25 17:27:15 +00:00
this.offset++
2025-04-16 05:21:52 +00:00
this.index++
2025-03-25 17:27:15 +00:00
}
/**
* @param {number} value
*/
2025-04-08 06:14:48 +00:00
ByteWriter.prototype.appendUint32 = function(value) {
2025-04-16 05:21:52 +00:00
this.ensure(this.index + 4)
this.view.setUint32(this.index, value, true)
2025-03-25 17:27:15 +00:00
this.offset += 4
2025-04-16 05:21:52 +00:00
this.index += 4
2025-03-25 17:27:15 +00:00
}
2025-03-25 23:42:52 +00:00
/**
* @param {number} value
*/
2025-04-08 06:14:48 +00:00
ByteWriter.prototype.appendInt32 = function(value) {
2025-04-16 05:21:52 +00:00
this.ensure(this.index + 4)
this.view.setInt32(this.index, value, true)
2025-03-25 23:42:52 +00:00
this.offset += 4
2025-04-16 05:21:52 +00:00
this.index += 4
2025-03-25 23:42:52 +00:00
}
/**
* @param {bigint} value
*/
2025-04-08 06:14:48 +00:00
ByteWriter.prototype.appendInt64 = function(value) {
2025-04-16 05:21:52 +00:00
this.ensure(this.index + 8)
this.view.setBigInt64(this.index, BigInt(value), true)
2025-03-25 23:42:52 +00:00
this.offset += 8
2025-04-16 05:21:52 +00:00
this.index += 8
2025-03-25 23:42:52 +00:00
}
2025-04-08 11:20:32 +00:00
/**
* @param {number} value
*/
ByteWriter.prototype.appendFloat32 = function(value) {
2025-04-16 05:21:52 +00:00
this.ensure(this.index + 8)
this.view.setFloat32(this.index, value, true)
2025-04-08 11:20:32 +00:00
this.offset += 4
2025-04-16 05:21:52 +00:00
this.index += 4
2025-04-08 11:20:32 +00:00
}
2025-03-25 17:27:15 +00:00
/**
* @param {number} value
*/
2025-04-08 06:14:48 +00:00
ByteWriter.prototype.appendFloat64 = function(value) {
2025-04-16 05:21:52 +00:00
this.ensure(this.index + 8)
this.view.setFloat64(this.index, value, true)
2025-03-25 17:27:15 +00:00
this.offset += 8
2025-04-16 05:21:52 +00:00
this.index += 8
2025-03-25 17:27:15 +00:00
}
/**
* @param {ArrayBuffer} value
*/
2025-04-08 06:14:48 +00:00
ByteWriter.prototype.appendBuffer = function(value) {
2025-03-26 03:15:14 +00:00
this.appendBytes(new Uint8Array(value))
}
/**
* @param {Uint8Array} value
*/
2025-04-08 06:14:48 +00:00
ByteWriter.prototype.appendBytes = function(value) {
2025-04-16 05:21:52 +00:00
this.ensure(this.index + value.length)
new Uint8Array(this.buffer, this.index, value.length).set(value)
2025-03-26 03:15:14 +00:00
this.offset += value.length
2025-04-16 05:21:52 +00:00
this.index += value.length
2025-03-25 17:27:15 +00:00
}
/**
* Convert a 32-bit signed integer to varint (1-5 bytes).
* Writes out groups of 7 bits at a time, setting high bit if more to come.
*
* @param {number} value
*/
2025-04-08 06:14:48 +00:00
ByteWriter.prototype.appendVarInt = function(value) {
2025-03-25 17:27:15 +00:00
while (true) {
if ((value & ~0x7f) === 0) {
// fits in 7 bits
this.appendUint8(value)
return
} else {
// write 7 bits and set high bit
this.appendUint8(value & 0x7f | 0x80)
value >>>= 7
}
}
}
/**
* Convert a bigint to varint (1-10 bytes for 64-bit range).
*
* @param {bigint} value
*/
2025-04-08 06:14:48 +00:00
ByteWriter.prototype.appendVarBigInt = function(value) {
2025-03-25 17:27:15 +00:00
while (true) {
if ((value & ~0x7fn) === 0n) {
// fits in 7 bits
this.appendUint8(Number(value))
return
} else {
// write 7 bits and set high bit
this.appendUint8(Number(value & 0x7fn | 0x80n))
value >>= 7n
}
}
}