@thi.ng/leb128 3.0.5 → 3.0.8
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/CHANGELOG.md +1 -1
- package/package.json +12 -11
- package/zig/leb128.zig +132 -0
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/leb128",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.8",
|
|
4
4
|
"description": "WASM based LEB128 encoder / decoder (signed & unsigned)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -35,17 +35,17 @@
|
|
|
35
35
|
"test": "testament test"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@thi.ng/checks": "^3.3.
|
|
39
|
-
"@thi.ng/errors": "^2.2.
|
|
40
|
-
"@thi.ng/transducers-binary": "^2.1.
|
|
38
|
+
"@thi.ng/checks": "^3.3.9",
|
|
39
|
+
"@thi.ng/errors": "^2.2.11",
|
|
40
|
+
"@thi.ng/transducers-binary": "^2.1.38"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@microsoft/api-extractor": "^7.
|
|
44
|
-
"@thi.ng/testament": "^0.3.
|
|
45
|
-
"rimraf": "^
|
|
43
|
+
"@microsoft/api-extractor": "^7.34.2",
|
|
44
|
+
"@thi.ng/testament": "^0.3.11",
|
|
45
|
+
"rimraf": "^4.1.2",
|
|
46
46
|
"tools": "^0.0.1",
|
|
47
|
-
"typedoc": "^0.23.
|
|
48
|
-
"typescript": "^4.9.
|
|
47
|
+
"typedoc": "^0.23.24",
|
|
48
|
+
"typescript": "^4.9.5"
|
|
49
49
|
},
|
|
50
50
|
"keywords": [
|
|
51
51
|
"64bit",
|
|
@@ -69,7 +69,8 @@
|
|
|
69
69
|
},
|
|
70
70
|
"files": [
|
|
71
71
|
"./*.js",
|
|
72
|
-
"./*.d.ts"
|
|
72
|
+
"./*.d.ts",
|
|
73
|
+
"zig"
|
|
73
74
|
],
|
|
74
75
|
"exports": {
|
|
75
76
|
".": {
|
|
@@ -79,5 +80,5 @@
|
|
|
79
80
|
"thi.ng": {
|
|
80
81
|
"year": 2019
|
|
81
82
|
},
|
|
82
|
-
"gitHead": "
|
|
83
|
+
"gitHead": "cafa4ecea90fb681949dc3885a5bd6ddefa38b51\n"
|
|
83
84
|
}
|
package/zig/leb128.zig
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
export var buf: [10]u8 = undefined;
|
|
2
|
+
|
|
3
|
+
/// Encodes 64bit uint `src` and writes result bytes into `dest` (must
|
|
4
|
+
/// have at least 10 bytes capacity)
|
|
5
|
+
pub fn leb128EncodeU(src: u64, dest: []u8) u8 {
|
|
6
|
+
if (src < 0x80) {
|
|
7
|
+
dest[0] = @intCast(u8, src & 0x7f);
|
|
8
|
+
return 1;
|
|
9
|
+
}
|
|
10
|
+
var n: u8 = 0;
|
|
11
|
+
var x: u64 = src;
|
|
12
|
+
while (true) {
|
|
13
|
+
var byte: u8 = @intCast(u8, x & 0x7f);
|
|
14
|
+
x = x >> 7;
|
|
15
|
+
if (x != 0) {
|
|
16
|
+
byte |= 0x80;
|
|
17
|
+
}
|
|
18
|
+
dest[n] = byte;
|
|
19
|
+
n += 1;
|
|
20
|
+
if (x == 0) break;
|
|
21
|
+
}
|
|
22
|
+
return n;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/// Decodes LEB128 bytes in `src` as u64 and writes number of bytes
|
|
26
|
+
/// consumed into `num`.
|
|
27
|
+
pub fn leb128DecodeU(src: []u8, num: *u8) u64 {
|
|
28
|
+
var res: u64 = 0;
|
|
29
|
+
var shift: u6 = 0;
|
|
30
|
+
var n: u8 = 0;
|
|
31
|
+
while (n < 10) {
|
|
32
|
+
var byte = src[n];
|
|
33
|
+
res |= @intCast(u64, byte & 0x7f) << shift;
|
|
34
|
+
shift += 7;
|
|
35
|
+
n += 1;
|
|
36
|
+
if (byte < 0x80) {
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
num.* = n;
|
|
41
|
+
return res;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/// Like `leb128EncodeU` but for signed integers
|
|
45
|
+
pub fn leb128EncodeI(src: i64, dest: []u8) u8 {
|
|
46
|
+
const neg: bool = src < 0;
|
|
47
|
+
if (src >= -64 and src < 64) {
|
|
48
|
+
dest[0] = @intCast(u8, src & 0x3f) |
|
|
49
|
+
@intCast(u8, @boolToInt(neg)) << 6;
|
|
50
|
+
return 1;
|
|
51
|
+
}
|
|
52
|
+
var n: u8 = 0;
|
|
53
|
+
var x: i64 = src;
|
|
54
|
+
var more: bool = true;
|
|
55
|
+
while (more) {
|
|
56
|
+
var byte: u8 = @intCast(u8, x & 0x7f);
|
|
57
|
+
var sign: bool = (byte & 0x40) > 0;
|
|
58
|
+
x >>= 7;
|
|
59
|
+
if ((x == 0 and !sign) or (x == -1 and sign)) {
|
|
60
|
+
more = false;
|
|
61
|
+
} else {
|
|
62
|
+
byte |= 0x80;
|
|
63
|
+
}
|
|
64
|
+
dest[n] = byte;
|
|
65
|
+
n += 1;
|
|
66
|
+
}
|
|
67
|
+
return n;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/// Like `leb128DecodeU` but for signed integers
|
|
71
|
+
pub fn leb128DecodeI(src: []u8, num: *u8) i64 {
|
|
72
|
+
var res: i64 = 0;
|
|
73
|
+
var shift: u6 = 0;
|
|
74
|
+
var n: u8 = 0;
|
|
75
|
+
var byte: u8 = 0;
|
|
76
|
+
while (true) {
|
|
77
|
+
byte = src[n];
|
|
78
|
+
res |= @intCast(i64, byte & 0x7f) << shift;
|
|
79
|
+
shift += 7;
|
|
80
|
+
n += 1;
|
|
81
|
+
if ((byte & 0x80) == 0 or n > 9) {
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (n < 10 and (byte & 0x40) > 0) {
|
|
86
|
+
res |= @intCast(i64, -1) << shift;
|
|
87
|
+
}
|
|
88
|
+
num.* = n;
|
|
89
|
+
return res;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/// WASM only. JS interop to exchange data via f64 (for lack of i64/u64
|
|
93
|
+
/// on JS side). Writes results to exported `buf` array and returns
|
|
94
|
+
/// number of bytes used.
|
|
95
|
+
export fn leb128EncodeU64(x: u64) u8 {
|
|
96
|
+
return leb128EncodeU(x, buf[0..]);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/// WASM only. JS interop to exchange data via f64 (for lack of i64/u64
|
|
100
|
+
/// on JS side). Consumes bytes from the exported `buf` array and returns
|
|
101
|
+
/// decoded value. Writes number of bytes consumed into `buf[0]`
|
|
102
|
+
export fn leb128DecodeU64() u64 {
|
|
103
|
+
return leb128DecodeU(buf[0..], &buf[0]);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/// See `leb128_encode_u_js`
|
|
107
|
+
export fn leb128EncodeI64(x: i64) u8 {
|
|
108
|
+
return leb128EncodeI(x, buf[0..]);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/// See `leb128_decode_u_js`
|
|
112
|
+
export fn leb128DecodeI64() i64 {
|
|
113
|
+
return leb128DecodeI(buf[0..], &buf[0]);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const std = @import("std");
|
|
117
|
+
const warn = std.debug.warn;
|
|
118
|
+
const assert = std.debug.assert;
|
|
119
|
+
const mem = std.mem;
|
|
120
|
+
|
|
121
|
+
test "min safe integer" {
|
|
122
|
+
assert(leb128EncodeI(-9007199254740991, buf[0..]) == 8);
|
|
123
|
+
assert(mem.eql(u8, buf[0..8], &[_]u8{ 129, 128, 128, 128, 128, 128, 128, 112 }));
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
test "max safe integer" {
|
|
127
|
+
assert(leb128EncodeI(9007199254740991, buf[0..]) == 8);
|
|
128
|
+
assert(mem.eql(u8, buf[0..8], &[_]u8{ 255, 255, 255, 255, 255, 255, 255, 15 }));
|
|
129
|
+
|
|
130
|
+
assert(leb128EncodeU(9007199254740991, buf[0..]) == 8);
|
|
131
|
+
assert(mem.eql(u8, buf[0..8], &[_]u8{ 255, 255, 255, 255, 255, 255, 255, 15 }));
|
|
132
|
+
}
|