UNPKG

@cloudpss/ubjson

Version:

116 lines 3.48 kB
import { EncoderBase } from './base/encoder.js'; const BLOCK_SIZE = 1024 * 64; // 64 KiB const MAX_SIZE = 1024 * 1024 * 128; //128 MiB /** 编码至 ubjson */ export class Encoder extends EncoderBase { constructor() { super(...arguments); this.flushedBuffers = []; /** 通过内存池减少分配 */ this.pool = new Uint8Array(BLOCK_SIZE); /** 缓存当前容量,避免对象访问耗时 */ this.capacity = 0; } /** * 确保 buffer 还有 capacity 的空闲空间 */ ensureCapacity(capacity) { if (capacity > MAX_SIZE) { // 超过最大尺寸限制 throw new Error('Buffer has exceed max size'); } if (this.capacity >= this.length + capacity) { // 无需扩容 return; } this.flushBuffer(capacity); } /** 提交并扩容 */ flushBuffer(capacity) { // 提交目前的数据 if (this.data === this.pool) { this.flushedBuffers.push(this.data.slice(0, this.length)); } else { this.flushedBuffers.push(this.data.subarray(0, this.length)); } // 重新分配缓冲区 if (capacity < BLOCK_SIZE) capacity = BLOCK_SIZE; this.allocUnsafe(capacity); } /** 分配 buffer */ allocUnsafe(size) { const data = size === BLOCK_SIZE ? // 从 pool 中获取 this.pool : // 新建 buffer new Uint8Array(size); this.data = data; this.view = new DataView(data.buffer); this.length = 0; this.capacity = size; } /** 获取结果 */ getResult() { if (this.flushedBuffers.length === 0) { // 缓冲区为空,复制当前 buffer return this.data.slice(0, this.length); } // 合并缓冲区 const { length } = this; const activeBuffer = this.data.subarray(0, length); const flushedBuffers = this.flushedBuffers.splice(0); const size = flushedBuffers.reduce((sum, buffer) => sum + buffer.byteLength, length); const result = new Uint8Array(size); let offset = 0; for (const buffer of flushedBuffers) { result.set(buffer, offset); offset += buffer.byteLength; } result.set(activeBuffer, offset); return result; } /** 抛弃结果 */ cleanResult() { this.flushedBuffers.splice(0); } /** 获取写入结果 */ encode(value) { try { this.allocUnsafe(BLOCK_SIZE); this.writeValue(value); return this.getResult(); } catch (e) { this.cleanResult(); throw e; } } /** 获取写入结果 */ encodeMany(value) { try { this.allocUnsafe(BLOCK_SIZE); for (const v of value) { this.writeValue(v); } return this.getResult(); } catch (e) { this.cleanResult(); throw e; } } } let _ENCODER; /** 获取默认的编码器 */ export function getEncoder(options) { _ENCODER ??= new Encoder(); _ENCODER.sortObjectKeys = options?.sortObjectKeys ?? false; return _ENCODER; } /** 重置编码器, For testing only */ export function resetEncoder() { _ENCODER = undefined; } //# sourceMappingURL=encoder.js.map