UNPKG

mustreams

Version:

Binary stream and buffer for mudb

289 lines (237 loc) 8.38 kB
import * as test from 'tape'; import { MuWriteStream, MuReadStream } from '../'; import { reallocBuffer, allocBuffer, freeBuffer } from '../'; import StringCodec = require('../string'); const { encodeString, decodeString, } = StringCodec; test('buffer allocation', (t) => { t.equals(allocBuffer(8).buffer.byteLength, 8); t.equals(allocBuffer(9).buffer.byteLength, 16); t.equals(allocBuffer(15).buffer.byteLength, 16); t.equals(allocBuffer(2 ** 30).buffer.byteLength, 2 ** 30); t.throws(() => allocBuffer(2 ** 30 + 1)); t.throws(() => allocBuffer(2 ** 32)); t.end(); }); test('growing buffer', (t) => { const ws = new MuWriteStream(8); const oldBuffer = ws.buffer; ws.writeFloat64(1234.5678); ws.grow(0); t.equals(ws.buffer.buffer.byteLength, 8); t.equals(oldBuffer, ws.buffer, 'still the same buffer'); ws.grow(1); t.equals(ws.buffer.buffer.byteLength, 16); t.notEquals(oldBuffer, ws.buffer, 'different buffer now'); t.equals(ws.buffer.dataView.getFloat64(0, true), oldBuffer.dataView.getFloat64(0, true), 'but same content'); t.end(); }); test('int', (t) => { const loops = 64; const ws = new MuWriteStream(0x1000); for (let i = -0x80; i < 0x80; i += 0x100 / loops) { ws.writeInt8(i); ws.writeInt8(i + 0x100 / loops - 1); } for (let i = -0x8000; i < 0x8000; i += 0x10000 / loops) { ws.writeInt16(i); ws.writeInt16(i + 0x10000 / loops - 1); } for (let i = -0x80000000; i < 0x80000000; i += 0x100000000 / loops) { ws.writeInt32(i); ws.writeInt32(i + 0x100000000 / loops - 1); } for (let i = 0; i < 0x100000000; i += 0x100000000 / loops) { ws.writeUint32(i); ws.writeUint32(i + 0x100000000 / loops - 1); } for (let i = 0; i < 0x10000; i += 0x10000 / loops) { ws.writeUint16(i); ws.writeUint16(i + 0x10000 / loops - 1); } for (let i = 0; i < 0x100; i += 0x100 / loops) { ws.writeUint8(i); ws.writeUint8(i + 0x100 / loops - 1); } const rs = new MuReadStream(ws.buffer.uint8); for (let i = -0x80; i < 0x80; i += 0x100 / loops) { t.equals(rs.readInt8(), i); t.equals(rs.readInt8(), i + 0x100 / loops - 1); } for (let i = -0x8000; i < 0x8000; i += 0x10000 / loops) { t.equals(rs.readInt16(), i); t.equals(rs.readInt16(), i + 0x10000 / loops - 1); } for (let i = -0x80000000; i < 0x80000000; i += 0x100000000 / loops) { t.equals(rs.readInt32(), i); t.equals(rs.readInt32(), i + 0x100000000 / loops - 1); } for (let i = 0; i < 0x100000000; i += 0x100000000 / loops) { t.equals(rs.readUint32(), i); t.equals(rs.readUint32(), i + 0x100000000 / loops - 1); } for (let i = 0; i < 0x10000; i += 0x10000 / loops) { t.equals(rs.readUint16(), i); t.equals(rs.readUint16(), i + 0x10000 / loops - 1); } for (let i = 0; i < 0x100; i += 0x100 / loops) { t.equals(rs.readUint8(), i); t.equals(rs.readUint8(), i + 0x100 / loops - 1); } t.end(); }); test('float', (t) => { const FLOAT32_EPSILON = 1.401298464324817e-45; const FLOAT32_MIN = 1.1754943508222875e-38; const FLOAT32_MAX = 3.4028234663852886e+38; const FLOAT64_EPSILON = 5e-324; const FLOAT64_MIN = 2.2250738585072014e-308; const FLOAT64_MAX = 1.7976931348623157e+308; const ws = new MuWriteStream(0x100); const floatNum = Math.random(); ws.writeFloat32(FLOAT32_MIN); ws.writeFloat32(-FLOAT32_EPSILON); ws.writeFloat32(0); ws.writeFloat32(FLOAT32_EPSILON); ws.writeFloat32(FLOAT32_MAX); ws.writeFloat32(floatNum); ws.writeFloat64(FLOAT64_MIN); ws.writeFloat64(-FLOAT64_EPSILON); ws.writeFloat64(0); ws.writeFloat64(FLOAT64_EPSILON); ws.writeFloat64(FLOAT64_MAX); ws.writeFloat64(floatNum); function fround (num) { const arr = new Float32Array(1); arr[0] = num; return arr[0]; } const rs = new MuReadStream(ws.buffer.uint8); t.equals(rs.readFloat32(), FLOAT32_MIN); t.equals(rs.readFloat32(), -FLOAT32_EPSILON); t.equals(rs.readFloat32(), 0); t.equals(rs.readFloat32(), FLOAT32_EPSILON); t.equals(rs.readFloat32(), FLOAT32_MAX); t.equals(rs.readFloat32(), fround(floatNum)); t.equals(rs.readFloat64(), FLOAT64_MIN); t.equals(rs.readFloat64(), -FLOAT64_EPSILON); t.equals(rs.readFloat64(), 0); t.equals(rs.readFloat64(), FLOAT64_EPSILON); t.equals(rs.readFloat64(), FLOAT64_MAX); t.equals(rs.readFloat64(), floatNum); t.end(); }); test('ascii string', (t) => { const asciis = new Array(128); for (let i = 0; i < 128; ++i) { asciis[i] = String.fromCharCode(i); } let ws = new MuWriteStream(1024); ws.writeUint32(0); ws.writeASCIINoLength(''); for (let i = 0; i < 128; ++i) { ws.writeUint32(1); ws.writeASCIINoLength(asciis[i]); } let rs = new MuReadStream(ws.buffer.uint8); let strLeng = rs.readUint32(); t.equals(rs.readASCIIOf(strLeng), ''); for (let i = 0; i < 128; ++i) { strLeng = rs.readUint32(); t.equals(rs.readASCIIOf(strLeng), asciis[i]); } let longStr = ''; const str = asciis.join(''); for (let i = 0; i < 1e5; ++i) { longStr += str; } ws = new MuWriteStream(2 ** 30); ws.writeUint32(longStr.length); ws.writeASCIINoLength(longStr); rs = new MuReadStream(ws.buffer.uint8); strLeng = rs.readUint32(); t.equals(rs.readASCIIOf(strLeng), longStr); t.end(); }); test('string', (t) => { const emptyStr = ''; const strA = String.fromCharCode(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); const strB = String.fromCharCode(0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); const strC = String.fromCharCode(0x12, 0x34, 0x56, 0x78, 0x87, 0x65, 0x43, 0x21); const strD = String.fromCharCode(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); let ws = new MuWriteStream(128); ws.writeString(''); ws.writeString(strA); ws.writeString(strB); ws.writeString(strC); ws.writeString(strD); let rs = new MuReadStream(ws.buffer.uint8); t.equals(rs.readString(), ''); t.equals(rs.readString(), strA); t.equals(rs.readString(), strB); t.equals(rs.readString(), strC); t.equals(rs.readString(), strD); const ascii = 'I <3 you.'; const twoBytes = 'אני אוהבת אותך'; const threeBytes = '我♥你'; const fourBytes = '👩👨❤️👨👩'; ws = new MuWriteStream(256); ws.writeString(ascii); ws.writeString(twoBytes); ws.writeString(threeBytes); ws.writeString(fourBytes); rs = new MuReadStream(ws.buffer.uint8); t.equals(rs.readString(), ascii); t.equals(rs.readString(), twoBytes); t.equals(rs.readString(), threeBytes); t.equals(rs.readString(), fourBytes); const varBytes = fourBytes + twoBytes + ascii + threeBytes; let longStr = ''; for (let i = 0; i < 100000; ++i) { longStr += varBytes; } ws = new MuWriteStream(2 ** 30); ws.writeString(longStr); rs = new MuReadStream(ws.buffer.uint8); t.equals(rs.readString(), longStr, 'able to write and read a long string of characters of various bytes'); t.end(); }); test('varints', (t) => { const testVals = [ 1, 64, 128, 129, 255, 256, (1 << 7), (1 << 14), (1 << 21), (1 << 28), (1 << 31), ]; for (let i = testVals.length - 1; i >= 0; --i) { const x = testVals[i]; testVals.push( (x - 1) >>> 0, (x + 1) >>> 0, (x + (Math.random() * x) | 0) >>> 0); } testVals.push(0); testVals.push(0xfffffff); const ws = new MuWriteStream(5 * testVals.length); for (let i = 0; i < testVals.length; ++i) { ws.writeVarInt(testVals[i]); } const rs = new MuReadStream(ws.bytes()); for (let i = 0; i < testVals.length; ++i) { t.equals(rs.readVarInt(), testVals[i] >>> 0, 'var int read ok: 0b' + (testVals[i] >>> 0).toString(2)); } t.end(); });