feat(serialize, parse): Number, String, Array, ConstString, ConstArray
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
coverage
|
||||||
|
build
|
||||||
|
dist
|
||||||
|
node_modules
|
||||||
2388
package-lock.json
generated
Normal file
2388
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
28
package.json
Normal file
28
package.json
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"name": "@sek1ro/serialize",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "structure and enum serialization in c-style",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "ssh://gitea@ssh.git.sek1.ro:50022/sek1ro/serialize-js.git"
|
||||||
|
},
|
||||||
|
"license": "LGPL-3.0-only",
|
||||||
|
"author": "Vlad Litvinov <vlad@sek1.ro>",
|
||||||
|
"type": "module",
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"build": "npx esbuild src/index.js --bundle --minify --outfile=dist/index.js --format=esm && npx rollup -c",
|
||||||
|
"test": "vitest",
|
||||||
|
"cover": "vitest --coverage"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@vitest/coverage-v8": "^3.2.4",
|
||||||
|
"esbuild": "^0.25.8",
|
||||||
|
"rollup": "^4.46.2",
|
||||||
|
"rollup-plugin-dts": "^6.2.1",
|
||||||
|
"vitest": "^3.2.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
10
rollup.config.js
Normal file
10
rollup.config.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { dts } from "rollup-plugin-dts";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
input: 'types/index.d.ts',
|
||||||
|
output: {
|
||||||
|
file: 'dist/index.d.ts',
|
||||||
|
format: 'es',
|
||||||
|
},
|
||||||
|
plugins: [dts()],
|
||||||
|
}
|
||||||
147
src/index.js
Normal file
147
src/index.js
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
import { limits } from "./limits"
|
||||||
|
import { memcpy } from "./mem"
|
||||||
|
import { ConstArray, ConstString } from "./type"
|
||||||
|
|
||||||
|
export { limits, memcpy, ConstString, ConstArray}
|
||||||
|
|
||||||
|
export function serialize(dv, src, ...types) {
|
||||||
|
const [type, ...inner_types] = types
|
||||||
|
|
||||||
|
if (type == Number && typeof src == 'number') {
|
||||||
|
if (dv.byteLength < 8) {
|
||||||
|
throw new Error('too small buffer')
|
||||||
|
}
|
||||||
|
dv.setFloat64(0, src)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ((type == String || type._func == ConstString) && typeof src == 'string') {
|
||||||
|
const encoder = new TextEncoder('utf-8')
|
||||||
|
let encoded
|
||||||
|
if (type == String) {
|
||||||
|
encoded = new DataView(encoder.encode(src).buffer)
|
||||||
|
if (dv.byteLength < 4 + encoded.byteLength) {
|
||||||
|
throw new Error('too small buffer')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
encoded = new DataView(encoder.encode(src).buffer, 0, type._size)
|
||||||
|
if (dv.byteLength < encoded.byteLength) {
|
||||||
|
throw new Error('too small buffer')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (encoded.byteLength > limits.u32.MAX_VALUE) {
|
||||||
|
throw new Error('string is too long')
|
||||||
|
}
|
||||||
|
|
||||||
|
dv.setUint32(0, encoded.byteLength)
|
||||||
|
|
||||||
|
const frame = new DataView(dv.buffer, dv.byteOffset + 4)
|
||||||
|
memcpy(frame, encoded)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ((type == Array || type._func == ConstArray) && Array.isArray(src)) {
|
||||||
|
|
||||||
|
const item_size = sizeofHead(src[0])
|
||||||
|
let size
|
||||||
|
|
||||||
|
if (type == Array) {
|
||||||
|
size = src.length
|
||||||
|
if (dv.byteLength < 4 + size * item_size) {
|
||||||
|
throw new Error('too small buffer')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
size = type._size
|
||||||
|
if (dv.byteLength < size * item_size) {
|
||||||
|
throw new Error('too small buffer')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (size > limits.u32.MAX_VALUE) {
|
||||||
|
throw new Error('array is too long')
|
||||||
|
}
|
||||||
|
|
||||||
|
dv.setUint32(0, size)
|
||||||
|
|
||||||
|
for (let i = 0; i < size; i++) {
|
||||||
|
const item_frame = new DataView(dv.buffer, dv.byteOffset + item_size * i)
|
||||||
|
serialize(item_frame, src[i], ...inner_types)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parse(dv, ...types) {
|
||||||
|
const [type, ...inner_types] = types
|
||||||
|
|
||||||
|
if (type == Number) {
|
||||||
|
return dv.getFloat64(0)
|
||||||
|
}
|
||||||
|
if (type == String || type._func == ConstString) {
|
||||||
|
let size
|
||||||
|
let frame
|
||||||
|
if (type == String) {
|
||||||
|
size = dv.getUint32(0)
|
||||||
|
frame = new DataView(dv.buffer, 4 + dv.byteOffset, size)
|
||||||
|
} else {
|
||||||
|
size = type._size
|
||||||
|
frame = new DataView(dv.buffer, dv.byteOffset, size)
|
||||||
|
}
|
||||||
|
const decoder = new TextDecoder('utf-8')
|
||||||
|
return decoder.decode(frame)
|
||||||
|
}
|
||||||
|
if (type == Array || type._func == ConstArray) {
|
||||||
|
let size
|
||||||
|
let offset = 0
|
||||||
|
if (type == Array) {
|
||||||
|
size = dv.getUint32(0)
|
||||||
|
offset = 4
|
||||||
|
} else {
|
||||||
|
size = type._size
|
||||||
|
}
|
||||||
|
const item_size = sizeofHead(inner_types[0])
|
||||||
|
const array = Array(size)
|
||||||
|
|
||||||
|
for (let i = 0; i < size; i++) {
|
||||||
|
const item_frame = new DataView(dv.buffer, dv.byteOffset + offset + item_size * i)
|
||||||
|
array[i] = parse(item_frame, ...inner_types)
|
||||||
|
}
|
||||||
|
|
||||||
|
return array
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isHeadless(...args) {
|
||||||
|
const [first_arg] = args
|
||||||
|
return first_arg == Array ||
|
||||||
|
first_arg == String ||
|
||||||
|
Array.isArray(first_arg) ||
|
||||||
|
typeof first_arg == 'string'
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sizeofHead(...args) {
|
||||||
|
if (isHeadless(...args)) {
|
||||||
|
return 4
|
||||||
|
} else {
|
||||||
|
return sizeof(...args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sizeof(...args) {
|
||||||
|
const [first_arg, ...remain_args] = args
|
||||||
|
|
||||||
|
if (first_arg == Number || typeof first_arg == 'number') {
|
||||||
|
return 8
|
||||||
|
}
|
||||||
|
if (first_arg._func == ConstArray) {
|
||||||
|
return sizeofHead(...remain_args) * first_arg._size
|
||||||
|
}
|
||||||
|
if (first_arg._func == ConstString) {
|
||||||
|
return first_arg._size
|
||||||
|
}
|
||||||
|
if (typeof first_arg == 'string') {
|
||||||
|
const encoder = new TextEncoder('utf-8')
|
||||||
|
return 4 + encoder.encode(first_arg).byteLength
|
||||||
|
}
|
||||||
|
if (Array.isArray(first_arg)) {
|
||||||
|
return 4 + sizeofHead(first_arg[0]) * first_arg.length
|
||||||
|
}
|
||||||
|
throw new Error('unknown size of ' + args)
|
||||||
|
}
|
||||||
69
src/limits.js
Normal file
69
src/limits.js
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
const i8 = {
|
||||||
|
MIN_VALUE: -128,
|
||||||
|
MAX_VALUE: 127,
|
||||||
|
}
|
||||||
|
const i16 = {
|
||||||
|
MIN_VALUE: -32768,
|
||||||
|
MAX_VALUE: 32767,
|
||||||
|
}
|
||||||
|
const i32 = {
|
||||||
|
MIN_VALUE: -2147483648,
|
||||||
|
MAX_VALUE: 2147483647,
|
||||||
|
}
|
||||||
|
const i64 = {
|
||||||
|
MIN_VALUE: -9223372036854775808n,
|
||||||
|
MAX_VALUE: 9223372036854775807n,
|
||||||
|
}
|
||||||
|
const u8 = {
|
||||||
|
MIN_VALUE: 0,
|
||||||
|
MAX_VALUE: 255,
|
||||||
|
}
|
||||||
|
const u16 = {
|
||||||
|
MIN_VALUE: 0,
|
||||||
|
MAX_VALUE: 65535,
|
||||||
|
}
|
||||||
|
const u32 = {
|
||||||
|
MIN_VALUE: 0,
|
||||||
|
MAX_VALUE: 4294967295,
|
||||||
|
}
|
||||||
|
const u64 = {
|
||||||
|
MIN_VALUE: 0n,
|
||||||
|
MAX_VALUE: 18446744073709551615n,
|
||||||
|
}
|
||||||
|
const bool = {
|
||||||
|
MIN_VALUE: 0,
|
||||||
|
MAX_VALUE: 1,
|
||||||
|
}
|
||||||
|
const f32 = {
|
||||||
|
MIN_VALUE: -3.40282347e+38,
|
||||||
|
MAX_VALUE: 3.40282347e+38,
|
||||||
|
MIN_NORMAL_VALUE: 1.17549435e-38,
|
||||||
|
MIN_SAFE_INTEGER: -16777215,
|
||||||
|
MAX_SAFE_INTEGER: 16777215,
|
||||||
|
EPSILON: 1.19209290e-07,
|
||||||
|
}
|
||||||
|
const f64 = {
|
||||||
|
MIN_VALUE: -1.7976931348623157e+308,
|
||||||
|
MAX_VALUE: 1.7976931348623157e+308,
|
||||||
|
MIN_NORMAL_VALUE: 2.2250738585072014e-308,
|
||||||
|
MIN_SAFE_INTEGER: -9007199254740991,
|
||||||
|
MAX_SAFE_INTEGER: 9007199254740991,
|
||||||
|
EPSILON: 2.2204460492503131e-16,
|
||||||
|
}
|
||||||
|
export const limits = {
|
||||||
|
i8,
|
||||||
|
i16,
|
||||||
|
i32,
|
||||||
|
i64,
|
||||||
|
u8,
|
||||||
|
u16,
|
||||||
|
u32,
|
||||||
|
u64,
|
||||||
|
bool,
|
||||||
|
f32,
|
||||||
|
f64,
|
||||||
|
}
|
||||||
|
for (const limit of Object.values(limits)) {
|
||||||
|
Object.freeze(limit)
|
||||||
|
}
|
||||||
|
Object.freeze(limits)
|
||||||
12
src/mem.js
Normal file
12
src/mem.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
export function memcpy(dest, src) {
|
||||||
|
const min_size = dest.byteLength > src.byteLength ?
|
||||||
|
src.byteLength : dest.byteLength
|
||||||
|
|
||||||
|
for (let i = 0; i < Math.floor(min_size / 8); i++) {
|
||||||
|
dest.setFloat64(i * 8, src.getFloat64(i * 8))
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = min_size - min_size % 8; i < min_size; i++) {
|
||||||
|
dest.setInt8(i, src.getInt8(i))
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/type.js
Normal file
18
src/type.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
export class Type {
|
||||||
|
constructor (func, obj) {
|
||||||
|
this._func = func
|
||||||
|
Object.assign(this, obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return this._func.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ConstString(size) {
|
||||||
|
return new Type(ConstString, { _size: size })
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ConstArray(size) {
|
||||||
|
return new Type(ConstArray, { _size: size })
|
||||||
|
}
|
||||||
15
test/index.js
Normal file
15
test/index.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
export function filledDataView(bytes) {
|
||||||
|
const ab = new ArrayBuffer(bytes.length)
|
||||||
|
const dv = new DataView(ab)
|
||||||
|
|
||||||
|
for (let i = 0; i < bytes.length; i++) {
|
||||||
|
dv.setInt8(i, bytes[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
return dv
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sizedDataView(length) {
|
||||||
|
const ab = new ArrayBuffer(length)
|
||||||
|
return new DataView(ab)
|
||||||
|
}
|
||||||
142
test/index.test.js
Normal file
142
test/index.test.js
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
import { describe, test, expect } from 'vitest'
|
||||||
|
import { filledDataView, sizedDataView } from '.'
|
||||||
|
import { parse, serialize, sizeof, sizeofHead } from '../src'
|
||||||
|
import { ConstArray, ConstString } from '../src/type'
|
||||||
|
|
||||||
|
describe('serialize', () => {
|
||||||
|
test('Number', () => {
|
||||||
|
const expected = filledDataView([0x40, 0x97, 0xF2, 0x80, 0x00, 0x00, 0x00, 0x00])
|
||||||
|
let dv = sizedDataView(7)
|
||||||
|
expect(() => serialize(dv, 0, Number)).toThrow()
|
||||||
|
|
||||||
|
dv = sizedDataView(sizeof(Number))
|
||||||
|
expect(8).toEqual(dv.byteLength)
|
||||||
|
|
||||||
|
serialize(dv, 1532.625, Number)
|
||||||
|
expect(dv).toEqual(expected)
|
||||||
|
})
|
||||||
|
test('ConstString', () => {
|
||||||
|
const expected = filledDataView([0x68, 0x65, 0x6C, 0x00, 0x00])
|
||||||
|
let dv = sizedDataView(4)
|
||||||
|
expect(() => serialize(dv, 'hello', ConstString(5))).toThrow()
|
||||||
|
|
||||||
|
dv = sizedDataView(5)
|
||||||
|
|
||||||
|
serialize(dv, 'hello', ConstString(3))
|
||||||
|
expect(dv).toEqual(expected)
|
||||||
|
})
|
||||||
|
test('String', () => {
|
||||||
|
const expected = filledDataView([
|
||||||
|
0x00, 0x00, 0x00, 0x05,
|
||||||
|
0x68, 0x65, 0x6C, 0x6C, 0x6F,
|
||||||
|
])
|
||||||
|
let dv = sizedDataView(8)
|
||||||
|
expect(() => serialize(dv, 'hello', String)).toThrow()
|
||||||
|
|
||||||
|
dv = sizedDataView(sizeof('hello'))
|
||||||
|
expect(9).toEqual(dv.byteLength)
|
||||||
|
|
||||||
|
serialize(dv, 'hello', String)
|
||||||
|
expect(dv).toEqual(expected)
|
||||||
|
})
|
||||||
|
test('ConstArray, Number', () => {
|
||||||
|
const expected = filledDataView([
|
||||||
|
0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
])
|
||||||
|
let dv = sizedDataView(15)
|
||||||
|
expect(() => serialize(dv, [1, 2], ConstArray(2), Number)).toThrow()
|
||||||
|
|
||||||
|
dv = sizedDataView(sizeof(ConstArray(2), Number))
|
||||||
|
expect(16).toEqual(dv.byteLength)
|
||||||
|
|
||||||
|
serialize(dv, [1, 2], ConstArray(2), Number)
|
||||||
|
expect(dv).toEqual(expected)
|
||||||
|
})
|
||||||
|
test('Array, Number', () => {
|
||||||
|
const expected = filledDataView([
|
||||||
|
0x00, 0x00, 0x00, 0x02,
|
||||||
|
0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
])
|
||||||
|
let dv = sizedDataView(19)
|
||||||
|
expect(() => serialize(dv, [1, 2], Array, Number)).toThrow()
|
||||||
|
|
||||||
|
dv = sizedDataView(sizeof([1, 2]))
|
||||||
|
expect(20).toEqual(dv.byteLength)
|
||||||
|
|
||||||
|
serialize(dv, [1, 2], Array, Number)
|
||||||
|
expect(dv).toEqual(expected)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('parse', () => {
|
||||||
|
test('Number', () => {
|
||||||
|
const expected = 1532.625
|
||||||
|
const dv = filledDataView([0x40, 0x97, 0xF2, 0x80, 0x00, 0x00, 0x00, 0x00])
|
||||||
|
const actual = parse(dv, Number)
|
||||||
|
expect(actual).toEqual(expected)
|
||||||
|
})
|
||||||
|
test('ConstString', () => {
|
||||||
|
const expected = 'hel'
|
||||||
|
const dv = filledDataView([0x68, 0x65, 0x6C, 0x6C, 0x6F])
|
||||||
|
const actual = parse(dv, ConstString(3))
|
||||||
|
expect(actual).toEqual(expected)
|
||||||
|
})
|
||||||
|
test('String', () => {
|
||||||
|
const expected = 'hello'
|
||||||
|
const dv = filledDataView([
|
||||||
|
0x00, 0x00, 0x00, 0x05,
|
||||||
|
0x68, 0x65, 0x6C, 0x6C, 0x6F
|
||||||
|
])
|
||||||
|
const actual = parse(dv, String)
|
||||||
|
expect(actual).toEqual(expected)
|
||||||
|
})
|
||||||
|
test('ConstArray, Number', () => {
|
||||||
|
const expected = [1, 2]
|
||||||
|
const dv = filledDataView([
|
||||||
|
0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
])
|
||||||
|
const actual = parse(dv, ConstArray(2), Number)
|
||||||
|
expect(actual).toEqual(expected)
|
||||||
|
})
|
||||||
|
test('Array, Number', () => {
|
||||||
|
const expected = [1, 2]
|
||||||
|
const dv = filledDataView([
|
||||||
|
0x00, 0x00, 0x00, 0x02,
|
||||||
|
0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
])
|
||||||
|
const actual = parse(dv, Array, Number)
|
||||||
|
expect(actual).toEqual(expected)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('sizeofHead', () => {
|
||||||
|
test('Number', () => {
|
||||||
|
expect(sizeofHead(Number)).toEqual(8)
|
||||||
|
expect(sizeofHead(1)).toEqual(8)
|
||||||
|
})
|
||||||
|
test('ConstString', () => {
|
||||||
|
expect(sizeofHead(ConstString(2))).toEqual(2)
|
||||||
|
})
|
||||||
|
test('String', () => {
|
||||||
|
expect(sizeofHead(String)).toEqual(4)
|
||||||
|
expect(sizeofHead('s')).toEqual(4)
|
||||||
|
})
|
||||||
|
test('ConstArray', () => {
|
||||||
|
expect(sizeofHead(ConstArray(2), Number)).toEqual(16)
|
||||||
|
})
|
||||||
|
test('Array', () => {
|
||||||
|
expect(sizeofHead(Array, Number)).toEqual(4)
|
||||||
|
expect(sizeofHead([1])).toEqual(4)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('sizeof', () => {
|
||||||
|
test('unknown', () => {
|
||||||
|
expect(() => sizeof(String)).toThrow()
|
||||||
|
expect(() => sizeof(Array, Number)).toThrow()
|
||||||
|
})
|
||||||
|
})
|
||||||
18
test/mem.test.js
Normal file
18
test/mem.test.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { expect, test } from "vitest";
|
||||||
|
import { filledDataView, sizedDataView } from ".";
|
||||||
|
import { memcpy } from "../src";
|
||||||
|
|
||||||
|
test('memcpy', () => {
|
||||||
|
{
|
||||||
|
const dest = sizedDataView(9)
|
||||||
|
const src = filledDataView([0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01])
|
||||||
|
memcpy(dest, src)
|
||||||
|
expect(dest).toEqual(src)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const dest = sizedDataView(10)
|
||||||
|
const src = filledDataView([0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01])
|
||||||
|
memcpy(dest, src)
|
||||||
|
expect(dest).toEqual(src)
|
||||||
|
}
|
||||||
|
})
|
||||||
67
types/index.d.ts
vendored
Normal file
67
types/index.d.ts
vendored
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import { memcpy } from "./mem";
|
||||||
|
import { limits } from "./limits";
|
||||||
|
import { ConstString, ConstArray } from "./type";
|
||||||
|
|
||||||
|
export { memcpy, limits, ConstString, ConstArray }
|
||||||
|
|
||||||
|
import { Type } from "./type";
|
||||||
|
|
||||||
|
export type SerializableType = NumberConstructor | StringConstructor | ArrayConstructor | Type
|
||||||
|
export type Serializable = number | string | array
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {DataView} dv destination memory
|
||||||
|
* @param {Serializable} src source object
|
||||||
|
* @param {SerializableType[]} ...types primary and inner types. eg: Array, Number
|
||||||
|
* @throws {Error} if too small buffer
|
||||||
|
* @throws {Error} if array|string size is higher than limits.u32.MAX_VALUE
|
||||||
|
*/
|
||||||
|
export function serialize(dv: DataView, src: Serializable, ...types: SerializableType[]): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {DataView} dv source memory
|
||||||
|
* @param {SerializableType[]} ...types primary and inner types. eg: Array, Number
|
||||||
|
* @returns {Serializable} parsed object
|
||||||
|
*/
|
||||||
|
export function parse(dv: DataView, ...types: SerializableType[]): Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* some types, like Array, String, has no fixed size. So in Structure they are stored as u32 offset, which points to their beginning
|
||||||
|
* @param {Serializable} obj to check
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
export function isHeadless(obj: Serializable): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* some types, like Array, String, has no fixed size. So in Structure they are stored as u32 offset, which points to their beginning
|
||||||
|
* @param {SerializableType[]} ...args primary and inner types. eg: Array, Number
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
export function isHeadless(...types: SerializableType[]): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if obj has no fixed size, return 4 (sizeof u32 offset)
|
||||||
|
* @param {Serializable} obj to check
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
export function sizeofHead(obj: Serializable): number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if obj has no fixed size, return 4 (sizeof u32 offset)
|
||||||
|
* @param {SerializableType[]} ...args primary and inner types. eg: Array, Number
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
export function sizeofHead(...types: SerializableType[]): number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Serializable} obj to check
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
export function sizeof(obj: Serializable): number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {SerializableType[]} ...args primary and inner types. eg: Array, Number
|
||||||
|
* @returns {number}
|
||||||
|
* @throws {Error} if passed Array or String type (unknown sizeof)
|
||||||
|
*/
|
||||||
|
export function sizeof(...types: SerializableType[]): number;
|
||||||
32
types/limits.d.ts
vendored
Normal file
32
types/limits.d.ts
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
export interface IntLimit {
|
||||||
|
MIN_VALUE: number
|
||||||
|
MAX_VALUE: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BigIntLimit {
|
||||||
|
MIN_VALUE: bigint
|
||||||
|
MAX_VALUE: bigint
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FloatLimit {
|
||||||
|
MIN_VALUE: number
|
||||||
|
MAX_VALUE: number
|
||||||
|
MIN_NORMAL_VALUE: number
|
||||||
|
MIN_SAFE_INTEGER: number
|
||||||
|
MAX_SAFE_INTEGER: number
|
||||||
|
EPSILON: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export const limits: {
|
||||||
|
i8: IntLimit
|
||||||
|
i16: IntLimit
|
||||||
|
i32: IntLimit
|
||||||
|
i64: BigIntLimit
|
||||||
|
u8: IntLimit
|
||||||
|
u16: IntLimit
|
||||||
|
u32: IntLimit
|
||||||
|
u64: BigIntLimit
|
||||||
|
bool: IntLimit
|
||||||
|
f32: FloatLimit
|
||||||
|
f64: FloatLimit
|
||||||
|
};
|
||||||
4
types/mem.d.ts
vendored
Normal file
4
types/mem.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* copies max possible number of bytes from src to dest (min of both sizes)
|
||||||
|
*/
|
||||||
|
export function memcpy(dest: DataView, src: DataView): void;
|
||||||
15
types/type.d.ts
vendored
Normal file
15
types/type.d.ts
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
export type Type = unknown
|
||||||
|
|
||||||
|
/**
|
||||||
|
* constructs type of utf8-string with constant byte size
|
||||||
|
* @param {number} byte_size max utf8-encoded byte size
|
||||||
|
* @returns {Type}
|
||||||
|
*/
|
||||||
|
export function ConstString(byte_size: number): Type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* constructs type of array with constant byte size
|
||||||
|
* @param {number} size number of items
|
||||||
|
* @returns {Type}
|
||||||
|
*/
|
||||||
|
export function ConstArray(size: number): Type;
|
||||||
Reference in New Issue
Block a user