Skip to content

Commit ad67754

Browse files
committed
feat: add Uint8Array's methods for DynamicBuffer.
Added every, filter, find, findIndex, forEach, join, map, some, and sort methods.
1 parent 569fe9d commit ad67754

File tree

2 files changed

+339
-1
lines changed

2 files changed

+339
-1
lines changed

src/dynamicBuffer.ts

Lines changed: 184 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,26 @@ export class DynamicBuffer {
439439
return this.compare(otherBuffer, 0, otherBuffer.length, 0, this.length) === 0;
440440
}
441441

442+
/**
443+
* Determines whether all the bytes of the buffer satisfy the specified test.
444+
*
445+
* @param predicate A function that accepts up to three arguments. The every method calls the
446+
* predicate function for each byte in the buffer until the predicate returns a value which is
447+
* coercible to the Boolean value false, or until the end of the buffer.
448+
* @param thisArg An object to which the this keyword can refer in the predicate function. If
449+
* thisArg is omitted, undefined is used as the this value.
450+
*/
451+
every(
452+
predicate: (value: number, index: number, array: Uint8Array) => unknown,
453+
thisArg?: any,
454+
): boolean {
455+
if (!this.buffer || this.length <= 0) {
456+
return true;
457+
}
458+
459+
return this.buffer.subarray(0, this.length).every(predicate, thisArg);
460+
}
461+
442462
/**
443463
* Fills this buffer with the specified value, and the entire buffer will be filled if the offset
444464
* and end are not given.
@@ -474,6 +494,85 @@ export class DynamicBuffer {
474494
return this;
475495
}
476496

497+
/**
498+
* Returns the bytes of an array that meet the condition specified in a callback function.
499+
*
500+
* @param predicate A function that accepts up to three arguments. The filter method calls
501+
* the predicate function one time for each byte in the buffer.
502+
* @param thisArg An object to which the this keyword can refer in the predicate function.
503+
* If thisArg is omitted, undefined is used as the this value.
504+
*/
505+
filter(
506+
predicate: (value: number, index: number, array: Uint8Array) => any,
507+
thisArg?: any,
508+
): Uint8Array {
509+
if (!this.buffer || this.length === 0) {
510+
return new Uint8Array(0);
511+
}
512+
513+
return this.buffer.subarray(0, this.length).filter(predicate, thisArg);
514+
}
515+
516+
/**
517+
* Returns the value of the first byte in the buffer where predicate is true, and undefined
518+
* otherwise.
519+
*
520+
* @param predicate find calls predicate once for each byte of the buffer, in ascending order,
521+
* until it finds one where predicate returns true. If such a byte is found, find immediately
522+
* returns that byte. Otherwise, find returns undefined.
523+
* @param thisArg If provided, it will be used as the this value for each invocation of
524+
* predicate. If it is not provided, undefined is used instead.
525+
*/
526+
find(
527+
predicate: (value: number, index: number, obj: Uint8Array) => boolean,
528+
thisArg?: any,
529+
): number | undefined {
530+
if (!this.buffer || this.length === 0) {
531+
return undefined;
532+
}
533+
534+
return this.buffer.subarray(0, this.length).find(predicate, thisArg);
535+
}
536+
537+
/**
538+
* Returns the index of the first byte in the buffer where predicate is true, and -1 otherwise.
539+
*
540+
* @param predicate find calls predicate once for each byte of the buffer, in ascending order,
541+
* until it finds one where predicate returns true. If such a byte is found, findIndex
542+
* immediately returns that byte position. Otherwise, findIndex returns -1.
543+
* @param thisArg If provided, it will be used as the this value for each invocation of
544+
* predicate. If it is not provided, undefined is used instead.
545+
*/
546+
findIndex(
547+
predicate: (value: number, index: number, obj: Uint8Array) => boolean,
548+
thisArg?: any,
549+
): number {
550+
if (!this.buffer || this.length === 0) {
551+
return -1;
552+
}
553+
554+
return this.buffer.subarray(0, this.length).findIndex(predicate, thisArg);
555+
}
556+
557+
/**
558+
* Performs the specified action for each byte in the buffer.
559+
*
560+
* @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn
561+
* function one time for each byte in the buffer.
562+
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If
563+
* thisArg is omitted, undefined is used as the this value.
564+
*/
565+
forEach(
566+
callbackfn: (value: number, index: number, array: Uint8Array) => void,
567+
thisArg?: any,
568+
): void {
569+
if (!this.buffer || this.length === 0) {
570+
return;
571+
}
572+
573+
this.buffer.subarray(0, this.length).forEach(callbackfn, thisArg);
574+
}
575+
477576
/**
478577
* Returns a boolean value to indicate whether this buffer includes a certain value among it.
479578
*
@@ -526,6 +625,20 @@ export class DynamicBuffer {
526625
return this.indexOfWithDir(true, value, byteOffset, encoding);
527626
}
528627

628+
/**
629+
* Adds all the bytes of the buffer separated by the specified separator string.
630+
*
631+
* @param separator A string used to separate one byte of the buffer from the next in the
632+
* resulting String. If omitted, the bytes are separated with a comma.
633+
*/
634+
join(separator?: string): string {
635+
if (!this.buffer || this.length === 0) {
636+
return '';
637+
}
638+
639+
return this.buffer.subarray(0, this.length).join(separator);
640+
}
641+
529642
/**
530643
* Creates and returns an iterator for keys(indices) in this buffer.
531644
*
@@ -592,6 +705,26 @@ export class DynamicBuffer {
592705
return this.indexOfWithDir(false, value, byteOffset, encoding);
593706
}
594707

708+
/**
709+
* Calls a defined callback function on each byte of the buffer, and returns an array that
710+
* contains the results.
711+
*
712+
* @param callbackfn A function that accepts up to three arguments. The map method calls the
713+
* callbackfn function one time for each byte in the buffer.
714+
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
715+
* If thisArg is omitted, undefined is used as the this value.
716+
*/
717+
map(
718+
callbackfn: (value: number, index: number, array: Uint8Array) => number,
719+
thisArg?: any,
720+
): Uint8Array {
721+
if (!this.buffer || this.length === 0) {
722+
return new Uint8Array(0);
723+
}
724+
725+
return this.buffer.subarray(0, this.length).map(callbackfn, thisArg);
726+
}
727+
595728
/**
596729
* Reads and returns a byte at the position `offset` in this buffer.
597730
*
@@ -654,6 +787,49 @@ export class DynamicBuffer {
654787
this.subarray(0, this.length).set(array, offset);
655788
}
656789

790+
/**
791+
* Determines whether the specified callback function returns true for any byte of the buffer.
792+
*
793+
* @param predicate A function that accepts up to three arguments. The some method calls the
794+
* predicate function for each byte in the buffer until the predicate returns a value which is
795+
* coercible to the Boolean value true, or until the end of the buffer.
796+
* @param thisArg An object to which the this keyword can refer in the predicate function.
797+
* If thisArg is omitted, undefined is used as the this value.
798+
*/
799+
some(
800+
predicate: (value: number, index: number, array: Uint8Array) => unknown,
801+
thisArg?: any,
802+
): boolean {
803+
if (!this.buffer || this.length === 0) {
804+
return false;
805+
}
806+
807+
return this.buffer.subarray(0, this.length).some(predicate, thisArg);
808+
}
809+
810+
/**
811+
* Sorts all bytes in the buffer.
812+
*
813+
* ```js
814+
* const buf = new DynamicBuffer('cba');
815+
* buf.sort();
816+
* console.log(buf.toString());
817+
* // abc
818+
* ```
819+
*
820+
* @param compareFn Function used to determine the order of the elements. It is expected to
821+
* return a negative value if first argument is less than second argument, zero if they're
822+
* equal and a positive value otherwise. If omitted, the elements are sorted in ascending order.
823+
* @returns The reference of this buffer.
824+
*/
825+
sort(compareFn?: (a: number, b: number) => number): this {
826+
if (this.buffer && this.length > 0) {
827+
this.buffer.subarray(0, this.length).sort(compareFn);
828+
}
829+
830+
return this;
831+
}
832+
657833
/**
658834
* Returns a new Buffer that references the same memory as the original, but offset and cropped
659835
* by the start and end indices.
@@ -841,7 +1017,14 @@ export class DynamicBuffer {
8411017
}
8421018

8431019
/**
844-
* The alias of toString().
1020+
* Decodes buffer to a string with the specified character encoding and range. It's an alias of
1021+
* toString().
1022+
*
1023+
* ```js
1024+
* const buf = new DynamicBuffer('hello');
1025+
* console.log(buf.toLocaleString());
1026+
* // hello
1027+
* ```
8451028
*
8461029
* @returns The string decodes from buffer
8471030
*/

test/array.spec.ts

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,125 @@ import { describe, it } from 'mocha';
33

44
import { DynamicBuffer } from '../src';
55

6+
describe('Every tests', () => {
7+
it('Test every', () => {
8+
const buf1 = new DynamicBuffer('hello');
9+
const buf2 = new DynamicBuffer('Hello');
10+
11+
assert.equal(buf1.every((v) => v >= 97 && v <= 122), true);
12+
assert.equal(buf2.every((v) => v >= 97 && v <= 122), false);
13+
});
14+
15+
it('Test empty buffer\'s every method', () => {
16+
const buf = new DynamicBuffer();
17+
18+
assert.equal(buf.every((v) => v >= 97 && v <= 122), true);
19+
});
20+
});
21+
22+
describe('Filter tests', () => {
23+
it('Test filter', () => {
24+
const buf = new DynamicBuffer('Hello');
25+
26+
assert.deepEqual(buf.filter((v) => v >= 97 && v <= 122), new Uint8Array([101, 108, 108, 111]));
27+
});
28+
29+
it('Test empty buffer\'s filter method', () => {
30+
const buf = new DynamicBuffer();
31+
32+
assert.deepEqual(buf.filter((v) => v >= 97 && v <= 122), new Uint8Array());
33+
});
34+
});
35+
36+
describe('Find tests', () => {
37+
it('Test find', () => {
38+
const buf = new DynamicBuffer('Hello');
39+
40+
assert.equal(buf.find((v) => v >= 97 && v <= 122), 101);
41+
assert.equal(buf.find((v) => v >= 48 && v <= 57), undefined);
42+
});
43+
44+
it('Test empty buffer\'s find method', () => {
45+
const buf = new DynamicBuffer();
46+
47+
assert.equal(buf.find((v) => v >= 97 && v <= 122), undefined);
48+
});
49+
});
50+
51+
describe('FindIndex tests', () => {
52+
it('Test findIndex', () => {
53+
const buf = new DynamicBuffer('Hello');
54+
55+
assert.equal(buf.findIndex((v) => v >= 97 && v <= 122), 1);
56+
assert.equal(buf.findIndex((v) => v >= 48 && v <= 57), -1);
57+
});
58+
59+
it('Test empty buffer\'s findIndex method', () => {
60+
const buf = new DynamicBuffer();
61+
62+
assert.equal(buf.findIndex((v) => v >= 97 && v <= 122), -1);
63+
});
64+
});
65+
66+
describe('ForEach tests', () => {
67+
it('Test forEach', () => {
68+
const buf = new DynamicBuffer('Hello');
69+
const arr: number[] = [];
70+
let called = false;
71+
72+
buf.forEach((v, i) => {
73+
called = true;
74+
arr[i] = v;
75+
});
76+
77+
assert.equal(called, true);
78+
assert.deepEqual(arr, [72, 101, 108, 108, 111]);
79+
});
80+
81+
it('Test empty buffer\'s forEach method', () => {
82+
const buf = new DynamicBuffer();
83+
const arr: number[] = [];
84+
let called = false;
85+
86+
buf.forEach((v, i) => {
87+
called = true;
88+
arr[i] = v;
89+
});
90+
91+
assert.equal(called, false);
92+
assert.deepEqual(arr, []);
93+
});
94+
});
95+
96+
describe('Join tests', () => {
97+
it('Test join', () => {
98+
const buf = new DynamicBuffer('Hello');
99+
100+
assert.equal(buf.join(), '72,101,108,108,111');
101+
assert.equal(buf.join('|'), '72|101|108|108|111');
102+
});
103+
104+
it('Test empty buffer\'s join method', () => {
105+
const buf = new DynamicBuffer();
106+
107+
assert.equal(buf.join(), '');
108+
});
109+
});
110+
111+
describe('Map tests', () => {
112+
it('Test map', () => {
113+
const buf = new DynamicBuffer('Hello');
114+
115+
assert.deepEqual(buf.map((v) => v + 1), new Uint8Array([73, 102, 109, 109, 112]));
116+
});
117+
118+
it('Test empty buffer\'s map method', () => {
119+
const buf = new DynamicBuffer();
120+
121+
assert.deepEqual(buf.map((v) => v + 1), new Uint8Array());
122+
});
123+
});
124+
6125
describe('Reverse tests', () => {
7126
it('Reverse buffer', () => {
8127
const buf = new DynamicBuffer('hello');
@@ -20,3 +139,39 @@ describe('Reverse tests', () => {
20139
assert.equal(ref.toString(), '');
21140
});
22141
});
142+
143+
describe('Some tests', () => {
144+
it('Test some', () => {
145+
const buf1 = new DynamicBuffer('HELLO');
146+
const buf2 = new DynamicBuffer('Hello');
147+
148+
assert.equal(buf1.some((v) => v >= 97 && v <= 122), false);
149+
assert.equal(buf2.some((v) => v >= 97 && v <= 122), true);
150+
});
151+
152+
it('Test empty buffer\'s some method', () => {
153+
const buf = new DynamicBuffer();
154+
155+
assert.equal(buf.some((v) => v >= 97 && v <= 122), false);
156+
});
157+
});
158+
159+
describe('Sort tests', () => {
160+
it('Sort without compare function', () => {
161+
const buf = new DynamicBuffer('cba');
162+
buf.sort();
163+
assert.equal(buf.toString(), 'abc');
164+
});
165+
166+
it('Sort in ascending order', () => {
167+
const buf = new DynamicBuffer('cba');
168+
buf.sort((a, b) => a - b);
169+
assert.equal(buf.toString(), 'abc');
170+
});
171+
172+
it('Sort in descending order', () => {
173+
const buf = new DynamicBuffer('abc');
174+
buf.sort((a, b) => b - a);
175+
assert.equal(buf.toString(), 'cba');
176+
});
177+
});

0 commit comments

Comments
 (0)