Skip to content

Commit a54ca91

Browse files
feat(binary): add DATAVIEW and IDataView
1 parent 0c9644a commit a54ca91

File tree

3 files changed

+195
-0
lines changed

3 files changed

+195
-0
lines changed

packages/binary/src/buffers.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// thing:no-export
2+
export const F64 = new Float64Array(1);
3+
export const F32 = new Float32Array(F64.buffer);
4+
export const I8 = new Uint8Array(F64.buffer);
5+
export const U8 = new Uint8Array(F64.buffer);
6+
export const U16 = new Uint16Array(F64.buffer);
7+
export const U32 = new Uint32Array(F64.buffer);
8+
export const I16 = new Int32Array(F64.buffer);
9+
export const I32 = new Int32Array(F64.buffer);

packages/binary/src/endianess.ts

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
import type { NumericArray, TypedArray } from "@thi.ng/api";
2+
import { F32, F64, I16, I32, I8, U16, U32, U8 } from "./buffers.js";
3+
4+
/**
5+
* JS native DataView-like functionality, but tailored for using `Uint8Array` or
6+
* vanilla JS numeric arrays (assuming the array contains U8 values). Use
7+
* {@link DATAVIEW} for default implementation.
8+
*
9+
* @remarks
10+
* The default byte ordering used for all accessors is Little Endian, but can be
11+
* overriden via `isLE` args.
12+
*
13+
* **IMPORTANT:** None of the operations perform any bounds checking.
14+
*/
15+
export interface IDataView {
16+
getI8(data: ArrayLike<number>, addr: number, isLE?: boolean): number;
17+
getU8(data: ArrayLike<number>, addr: number, isLE?: boolean): number;
18+
19+
getI16(data: ArrayLike<number>, addr: number, isLE?: boolean): number;
20+
getU16(data: ArrayLike<number>, addr: number, isLE?: boolean): number;
21+
22+
getI32(data: ArrayLike<number>, addr: number, isLE?: boolean): number;
23+
getU32(data: ArrayLike<number>, addr: number, isLE?: boolean): number;
24+
25+
getF32(data: ArrayLike<number>, addr: number, isLE?: boolean): number;
26+
getF64(data: ArrayLike<number>, addr: number, isLE?: boolean): number;
27+
28+
setI8(data: NumericArray, addr: number, val: number, isLE?: boolean): void;
29+
setU8(data: NumericArray, addr: number, val: number, isLE?: boolean): void;
30+
31+
setI16(data: NumericArray, addr: number, val: number, isLE?: boolean): void;
32+
setU16(data: NumericArray, addr: number, val: number, isLE?: boolean): void;
33+
34+
setI32(data: NumericArray, addr: number, val: number, isLE?: boolean): void;
35+
setU32(data: NumericArray, addr: number, val: number, isLE?: boolean): void;
36+
37+
setF32(data: NumericArray, addr: number, val: number, isLE?: boolean): void;
38+
setF64(data: NumericArray, addr: number, val: number, isLE?: boolean): void;
39+
}
40+
41+
/**
42+
* Indicator flag if current runtime/platform uses Little Endian byte order.
43+
*/
44+
export const IS_LE = ((U32[0] = 1), U8[0] === 1);
45+
46+
/**
47+
* {@link IDataView} implementation for Big Endian access.
48+
*
49+
* @remarks
50+
* **IMPORTANT:** None of the operations perform any bounds checking.
51+
*/
52+
export const DATAVIEW: IDataView = {
53+
getI8: (src, i) => ((I8[0] = src[i]), I8[0]),
54+
getU8: (src, i) => src[i] & 0xff,
55+
56+
getI16: (src, i, isLE) => __get2(src, i, I16, isLE),
57+
getU16: (src, i, isLE) => __get2(src, i, U16, isLE),
58+
59+
getI32: (src, i, isLE) => __get4(src, i, I32, isLE),
60+
getU32: (src, i, isLE) => __get4(src, i, U32, isLE) >>> 0,
61+
62+
getF32: (src, i, isLE) => __get4(src, i, F32, isLE),
63+
getF64: (src, i, isLE) => __get8(src, i, F64, isLE),
64+
65+
setI8: (data, addr, x) => {
66+
I8[0] = x;
67+
data[addr] = U8[0];
68+
},
69+
setU8: (data, addr, x) => {
70+
data[addr] = x & 0xff;
71+
},
72+
73+
setI16: (data, addr, x, isLE) => {
74+
I16[0] = x;
75+
__set2(data, addr, isLE);
76+
},
77+
setU16: (data, addr, x, isLE) => {
78+
U16[0] = x;
79+
__set2(data, addr, isLE);
80+
},
81+
82+
setI32: (data, addr, x, isLE) => {
83+
I32[0] = x;
84+
__set4(data, addr, isLE);
85+
},
86+
setU32: (data, addr, x, isLE) => {
87+
U32[0] = x;
88+
__set4(data, addr, isLE);
89+
},
90+
91+
setF32: (data, addr, x, isLE) => {
92+
F32[0] = x;
93+
__set4(data, addr, isLE);
94+
},
95+
setF64: (data, addr, x, isLE) => {
96+
F64[0] = x;
97+
__set8(data, addr, isLE);
98+
},
99+
};
100+
101+
const __get2 = (
102+
src: ArrayLike<number>,
103+
i: number,
104+
view: TypedArray,
105+
isLE = true
106+
) =>
107+
isLE !== IS_LE
108+
? ((U8[1] = src[i]), (U8[0] = src[i + 1]), view[0])
109+
: ((U8[0] = src[i]), (U8[1] = src[i + 1]), view[0]);
110+
111+
const __get4 = (
112+
src: ArrayLike<number>,
113+
i: number,
114+
view: TypedArray,
115+
isLE = true
116+
) =>
117+
isLE !== IS_LE
118+
? ((U8[3] = src[i]),
119+
(U8[2] = src[i + 1]),
120+
(U8[1] = src[i + 2]),
121+
(U8[0] = src[i + 3]),
122+
view[0])
123+
: ((U8[0] = src[i]),
124+
(U8[1] = src[i + 1]),
125+
(U8[2] = src[i + 2]),
126+
(U8[3] = src[i + 3]),
127+
view[0]);
128+
129+
const __get8 = (
130+
src: ArrayLike<number>,
131+
i: number,
132+
view: TypedArray,
133+
isLE = true
134+
) =>
135+
isLE !== IS_LE
136+
? ((U8[7] = src[i]),
137+
(U8[6] = src[i + 1]),
138+
(U8[5] = src[i + 2]),
139+
(U8[4] = src[i + 3]),
140+
(U8[3] = src[i + 4]),
141+
(U8[2] = src[i + 5]),
142+
(U8[1] = src[i + 6]),
143+
(U8[0] = src[i + 7]),
144+
view[0])
145+
: ((U8[0] = src[i]),
146+
(U8[1] = src[i + 1]),
147+
(U8[2] = src[i + 2]),
148+
(U8[3] = src[i + 3]),
149+
(U8[4] = src[i + 4]),
150+
(U8[5] = src[i + 5]),
151+
(U8[6] = src[i + 6]),
152+
(U8[7] = src[i + 7]),
153+
view[0]);
154+
155+
const __set2 = (data: NumericArray, addr: number, isLE = true) => {
156+
if (isLE !== IS_LE) {
157+
data[addr] = U8[1];
158+
data[addr + 1] = U8[0];
159+
} else {
160+
data[addr] = U8[0];
161+
data[addr + 1] = U8[1];
162+
}
163+
};
164+
165+
const __set4 = (data: NumericArray, addr: number, isLE = true) => {
166+
if (isLE !== IS_LE) {
167+
data[addr] = U8[3];
168+
data[addr + 1] = U8[2];
169+
data[addr + 2] = U8[1];
170+
data[addr + 3] = U8[0];
171+
} else {
172+
data[addr] = U8[0];
173+
data[addr + 1] = U8[1];
174+
data[addr + 2] = U8[2];
175+
data[addr + 3] = U8[3];
176+
}
177+
};
178+
179+
const __set8 = (data: NumericArray, addr: number, isLE = true) => {
180+
if (isLE !== IS_LE) {
181+
for (let i = 0; i < 8; i++) data[addr + i] = U8[7 - i];
182+
} else {
183+
for (let i = 0; i < 8; i++) data[addr + i] = U8[i];
184+
}
185+
};

packages/binary/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export * from "./bytes.js";
55
export * from "./constants.js";
66
export * from "./count.js";
77
export * from "./edit.js";
8+
export * from "./endianess.js";
89
export * from "./float.js";
910
export * from "./gray.js";
1011
export * from "./int.js";

0 commit comments

Comments
 (0)