Skip to content

Commit 9dd684e

Browse files
authored
Merge pull request #13 from jsonjoy-com/buffers
Buffers
2 parents ad9788e + 627923e commit 9dd684e

57 files changed

Lines changed: 64 additions & 2344 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@
5757
"peerDependencies": {
5858
"tslib": "2"
5959
},
60-
"dependencies": {},
60+
"dependencies": {
61+
"@jsonjoy.com/buffers": "^1.0.0"
62+
},
6163
"devDependencies": {
6264
"@types/benchmark": "^2.1.2",
6365
"@types/jest": "^29.5.12",

src/buffers/Reader.ts

Lines changed: 1 addition & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -1,115 +1 @@
1-
import {decodeUtf8} from './utf8/decodeUtf8';
2-
import type {IReader, IReaderResettable} from './types';
3-
4-
export class Reader implements IReader, IReaderResettable {
5-
public uint8 = new Uint8Array([]);
6-
public view = new DataView(this.uint8.buffer);
7-
public x = 0;
8-
9-
public reset(uint8: Uint8Array): void {
10-
this.x = 0;
11-
this.uint8 = uint8;
12-
this.view = new DataView(uint8.buffer, uint8.byteOffset, uint8.length);
13-
}
14-
15-
/**
16-
* Get current byte value without advancing the cursor.
17-
*/
18-
public peek(): number {
19-
return this.view.getUint8(this.x);
20-
}
21-
22-
/**
23-
* @deprecated Use peek() instead.
24-
*/
25-
public peak(): number {
26-
return this.peek();
27-
}
28-
29-
public skip(length: number): void {
30-
this.x += length;
31-
}
32-
33-
public buf(size: number): Uint8Array {
34-
const end = this.x + size;
35-
const bin = this.uint8.subarray(this.x, end);
36-
this.x = end;
37-
return bin;
38-
}
39-
40-
public u8(): number {
41-
return this.uint8[this.x++];
42-
// return this.view.getUint8(this.x++);
43-
}
44-
45-
public i8(): number {
46-
return this.view.getInt8(this.x++);
47-
}
48-
49-
public u16(): number {
50-
// const num = this.view.getUint16(this.x);
51-
// this.x += 2;
52-
// return num;
53-
let x = this.x;
54-
const num = (this.uint8[x++] << 8) + this.uint8[x++];
55-
this.x = x;
56-
return num;
57-
}
58-
59-
public i16(): number {
60-
const num = this.view.getInt16(this.x);
61-
this.x += 2;
62-
return num;
63-
}
64-
65-
public u32(): number {
66-
const num = this.view.getUint32(this.x);
67-
this.x += 4;
68-
return num;
69-
}
70-
71-
public i32(): number {
72-
const num = this.view.getInt32(this.x);
73-
this.x += 4;
74-
return num;
75-
}
76-
77-
public u64(): bigint {
78-
const num = this.view.getBigUint64(this.x);
79-
this.x += 8;
80-
return num;
81-
}
82-
83-
public i64(): bigint {
84-
const num = this.view.getBigInt64(this.x);
85-
this.x += 8;
86-
return num;
87-
}
88-
89-
public f32(): number {
90-
const pos = this.x;
91-
this.x += 4;
92-
return this.view.getFloat32(pos);
93-
}
94-
95-
public f64(): number {
96-
const pos = this.x;
97-
this.x += 8;
98-
return this.view.getFloat64(pos);
99-
}
100-
101-
public utf8(size: number): string {
102-
const start = this.x;
103-
this.x += size;
104-
return decodeUtf8(this.uint8, start, size);
105-
}
106-
107-
public ascii(length: number): string {
108-
const uint8 = this.uint8;
109-
let str = '';
110-
const end = this.x + length;
111-
for (let i = this.x; i < end; i++) str += String.fromCharCode(uint8[i]);
112-
this.x = end;
113-
return str;
114-
}
115-
}
1+
export * from '@jsonjoy.com/buffers/lib/Reader';

src/buffers/Slice.ts

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1 @@
1-
export class Slice {
2-
constructor(
3-
public readonly uint8: Uint8Array,
4-
public readonly view: DataView,
5-
public readonly start: number,
6-
public readonly end: number,
7-
) {}
8-
9-
public subarray(): Uint8Array {
10-
return this.uint8.subarray(this.start, this.end);
11-
}
12-
}
1+
export * from '@jsonjoy.com/buffers/lib/Slice';
Lines changed: 1 addition & 183 deletions
Original file line numberDiff line numberDiff line change
@@ -1,183 +1 @@
1-
const fromCharCode = String.fromCharCode;
2-
3-
export class StreamingOctetReader {
4-
protected readonly chunks: Uint8Array[] = [];
5-
6-
/** Total size of all chunks. */
7-
protected chunkSize: number = 0;
8-
9-
protected x: number = 0;
10-
11-
public size(): number {
12-
return this.chunkSize - this.x;
13-
}
14-
15-
public push(chunk: Uint8Array): void {
16-
this.chunks.push(chunk);
17-
this.chunkSize += chunk.length;
18-
}
19-
20-
protected assertSize(size: number): void {
21-
if (size > this.size()) throw new RangeError('OUT_OF_BOUNDS');
22-
}
23-
24-
public u8(): number {
25-
this.assertSize(1);
26-
const chunk = this.chunks[0]!;
27-
let x = this.x;
28-
const octet = chunk[x++];
29-
if (x === chunk.length) {
30-
this.chunks.shift();
31-
this.chunkSize -= chunk.length;
32-
x = 0;
33-
}
34-
this.x = x;
35-
return octet;
36-
}
37-
38-
public u32(): number {
39-
const octet0 = this.u8();
40-
const octet1 = this.u8();
41-
const octet2 = this.u8();
42-
const octet3 = this.u8();
43-
return (octet0 * 0x1000000 + (octet1 << 16) + (octet2 << 8)) | octet3;
44-
}
45-
46-
public copy(size: number, dst: Uint8Array, pos: number): void {
47-
if (!size) return;
48-
this.assertSize(size);
49-
const chunk0 = this.chunks[0]!;
50-
const size0 = Math.min(chunk0.length - this.x, size);
51-
dst.set(chunk0.subarray(this.x, this.x + size0), pos);
52-
size -= size0;
53-
if (size <= 0) {
54-
this.skipUnsafe(size0);
55-
return;
56-
}
57-
let chunkIndex = 1;
58-
while (size > 0) {
59-
const chunk1 = this.chunks[chunkIndex]!;
60-
const size1 = Math.min(chunk1.length, size);
61-
dst.set(chunk1.subarray(0, size1), pos + size0);
62-
size -= size1;
63-
chunkIndex++;
64-
}
65-
this.skipUnsafe(size);
66-
}
67-
68-
public copyXor(
69-
size: number,
70-
dst: Uint8Array,
71-
pos: number,
72-
mask: [number, number, number, number],
73-
maskIndex: number,
74-
): void {
75-
if (!size) return;
76-
this.assertSize(size);
77-
const chunk0 = this.chunks[0]!;
78-
let x = this.x;
79-
const size0 = Math.min(chunk0.length - x, size);
80-
const end = x + size0;
81-
for (; x < end; ) dst[pos++] = chunk0[x++] ^ mask[maskIndex++ % 4];
82-
size -= size0;
83-
if (size <= 0) {
84-
this.skipUnsafe(size0);
85-
return;
86-
}
87-
let chunkIndex = 1;
88-
while (size > 0) {
89-
const chunk1 = this.chunks[chunkIndex++]!;
90-
const size1 = Math.min(chunk1.length, size);
91-
for (let x = 0; x < size1; ) dst[pos++] = chunk1[x++] ^ mask[maskIndex++ % 4];
92-
size -= size1;
93-
}
94-
this.skipUnsafe(size);
95-
}
96-
97-
public buf(size: number): Uint8Array {
98-
this.assertSize(size);
99-
const buf = new Uint8Array(size);
100-
this.copy(size, buf, 0);
101-
return buf;
102-
}
103-
104-
public bufXor(size: number, mask: [number, number, number, number], maskIndex: number): Uint8Array {
105-
this.assertSize(size);
106-
const buf = new Uint8Array(size);
107-
this.copyXor(size, buf, 0, mask, maskIndex);
108-
return buf;
109-
}
110-
111-
public skipUnsafe(n: number): void {
112-
if (!n) return;
113-
const chunk = this.chunks[0]!;
114-
const chunkLength = chunk.length;
115-
const remaining = chunkLength - this.x;
116-
if (remaining > n) {
117-
this.x = this.x + n;
118-
return;
119-
}
120-
this.x = 0;
121-
this.chunks.shift();
122-
this.chunkSize -= chunkLength;
123-
n -= remaining;
124-
this.skipUnsafe(n);
125-
}
126-
127-
public skip(n: number): void {
128-
this.assertSize(n);
129-
this.skipUnsafe(n);
130-
}
131-
132-
public peek(): number {
133-
this.assertSize(1);
134-
return this.chunks[0]![this.x];
135-
}
136-
137-
/**
138-
* Get current byte value without advancing the cursor.
139-
* @deprecated Use peek() instead.
140-
*/
141-
public peak(): number {
142-
return this.peek();
143-
}
144-
145-
public utf8(length: number, mask: [number, number, number, number], maskIndex: number): string {
146-
this.assertSize(length);
147-
let i = 0;
148-
const points: number[] = [];
149-
while (i < length) {
150-
let code = this.u8() ^ mask[maskIndex++ % 4];
151-
i++;
152-
if ((code & 0x80) !== 0) {
153-
const octet2 = (this.u8() ^ mask[maskIndex++ % 4]) & 0x3f;
154-
i++;
155-
if ((code & 0xe0) === 0xc0) {
156-
code = ((code & 0x1f) << 6) | octet2;
157-
} else {
158-
const octet3 = (this.u8() ^ mask[maskIndex++ % 4]) & 0x3f;
159-
i++;
160-
if ((code & 0xf0) === 0xe0) {
161-
code = ((code & 0x1f) << 12) | (octet2 << 6) | octet3;
162-
} else {
163-
if ((code & 0xf8) === 0xf0) {
164-
const octet4 = (this.u8() ^ mask[maskIndex++ % 4]) & 0x3f;
165-
i++;
166-
let unit = ((code & 0x07) << 0x12) | (octet2 << 0x0c) | (octet3 << 0x06) | octet4;
167-
if (unit > 0xffff) {
168-
unit -= 0x10000;
169-
const unit0 = ((unit >>> 10) & 0x3ff) | 0xd800;
170-
code = 0xdc00 | (unit & 0x3ff);
171-
points.push(unit0);
172-
} else {
173-
code = unit;
174-
}
175-
}
176-
}
177-
}
178-
}
179-
points.push(code);
180-
}
181-
return fromCharCode.apply(String, points);
182-
}
183-
}
1+
export * from '@jsonjoy.com/buffers/lib/StreamingOctetReader';

0 commit comments

Comments
 (0)