Skip to content

Commit 0a802ce

Browse files
committed
feat: add iteration methods.
- Add entries method to get an iterator of index-byte pairs. - Add keys method to get an iterator of indices. - Add values method to get an iterator of bytes. - Add test cases for iterations. - Update eslint rules.
1 parent c0a59bc commit 0a802ce

File tree

4 files changed

+223
-0
lines changed

4 files changed

+223
-0
lines changed

.eslintrc.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
".tx": "never"
2222
}
2323
],
24+
"import/prefer-default-export": "off",
25+
"max-classes-per-file": "off",
2426
"no-dupe-class-members": "off",
2527
"no-unused-vars": "off"
2628
},

src/dynamicBuffer.ts

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { constants } from 'buffer';
22

3+
import { DynamicBufferIterator } from './iterator';
4+
35
type BufferEncoding = 'ascii' | 'utf8' | 'utf-8' | 'utf16le' | 'ucs2' | 'ucs-2'
46
| 'base64' | 'base64url' | 'latin1' | 'binary' | 'hex';
57

@@ -226,6 +228,123 @@ export class DynamicBuffer {
226228
};
227229
}
228230

231+
/**
232+
* Creates and returns an iterator of key(index) and value(byte) pairs from this buffer.
233+
*
234+
* ```js
235+
* buf.append('Hello');
236+
*
237+
* for (const pair of buf.entries()) {
238+
* console.log(pair);
239+
* }
240+
* // [0, 72]
241+
* // [1, 101]
242+
* // [2, 108]
243+
* // [3, 108]
244+
* // [4, 111]
245+
*
246+
* @returns Iterator of index and byte pairs from this buffer.
247+
* ```
248+
*/
249+
entries(): IterableIterator<[number, number]> {
250+
return new class extends DynamicBufferIterator<[number, number]> {
251+
next(): IteratorResult<[number, number], any> {
252+
if (!this.buf.buffer || this.buf.used === this.index) {
253+
return {
254+
done: true,
255+
value: undefined,
256+
};
257+
}
258+
259+
const i = this.index;
260+
const value = this.buf.buffer[this.index];
261+
this.index += 1;
262+
263+
return {
264+
done: false,
265+
value: [i, value],
266+
};
267+
}
268+
}(this);
269+
}
270+
271+
/**
272+
* Creates and returns an iterator for keys(indices) in this buffer.
273+
*
274+
* ```js
275+
* buf.append('Hello');
276+
*
277+
* for (const key of buf.keys()) {
278+
* console.log(key);
279+
* }
280+
* // 0
281+
* // 1
282+
* // 2
283+
* // 3
284+
* // 4
285+
*
286+
* @returns Iterator of buffer keys.
287+
* ```
288+
*/
289+
keys(): IterableIterator<number> {
290+
return new class extends DynamicBufferIterator<number> {
291+
next(): IteratorResult<number, any> {
292+
if (!this.buf.buffer || this.buf.used === this.index) {
293+
return {
294+
done: true,
295+
value: undefined,
296+
};
297+
}
298+
299+
const value = this.index;
300+
this.index += 1;
301+
302+
return {
303+
done: false,
304+
value,
305+
};
306+
}
307+
}(this);
308+
}
309+
310+
/**
311+
* Creates and returns an iterator for values(bytes) in this buffer.
312+
*
313+
* ```js
314+
* buf.append('Hello');
315+
* for (const value of buf.values()) {
316+
* console.log(value);
317+
* }
318+
* // 72
319+
* // 101
320+
* // 108
321+
* // 108
322+
* // 111
323+
*
324+
* @returns Iterator of buffer values.
325+
* ```
326+
*/
327+
values(): IterableIterator<number> {
328+
return new class extends DynamicBufferIterator<number> {
329+
next(): IteratorResult<number, any> {
330+
if (!this.buf.buffer || this.buf.used === this.index) {
331+
return {
332+
done: true,
333+
value: undefined,
334+
};
335+
}
336+
337+
const value = this.buf.buffer[this.index];
338+
this.index += 1;
339+
340+
return {
341+
done: false,
342+
value,
343+
};
344+
}
345+
}(this);
346+
}
347+
229348
/**
230349
* Ensures the buffer size is at least equal to the expect size.
231350
*

src/iterator.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { DynamicBuffer } from '.';
2+
3+
/**
4+
* Abstract iterator class for DynamicBuffer.
5+
*
6+
* ```js
7+
* class ValueIterator extends DynamicBufferIterator<number> {
8+
* next() {
9+
* // ...
10+
* }
11+
* }
12+
* ```
13+
*/
14+
export abstract class DynamicBufferIterator<T> implements IterableIterator<T> {
15+
protected buf: DynamicBuffer;
16+
17+
protected index: number;
18+
19+
constructor(buf: DynamicBuffer) {
20+
this.buf = buf;
21+
this.index = 0;
22+
}
23+
24+
[Symbol.iterator](): IterableIterator<T> {
25+
return this;
26+
}
27+
28+
abstract next(): IteratorResult<T, any>;
29+
}

test/dynamicBuffer.spec.ts

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable no-restricted-syntax */
12
import assert from 'assert';
23
import { constants } from 'buffer';
34
import { describe, it } from 'mocha';
@@ -236,6 +237,78 @@ describe('Exports to JSON object', () => {
236237
});
237238
});
238239

240+
describe('Iteration tests', () => {
241+
it('Test entries() before writing data', () => {
242+
const buf = new DynamicBuffer();
243+
244+
for (const _ of buf.entries()) {
245+
assert.fail('Should not enter loop');
246+
}
247+
});
248+
249+
it('Test entires()', () => {
250+
const buf = new DynamicBuffer();
251+
const str = 'Hello world';
252+
253+
buf.append(str);
254+
255+
let index = 0;
256+
for (const pair of buf.entries()) {
257+
assert.equal(pair[0], index);
258+
assert.equal(pair[1], str.charCodeAt(index));
259+
index += 1;
260+
}
261+
262+
assert.equal(buf.length, index);
263+
});
264+
265+
it('Test keys() before writing data', () => {
266+
const buf = new DynamicBuffer();
267+
268+
for (const _ of buf.keys()) {
269+
assert.fail('Should not enter loop');
270+
}
271+
});
272+
273+
it('Test keys()', () => {
274+
const buf = new DynamicBuffer();
275+
const str = 'Hello world';
276+
277+
buf.append(str);
278+
279+
let index = 0;
280+
for (const key of buf.keys()) {
281+
assert.equal(key, index);
282+
index += 1;
283+
}
284+
285+
assert.equal(buf.length, index);
286+
});
287+
288+
it('Test values() before writing data', () => {
289+
const buf = new DynamicBuffer();
290+
291+
for (const _ of buf.values()) {
292+
assert.fail('Should not enter loop');
293+
}
294+
});
295+
296+
it('Test values()', () => {
297+
const buf = new DynamicBuffer();
298+
const str = 'Hello world';
299+
300+
buf.append(str);
301+
302+
let index = 0;
303+
for (const value of buf.values()) {
304+
assert.equal(value, str.charCodeAt(index));
305+
index += 1;
306+
}
307+
308+
assert.equal(buf.length, index);
309+
});
310+
});
311+
239312
describe('Resize tests', () => {
240313
it('Test resize()', () => {
241314
const buffer = new DynamicBuffer();

0 commit comments

Comments
 (0)