-
Notifications
You must be signed in to change notification settings - Fork 906
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5b21c65
commit 77d9352
Showing
7 changed files
with
133 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
const END_OF_BUFFER_ERROR_MESSAGE = 'Reached end of buffer unexpectedly'; | ||
|
||
/** | ||
* Delegates to `Array#shift`, but throws if the array is zero-length. | ||
*/ | ||
export function guardedShift<T>(byteArray: T[]): T { | ||
if (byteArray.length === 0) { | ||
throw new Error(END_OF_BUFFER_ERROR_MESSAGE); | ||
} | ||
return byteArray.shift() as T; | ||
} | ||
|
||
/** | ||
* Delegates to `Array#splice`, but throws if the section being spliced out extends past the end of | ||
* the array. | ||
*/ | ||
export function guardedSplice<T>( | ||
byteArray: T[], | ||
...args: | ||
| [start: number, deleteCount?: number] | ||
| [start: number, deleteCount: number, ...items: T[]] | ||
): T[] { | ||
const [start] = args; | ||
if ( | ||
args.length === 2 // Implies that `deleteCount` was supplied | ||
? start + (args[1] ?? 0) > byteArray.length | ||
: start >= byteArray.length | ||
) { | ||
throw new Error(END_OF_BUFFER_ERROR_MESSAGE); | ||
} | ||
return byteArray.splice( | ||
...(args as Parameters<typeof Array.prototype.splice>), | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import {expect} from 'chai'; | ||
import {spy} from 'sinon'; | ||
|
||
import {guardedShift, guardedSplice} from '../src/utils/guarded-array-utils'; | ||
|
||
describe('guardedShift', () => { | ||
it('delegates to Array#shift', () => { | ||
const arr = [1, 2, 3]; | ||
const shiftSpy = spy(arr, 'shift'); | ||
const result = guardedShift(arr); | ||
expect(shiftSpy).is.calledWithExactly(); | ||
expect(result).to.eq(shiftSpy.returnValues[0]); | ||
}); | ||
it('throws when the array is zero-length', () => { | ||
const arr: number[] = []; | ||
expect(() => guardedShift(arr)).to.throw(); | ||
}); | ||
}); | ||
|
||
describe('guardedSplice', () => { | ||
it('delegates to Array#splice', () => { | ||
const arr = [1, 2, 3]; | ||
const spliceSpy = spy(arr, 'splice'); | ||
const result = guardedSplice( | ||
arr, | ||
/* start */ 0, | ||
/* deleteCount */ 3, | ||
/* ...items */ | ||
100, | ||
101, | ||
102, | ||
); | ||
expect(spliceSpy).is.calledWithExactly(0, 3, 100, 101, 102); | ||
expect(result).to.eq(spliceSpy.returnValues[0]); | ||
}); | ||
it('allows zero-length splices', () => { | ||
const arr: number[] = [1, 2, 3]; | ||
expect(guardedSplice(arr, 0, 0)).to.be.an.empty('array'); | ||
}); | ||
it('allows zero-length splices via the `deleteCount` argument being the explicit value `undefined`', () => { | ||
const arr: number[] = [1, 2, 3]; | ||
expect(guardedSplice(arr, 0, undefined)).to.be.an.empty('array'); | ||
}); | ||
it('throws when the `start` would take you past the end of the array', () => { | ||
const arr: number[] = [1, 2, 3]; | ||
expect(() => guardedSplice(arr, 3)).to.throw(); | ||
}); | ||
it('throws when the `deleteCount` and `start` would take you past the end of the array', () => { | ||
const arr: number[] = [1, 2, 3]; | ||
expect(() => guardedSplice(arr, 1, 3)).to.throw(); | ||
}); | ||
}); |