structom 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +16 -0
- package/readme.md +0 -0
- package/src/any.ts +145 -0
- package/src/buf.ts +116 -0
- package/src/general.ts +90 -0
- package/src/index.ts +40 -0
- package/src/number.ts +166 -0
- package/src/rich.ts +32 -0
- package/tsconfig.json +20 -0
package/package.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "structom",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "new generation of reactivity and speed",
|
|
5
|
+
"author": "aliibrahim123",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"homepage": "https://aliibrahim123.github.io/structom/",
|
|
8
|
+
"bugs": {
|
|
9
|
+
"url": "https://github.com/aliibrahim123/structom/issues"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "https://github.com/aliibrahim123/structom.git"
|
|
14
|
+
},
|
|
15
|
+
"license": "MIT"
|
|
16
|
+
}
|
package/readme.md
ADDED
|
File without changes
|
package/src/any.ts
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { decode_i16, decode_i32, decode_i64, decode_i8, decode_u16, decode_u32, decode_u64, decode_u8, encode_u8, type Buffer, type Cursor } from "./buf.ts";
|
|
2
|
+
import { decode_bool, decode_str, decode_arr, decode_map, encode_bool, encode_str, encode_arr, encode_map } from "./general.ts";
|
|
3
|
+
import type { Value } from "./index.ts";
|
|
4
|
+
import { decode_f32, decode_f64, decode_vint, decode_vuint, encode_f64, encode_vint, encode_vuint } from "./number.ts";
|
|
5
|
+
import { decode_dur, decode_inst, decode_instN, decode_uuid, encode_dur, encode_inst, encode_uuid } from "./rich.ts";
|
|
6
|
+
|
|
7
|
+
const any_typeid = 0x01;
|
|
8
|
+
const bool_typeid = 0x08;
|
|
9
|
+
const u8_typeid = 0x10;
|
|
10
|
+
const u16_typeid = 0x11;
|
|
11
|
+
const u32_typeid = 0x12;
|
|
12
|
+
const u64_typeid = 0x13;
|
|
13
|
+
const i8_typeid = 0x14;
|
|
14
|
+
const i16_typeid = 0x15;
|
|
15
|
+
const i32_typeid = 0x16;
|
|
16
|
+
const i64_typeid = 0x17;
|
|
17
|
+
const f32_typeid = 0x18;
|
|
18
|
+
const f64_typeid = 0x19;
|
|
19
|
+
const vuint_typeid = 0x1c;
|
|
20
|
+
const vint_typeid = 0x1d;
|
|
21
|
+
const str_typeid = 0x20;
|
|
22
|
+
const arr_typeid = 0x22;
|
|
23
|
+
const map_typeid = 0x23;
|
|
24
|
+
const inst_typeid = 0x30;
|
|
25
|
+
const instn_typeid = 0x31;
|
|
26
|
+
const dur_typeid = 0x32;
|
|
27
|
+
const uuid_typeid = 0x33;
|
|
28
|
+
|
|
29
|
+
function decode_value(buf: Buffer, typeid: number, cur: Cursor): Value {
|
|
30
|
+
switch (typeid) {
|
|
31
|
+
case any_typeid: return decode_any(buf, cur);
|
|
32
|
+
case bool_typeid: return decode_bool(buf, cur);
|
|
33
|
+
|
|
34
|
+
case u8_typeid: return decode_u8(buf, cur);
|
|
35
|
+
case u16_typeid: return decode_u16(buf, cur);
|
|
36
|
+
case u32_typeid: return decode_u32(buf, cur);
|
|
37
|
+
case u64_typeid: return decode_u64(buf, cur);
|
|
38
|
+
|
|
39
|
+
case i8_typeid: return decode_i8(buf, cur);
|
|
40
|
+
case i16_typeid: return decode_i16(buf, cur);
|
|
41
|
+
case i32_typeid: return decode_i32(buf, cur);
|
|
42
|
+
case i64_typeid: return decode_i64(buf, cur);
|
|
43
|
+
|
|
44
|
+
case f32_typeid: return decode_f32(buf, cur);
|
|
45
|
+
case f64_typeid: return decode_f64(buf, cur);
|
|
46
|
+
|
|
47
|
+
case vuint_typeid: return decode_vuint(buf, cur);
|
|
48
|
+
case vint_typeid: return decode_vint(buf, cur);
|
|
49
|
+
|
|
50
|
+
case str_typeid: return decode_str(buf, cur);
|
|
51
|
+
case inst_typeid: return decode_inst(buf, cur);
|
|
52
|
+
case instn_typeid: return decode_instN(buf, cur);
|
|
53
|
+
case dur_typeid: return decode_dur(buf, cur);
|
|
54
|
+
case uuid_typeid: return decode_uuid(buf, cur);
|
|
55
|
+
|
|
56
|
+
case arr_typeid: {
|
|
57
|
+
let item_id = decode_u8(buf, cur);
|
|
58
|
+
return decode_arr(buf, cur, (buf, cur) => decode_value(buf, item_id, cur))
|
|
59
|
+
}
|
|
60
|
+
case map_typeid: {
|
|
61
|
+
let key_id = decode_u8(buf, cur);
|
|
62
|
+
let value_id = decode_u8(buf, cur);
|
|
63
|
+
return decode_map(buf, cur,
|
|
64
|
+
(buf, cur) => decode_value(buf, key_id, cur),
|
|
65
|
+
(buf, cur) => decode_value(buf, value_id, cur)
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return undefined as any
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function decode_any (buf: Buffer, cur: Cursor): Value {
|
|
73
|
+
return decode_value(buf, decode_u8(buf, cur), cur);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function resolve_typeid(value: Value): number {
|
|
77
|
+
switch (typeof(value)) {
|
|
78
|
+
case 'boolean': return bool_typeid;
|
|
79
|
+
case 'number': return Number.isInteger(value) ? vint_typeid : f64_typeid
|
|
80
|
+
case 'bigint': return vint_typeid;
|
|
81
|
+
case 'string': return str_typeid
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (value instanceof Date) return inst_typeid;
|
|
85
|
+
if ('type' in value) switch (value.type) {
|
|
86
|
+
case 'dur': return dur_typeid;
|
|
87
|
+
case 'uuid': return uuid_typeid;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (Array.isArray(value)) return arr_typeid;
|
|
91
|
+
return map_typeid
|
|
92
|
+
}
|
|
93
|
+
function encode_value(buf: Buffer, value: Value, typeid: number): void {
|
|
94
|
+
switch (typeid) {
|
|
95
|
+
case any_typeid: return encode_any(buf, value);
|
|
96
|
+
case bool_typeid: return encode_bool(buf, value as any);
|
|
97
|
+
case vint_typeid: return encode_vint(buf, value as any);
|
|
98
|
+
case f64_typeid: return encode_f64(buf, value as any);
|
|
99
|
+
case str_typeid: return encode_str(buf, value as any);
|
|
100
|
+
case inst_typeid: return encode_inst(buf, value as any);
|
|
101
|
+
case dur_typeid: return encode_dur(buf, value as any);
|
|
102
|
+
case uuid_typeid: return encode_uuid(buf, value as any);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
export function encode_any (buf: Buffer, value: Value): void {
|
|
106
|
+
let typeid = resolve_typeid(value);
|
|
107
|
+
encode_u8(buf, typeid);
|
|
108
|
+
|
|
109
|
+
if (typeid !== arr_typeid && typeid !== map_typeid)
|
|
110
|
+
return encode_value(buf, value, typeid);
|
|
111
|
+
|
|
112
|
+
if (Array.isArray(value)) {
|
|
113
|
+
let item_id = value.length === 0 ? any_typeid : resolve_typeid(value[0]);
|
|
114
|
+
for (let v of value) if (resolve_typeid(v) !== item_id) {
|
|
115
|
+
item_id = any_typeid;
|
|
116
|
+
break
|
|
117
|
+
}
|
|
118
|
+
if (item_id === arr_typeid || item_id === map_typeid) item_id = any_typeid;
|
|
119
|
+
encode_u8(buf, item_id);
|
|
120
|
+
return encode_arr(buf, value, (buf, v) => encode_value(buf, v, item_id));
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (value instanceof Map) {
|
|
124
|
+
let entry = value.entries().next().value;
|
|
125
|
+
let key_id = entry === undefined ? any_typeid : resolve_typeid(entry?.[0] as any);
|
|
126
|
+
let value_id = entry === undefined ? any_typeid : resolve_typeid(entry?.[1] as any);
|
|
127
|
+
|
|
128
|
+
for (let [k, _] of value) if (resolve_typeid(k) !== key_id) {
|
|
129
|
+
key_id = any_typeid;
|
|
130
|
+
break
|
|
131
|
+
}
|
|
132
|
+
for (let [_, v] of value) if (resolve_typeid(v) !== value_id) {
|
|
133
|
+
value_id = any_typeid;
|
|
134
|
+
break
|
|
135
|
+
}
|
|
136
|
+
if (value_id === arr_typeid || value_id === map_typeid) value_id = any_typeid;
|
|
137
|
+
|
|
138
|
+
encode_u8(buf, key_id);
|
|
139
|
+
encode_u8(buf, value_id);
|
|
140
|
+
return encode_map(buf, value,
|
|
141
|
+
(buf, k) => encode_value(buf, k, key_id),
|
|
142
|
+
(buf, v) => encode_value(buf, v, value_id)
|
|
143
|
+
)
|
|
144
|
+
}
|
|
145
|
+
}
|
package/src/buf.ts
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
export interface Buffer {
|
|
2
|
+
buf: Uint8Array,
|
|
3
|
+
view: DataView
|
|
4
|
+
pos: number
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface Cursor {
|
|
8
|
+
pos: number
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function reserve(buf: Buffer, add_size: number) {
|
|
12
|
+
let old_size = buf.buf.length
|
|
13
|
+
if (buf.pos + add_size > old_size) {
|
|
14
|
+
let new_size = old_size > 2 ** 20 ? old_size + 2 ** 10 : old_size * 2;
|
|
15
|
+
if (new_size < buf.pos + add_size) new_size = buf.pos + add_size;
|
|
16
|
+
let new_buf = new Uint8Array(new_size);
|
|
17
|
+
new_buf.set(buf.buf);
|
|
18
|
+
buf.buf = new_buf;
|
|
19
|
+
buf.view = new DataView(new_buf.buffer)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function encode_u8(buf: Buffer, value: number) {
|
|
24
|
+
reserve(buf, 1);
|
|
25
|
+
buf.buf[buf.pos] = value;
|
|
26
|
+
buf.pos += 1;
|
|
27
|
+
}
|
|
28
|
+
export function encode_u16(buf: Buffer, value: number) {
|
|
29
|
+
reserve(buf, 2);
|
|
30
|
+
buf.view.setUint16(buf.pos, value, true);
|
|
31
|
+
buf.pos += 2;
|
|
32
|
+
}
|
|
33
|
+
export function encode_u32(buf: Buffer, value: number) {
|
|
34
|
+
reserve(buf, 4);
|
|
35
|
+
buf.view.setUint32(buf.pos, value, true);
|
|
36
|
+
buf.pos += 4;
|
|
37
|
+
}
|
|
38
|
+
export function encode_u64(buf: Buffer, value: bigint) {
|
|
39
|
+
reserve(buf, 8);
|
|
40
|
+
buf.view.setBigUint64(buf.pos, value, true);
|
|
41
|
+
buf.pos += 8;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function encode_i8(buf: Buffer, value: number) {
|
|
45
|
+
reserve(buf, 1);
|
|
46
|
+
buf.view.setInt8(buf.pos, value);
|
|
47
|
+
buf.pos += 1;
|
|
48
|
+
}
|
|
49
|
+
export function encode_i16(buf: Buffer, value: number) {
|
|
50
|
+
reserve(buf, 2);
|
|
51
|
+
buf.view.setInt16(buf.pos, value, true);
|
|
52
|
+
buf.pos += 2;
|
|
53
|
+
}
|
|
54
|
+
export function encode_i32(buf: Buffer, value: number) {
|
|
55
|
+
reserve(buf, 4);
|
|
56
|
+
buf.view.setInt32(buf.pos, value, true);
|
|
57
|
+
buf.pos += 4;
|
|
58
|
+
}
|
|
59
|
+
export function encode_i64(buf: Buffer, value: bigint) {
|
|
60
|
+
reserve(buf, 8);
|
|
61
|
+
buf.view.setBigInt64(buf.pos, value, true);
|
|
62
|
+
buf.pos += 8;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function decode_u8(buf: Buffer, cur: Cursor) {
|
|
66
|
+
let res = buf.buf[cur.pos];
|
|
67
|
+
cur.pos += 1;
|
|
68
|
+
return res;
|
|
69
|
+
}
|
|
70
|
+
export function decode_u16(buf: Buffer, cur: Cursor) {
|
|
71
|
+
let res = buf.view.getUint16(cur.pos, true);
|
|
72
|
+
cur.pos += 2;
|
|
73
|
+
return res;
|
|
74
|
+
}
|
|
75
|
+
export function decode_u32(buf: Buffer, cur: Cursor) {
|
|
76
|
+
let res = buf.view.getUint32(cur.pos, true);
|
|
77
|
+
cur.pos += 4;
|
|
78
|
+
return res;
|
|
79
|
+
}
|
|
80
|
+
export function decode_u64(buf: Buffer, cur: Cursor) {
|
|
81
|
+
let res = buf.view.getBigUint64(cur.pos, true);
|
|
82
|
+
cur.pos += 8;
|
|
83
|
+
return res;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function decode_i8(buf: Buffer, cur: Cursor) {
|
|
87
|
+
let res = buf.view.getInt8(cur.pos);
|
|
88
|
+
cur.pos += 1;
|
|
89
|
+
return res;
|
|
90
|
+
}
|
|
91
|
+
export function decode_i16(buf: Buffer, cur: Cursor) {
|
|
92
|
+
let res = buf.view.getInt16(cur.pos, true);
|
|
93
|
+
cur.pos += 2;
|
|
94
|
+
return res;
|
|
95
|
+
}
|
|
96
|
+
export function decode_i32(buf: Buffer, cur: Cursor) {
|
|
97
|
+
let res = buf.view.getInt32(cur.pos, true);
|
|
98
|
+
cur.pos += 4;
|
|
99
|
+
return res;
|
|
100
|
+
}
|
|
101
|
+
export function decode_i64(buf: Buffer, cur: Cursor) {
|
|
102
|
+
let res = buf.view.getBigInt64(cur.pos, true);
|
|
103
|
+
cur.pos += 8;
|
|
104
|
+
return res;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function encode_u8_arr(buf: Buffer, value: ArrayLike<number>) {
|
|
108
|
+
reserve(buf, value.length);
|
|
109
|
+
buf.buf.set(value, buf.pos);
|
|
110
|
+
buf.pos += value.length;
|
|
111
|
+
}
|
|
112
|
+
export function decode_u8_arr(buf: Buffer, size: number, cur: Cursor) {
|
|
113
|
+
let res = buf.buf.slice(cur.pos, cur.pos + size);
|
|
114
|
+
cur.pos += size;
|
|
115
|
+
return res
|
|
116
|
+
}
|
package/src/general.ts
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { decode_u8, decode_u8_arr, encode_u8, encode_u8_arr, reserve, type Buffer, type Cursor } from "./buf.ts";
|
|
2
|
+
import { decode_vuint, encode_vuint } from "./number.ts";
|
|
3
|
+
|
|
4
|
+
export function encode_bool(buf: Buffer, value: boolean) {
|
|
5
|
+
encode_u8(buf, value === true ? 1 : 0)
|
|
6
|
+
}
|
|
7
|
+
export function decode_bool(buf: Buffer, cur: Cursor) {
|
|
8
|
+
return decode_u8(buf, cur) !== 0
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
let TextEnc = new TextEncoder();
|
|
12
|
+
export function encode_str(buf: Buffer, value: string) {
|
|
13
|
+
let res = TextEnc.encode(value);
|
|
14
|
+
encode_vuint(buf, res.length);
|
|
15
|
+
encode_u8_arr(buf, res);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let TextDec = new TextDecoder('utf-8');
|
|
19
|
+
export function decode_str (buf: Buffer, cur: Cursor) {
|
|
20
|
+
let size = decode_vuint(buf, cur) as number;
|
|
21
|
+
return TextDec.decode(decode_u8_arr(buf, size, cur));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
type Encoder <T> = (buf: Buffer, value: T) => void;
|
|
25
|
+
type Decoder <T> = (buf: Buffer, cur: Cursor) => T;
|
|
26
|
+
|
|
27
|
+
export function encode_arr<T> (buf: Buffer, value: T[], item_fn: Encoder<T>, in_field = false) {
|
|
28
|
+
if (!in_field)
|
|
29
|
+
encode_vuint(buf, value.length);
|
|
30
|
+
for (let val of value)
|
|
31
|
+
item_fn(buf, val);
|
|
32
|
+
}
|
|
33
|
+
export function decode_arr<T> (buf: Buffer, cur: Cursor, item_fn: Decoder<T>, in_field = false) {
|
|
34
|
+
let len = decode_vuint(buf, cur) as number;
|
|
35
|
+
if (in_field) {
|
|
36
|
+
let start_ind = cur.pos;
|
|
37
|
+
let arr: T[] = [];
|
|
38
|
+
while (cur.pos < start_ind + len)
|
|
39
|
+
arr.push(item_fn(buf, cur));
|
|
40
|
+
return arr
|
|
41
|
+
} else {
|
|
42
|
+
let arr: T[] = [];
|
|
43
|
+
for (let i = 0; i < len; i++)
|
|
44
|
+
arr.push(item_fn(buf, cur));
|
|
45
|
+
return arr
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function encode_map<K, V> (
|
|
50
|
+
buf: Buffer, value: Map<K, V>, key_fn: Encoder<K>, val_fn: Encoder<V>,
|
|
51
|
+
in_field = false
|
|
52
|
+
) {
|
|
53
|
+
if (!in_field)
|
|
54
|
+
encode_vuint(buf, value.size);
|
|
55
|
+
for (let [k, v] of value) {
|
|
56
|
+
key_fn(buf, k);
|
|
57
|
+
val_fn(buf, v);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
export function decode_map<K, V> (
|
|
61
|
+
buf: Buffer, cur: Cursor, key_fn: Decoder<K>, val_fn: Decoder<V>,
|
|
62
|
+
in_field = false
|
|
63
|
+
) {
|
|
64
|
+
let len = decode_vuint(buf, cur) as number;
|
|
65
|
+
if (in_field) {
|
|
66
|
+
let start_ind = cur.pos;
|
|
67
|
+
let map = new Map<K, V>();
|
|
68
|
+
while (cur.pos < start_ind + len)
|
|
69
|
+
map.set(key_fn(buf, cur), val_fn(buf, cur));
|
|
70
|
+
return map
|
|
71
|
+
} else {
|
|
72
|
+
let map = new Map<K, V>();
|
|
73
|
+
for (let i = 0; i < len; i++) {
|
|
74
|
+
map.set(key_fn(buf, cur), val_fn(buf, cur));}
|
|
75
|
+
return map
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function skip_field (buf: Buffer, cur: Cursor, header: number) {
|
|
80
|
+
switch (header & 0b111) {
|
|
81
|
+
case 0b000: cur.pos += 1; break;
|
|
82
|
+
case 0b001: cur.pos += 2; break;
|
|
83
|
+
case 0b010: cur.pos += 4; break;
|
|
84
|
+
case 0b011: cur.pos += 8; break;
|
|
85
|
+
// decode vuint and ignore
|
|
86
|
+
case 0b100: decode_vuint(buf, cur); break;
|
|
87
|
+
// len field is encoded
|
|
88
|
+
case 0b101: cur.pos += decode_vuint(buf, cur) as number;
|
|
89
|
+
}
|
|
90
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { decode_any, encode_any } from "./any.ts";
|
|
2
|
+
import { decode_u8, encode_u8, type Buffer, type Cursor } from "./buf.ts";
|
|
3
|
+
|
|
4
|
+
export interface UUID {
|
|
5
|
+
type: 'uuid',
|
|
6
|
+
value: Uint8Array
|
|
7
|
+
};
|
|
8
|
+
export interface Dur {
|
|
9
|
+
type: 'dur',
|
|
10
|
+
value: bigint
|
|
11
|
+
}
|
|
12
|
+
export type Value =
|
|
13
|
+
boolean | number | string | bigint | Date | UUID | Dur | Array<Value> | Map<Value, Value>;
|
|
14
|
+
|
|
15
|
+
export function encode(value: Value) {
|
|
16
|
+
let _buf = new Uint8Array(256);
|
|
17
|
+
let buf: Buffer = { buf: _buf, pos: 0, view: new DataView(_buf.buffer) };
|
|
18
|
+
encode_u8(buf, 0);
|
|
19
|
+
encode_any(buf, value);
|
|
20
|
+
return buf.buf.slice(0, buf.pos);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function decode(data: ArrayBuffer) {
|
|
24
|
+
let buf: Buffer = { buf: new Uint8Array(data), pos: 0, view: new DataView(data) };
|
|
25
|
+
let cur: Cursor = { pos: 0 };
|
|
26
|
+
if (decode_u8(buf, cur) !== 0) return;
|
|
27
|
+
let value = decode_any(buf, cur);
|
|
28
|
+
if (cur.pos !== data.byteLength) return;
|
|
29
|
+
return value;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export * from './any.ts';
|
|
33
|
+
export * from './general.ts';
|
|
34
|
+
export * from './number.ts';
|
|
35
|
+
export * from './rich.ts';
|
|
36
|
+
export {
|
|
37
|
+
decode_i8, decode_i16, decode_i32, decode_i64, decode_u8, decode_u16, decode_u32, decode_u64,
|
|
38
|
+
decode_u8_arr, encode_i8, encode_i16, encode_i32, encode_i64, encode_u8, encode_u16, encode_u32,
|
|
39
|
+
encode_u64, encode_u8_arr
|
|
40
|
+
} from './buf.ts';
|
package/src/number.ts
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { decode_u8, encode_u8, reserve, type Buffer, type Cursor } from "./buf.ts";
|
|
2
|
+
|
|
3
|
+
export function encode_f32 (buf: Buffer, value: number) {
|
|
4
|
+
reserve(buf, 4);
|
|
5
|
+
buf.view.setFloat32(buf.pos, value, true);
|
|
6
|
+
buf.pos += 4;
|
|
7
|
+
}
|
|
8
|
+
export function encode_f64 (buf: Buffer, value: number) {
|
|
9
|
+
reserve(buf, 8);
|
|
10
|
+
buf.view.setFloat64(buf.pos, value, true);
|
|
11
|
+
buf.pos += 8;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function decode_f32 (buf: Buffer, cur: Cursor) {
|
|
15
|
+
let res = buf.view.getFloat32(cur.pos, true);
|
|
16
|
+
cur.pos += 4;
|
|
17
|
+
return res
|
|
18
|
+
}
|
|
19
|
+
export function decode_f64 (buf: Buffer, cur: Cursor) {
|
|
20
|
+
let res = buf.view.getFloat64(cur.pos, true);
|
|
21
|
+
cur.pos += 8;
|
|
22
|
+
return res
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function encode_vuint(buf: Buffer, value: number | bigint) {
|
|
26
|
+
let cond = true;
|
|
27
|
+
|
|
28
|
+
if (typeof(value) === 'number' && Math.abs(value) < 2 ** 31) {
|
|
29
|
+
// while there is input
|
|
30
|
+
while (cond) {
|
|
31
|
+
// extract least significant 7 bits
|
|
32
|
+
let byte = value & 0b0111_1111;
|
|
33
|
+
// shift to next section
|
|
34
|
+
value >>= 7;
|
|
35
|
+
// add continuation bit (0 = end byte)
|
|
36
|
+
encode_u8(buf, value == 0 ? byte : byte | 0b1000_0000 );
|
|
37
|
+
|
|
38
|
+
cond = value != 0;
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
value = BigInt(value);
|
|
42
|
+
// while there is input
|
|
43
|
+
while (cond) {
|
|
44
|
+
// extract least significant 7 bits
|
|
45
|
+
let byte = Number(value & 0b0111_1111n);
|
|
46
|
+
// shift to next section
|
|
47
|
+
value >>= 7n;
|
|
48
|
+
// add continuation bit (0 = end byte)
|
|
49
|
+
encode_u8(buf, value == 0n ? byte : byte | 0b1000_0000 );
|
|
50
|
+
|
|
51
|
+
cond = value != 0n;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export function encode_vint(buf: Buffer, value: number | bigint) {
|
|
56
|
+
let cond = true;
|
|
57
|
+
|
|
58
|
+
if (typeof(value) === 'number' && Math.abs(value) < 2 ** 31) {
|
|
59
|
+
// while there is input
|
|
60
|
+
while (cond) {
|
|
61
|
+
// extract least significant 7 bits
|
|
62
|
+
let byte = value & 0b0111_1111;
|
|
63
|
+
// shift to next section
|
|
64
|
+
value >>= 7;
|
|
65
|
+
// ensure at least 1 sign bit is encoded (0 for positive and 1 for negative)
|
|
66
|
+
let sign_bit = byte & 0b0100_0000;
|
|
67
|
+
if ((value == 0 && sign_bit == 0) || (value == -1 && sign_bit != 0))
|
|
68
|
+
cond = false;
|
|
69
|
+
// add continuation bit (0 = end byte)
|
|
70
|
+
else byte |= 0b1000_0000;
|
|
71
|
+
// add continuation bit (0 = end byte)
|
|
72
|
+
encode_u8(buf, byte);
|
|
73
|
+
}
|
|
74
|
+
} else {
|
|
75
|
+
value = BigInt(value);
|
|
76
|
+
// while there is input
|
|
77
|
+
while (cond) {
|
|
78
|
+
// extract least significant 7 bits
|
|
79
|
+
let byte = Number(value & 0b0111_1111n);
|
|
80
|
+
// shift to next section
|
|
81
|
+
value >>= 7n;
|
|
82
|
+
// ensure at least 1 sign bit is encoded (0 for positive and 1 for negative)
|
|
83
|
+
let sign_bit = byte & 0b0100_0000;
|
|
84
|
+
if ((value == 0n && sign_bit == 0) || (value == -1n && sign_bit != 0))
|
|
85
|
+
cond = false;
|
|
86
|
+
// add continuation bit (0 = end byte)
|
|
87
|
+
else byte |= 0b1000_0000;
|
|
88
|
+
// add continuation bit (0 = end byte)
|
|
89
|
+
encode_u8(buf, byte);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function decode_vuint (buf: Buffer, cur: Cursor) {
|
|
95
|
+
let res = 0n, shift = 0n, cond = true;
|
|
96
|
+
|
|
97
|
+
// while there is input
|
|
98
|
+
while (cond) {
|
|
99
|
+
let byte = decode_u8(buf, cur);
|
|
100
|
+
// add the least significant 7 bits to the next section of the result
|
|
101
|
+
res |= BigInt(byte & 0b0111_1111) << shift;
|
|
102
|
+
// next section
|
|
103
|
+
shift += 7n;
|
|
104
|
+
// if the continuation bit is set, continue
|
|
105
|
+
cond = (byte & 0b1000_0000) != 0;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return res > 2 ** 50 ? res : Number(res);
|
|
109
|
+
}
|
|
110
|
+
export function decode_vint(buf: Buffer, cur: Cursor) {
|
|
111
|
+
let res = 0n, shift = 0n, cond = true, byte = 0;
|
|
112
|
+
|
|
113
|
+
// while there is input
|
|
114
|
+
while (cond) {
|
|
115
|
+
byte = decode_u8(buf, cur);
|
|
116
|
+
// add the least significant 7 bits to the next section of the result
|
|
117
|
+
res |= BigInt(byte & 0b0111_1111) << shift;
|
|
118
|
+
// next section
|
|
119
|
+
shift += 7n;
|
|
120
|
+
// if the continuation bit is set, continue
|
|
121
|
+
cond = (byte & 0b1000_0000) != 0;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// if the value is neg, sign extend it
|
|
125
|
+
if ((shift < 64n) && ((byte & 0b0100_0000) !== 0)) {
|
|
126
|
+
res |= ~0n << shift;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return (res > 0 ? res : -res) > 2 ** 50 ? res : Number(res);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function encode_vuint_pre_aloc(
|
|
133
|
+
buf: Buffer, value: number, start_ind: number, pre_aloc: number
|
|
134
|
+
) {
|
|
135
|
+
let nb_buf = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
136
|
+
let size = 0, cond = true;
|
|
137
|
+
|
|
138
|
+
while (cond) {
|
|
139
|
+
// extract least significant 7 bits
|
|
140
|
+
let byte = value & 0b0111_1111;
|
|
141
|
+
// shift to next section
|
|
142
|
+
value >>= 7;
|
|
143
|
+
// add continuation bit (0 = end byte)
|
|
144
|
+
nb_buf[size] = value == 0 ? byte : byte | 0b1000_0000 ;
|
|
145
|
+
|
|
146
|
+
cond = value != 0;
|
|
147
|
+
size += 1;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// case size is larger than pre allocated space, expand to fit
|
|
151
|
+
if (size > pre_aloc) {
|
|
152
|
+
let len = buf.pos;
|
|
153
|
+
reserve(buf, size - pre_aloc);
|
|
154
|
+
buf.buf.copyWithin(start_ind + size, start_ind + pre_aloc, len);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// set continuation bits in all pre allocated area, even if not used, making it padding
|
|
158
|
+
if (size < pre_aloc) {
|
|
159
|
+
for (let i = 0; i < pre_aloc - 1; i++) {
|
|
160
|
+
nb_buf[i] |= 0b1000_0000
|
|
161
|
+
}
|
|
162
|
+
size = pre_aloc;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
for (let ind = 0; ind < size; ind++) buf.buf[ind + start_ind] = nb_buf[ind];
|
|
166
|
+
}
|
package/src/rich.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { decode_i64, decode_u32, decode_u8_arr, encode_i64, encode_u32, encode_u8_arr, type Buffer, type Cursor } from "./buf.ts";
|
|
2
|
+
import type { Dur, UUID } from "./index.ts";
|
|
3
|
+
|
|
4
|
+
export function encode_uuid (buf: Buffer, value: UUID) {
|
|
5
|
+
encode_u8_arr(buf, value.value);
|
|
6
|
+
}
|
|
7
|
+
export function decode_uuid (buf: Buffer, cur: Cursor) {
|
|
8
|
+
return { type: 'uuid', value: decode_u8_arr(buf, 16, cur) } satisfies UUID
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function encode_inst(buf: Buffer, value: Date) {
|
|
12
|
+
encode_i64(buf, BigInt(Number(value)))
|
|
13
|
+
}
|
|
14
|
+
export function encode_instN(buf: Buffer, value: Date) {
|
|
15
|
+
encode_i64(buf, BigInt(Number(value)))
|
|
16
|
+
encode_u32(buf, 0)
|
|
17
|
+
}
|
|
18
|
+
export function decode_inst(buf: Buffer, cur: Cursor) {
|
|
19
|
+
return new Date(Number(decode_i64(buf, cur)))
|
|
20
|
+
}
|
|
21
|
+
export function decode_instN(buf: Buffer, cur: Cursor) {
|
|
22
|
+
let res = decode_i64(buf, cur);
|
|
23
|
+
decode_u32(buf, cur);
|
|
24
|
+
return new Date(Number(res))
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function encode_dur(buf: Buffer, value: Dur) {
|
|
28
|
+
encode_i64(buf, value.value)
|
|
29
|
+
}
|
|
30
|
+
export function decode_dur(buf: Buffer, cur: Cursor) {
|
|
31
|
+
return { type: 'dur', value: decode_i64(buf, cur) } satisfies Dur
|
|
32
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"esModuleInterop": true,
|
|
4
|
+
"skipLibCheck": true,
|
|
5
|
+
"target": "esnext",
|
|
6
|
+
"allowJs": true,
|
|
7
|
+
"resolveJsonModule": true,
|
|
8
|
+
"moduleDetection": "force",
|
|
9
|
+
"moduleResolution": "bundler",
|
|
10
|
+
"isolatedModules": true,
|
|
11
|
+
"verbatimModuleSyntax": true,
|
|
12
|
+
"strict": true,
|
|
13
|
+
"allowImportingTsExtensions": true,
|
|
14
|
+
"noImplicitOverride": true,
|
|
15
|
+
"module": "preserve",
|
|
16
|
+
"noEmit": true,
|
|
17
|
+
"lib": ["esnext", "dom"],
|
|
18
|
+
},
|
|
19
|
+
"include": ["src/**/*"],
|
|
20
|
+
}
|