Skip to content

Commit 32654ee

Browse files
authored
Merge pull request #209 from msgpack/clarify_empty_input
[doc] clarify the edge cases where the input buffer is empty
2 parents 81bf88b + bebb16b commit 32654ee

File tree

8 files changed

+144
-7
lines changed

8 files changed

+144
-7
lines changed

.eslintrc.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ module.exports = {
1515
"prettier",
1616
],
1717
plugins: [
18-
"@typescript-eslint",
18+
"@typescript-eslint/eslint-plugin",
19+
"eslint-plugin-tsdoc"
1920
],
2021
parser: "@typescript-eslint/parser",
2122
parserOptions: {
@@ -38,6 +39,8 @@ module.exports = {
3839
"import/no-cycle": "error",
3940
"import/no-default-export": "warn",
4041

42+
"tsdoc/syntax": "warn",
43+
4144
"@typescript-eslint/await-thenable": "warn",
4245
"@typescript-eslint/array-type": ["warn", { default: "generic" }],
4346
"@typescript-eslint/naming-convention": [

.vscode/settings.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,8 @@
44
"editor.tabSize": 2,
55
"editor.codeActionsOnSave": {
66
"source.fixAll.eslint": true
7-
}
7+
},
8+
"cSpell.words": [
9+
"tsdoc"
10+
]
811
}

package-lock.json

Lines changed: 94 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
"eslint": "latest",
6868
"eslint-config-prettier": "latest",
6969
"eslint-plugin-import": "latest",
70+
"eslint-plugin-tsdoc": "latest",
7071
"ieee754": "latest",
7172
"karma": "latest",
7273
"karma-chrome-launcher": "latest",

src/Decoder.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,8 @@ export class Decoder<ContextType = undefined> {
118118
}
119119

120120
/**
121-
* @throws {DecodeError}
122-
* @throws {RangeError}
121+
* @throws {@link DecodeError}
122+
* @throws {@link RangeError}
123123
*/
124124
public decode(buffer: ArrayLike<number> | BufferSource): unknown {
125125
this.reinitializeState();

src/decode.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ export const defaultDecodeOptions: DecodeOptions = {};
4747
*
4848
* This is a synchronous decoding function.
4949
* See other variants for asynchronous decoding: {@link decodeAsync()}, {@link decodeStream()}, or {@link decodeArrayStream()}.
50+
*
51+
* @throws {@link RangeError} if the buffer is incomplete, including the case where the buffer is empty.
52+
* @throws {@link DecodeError} if the buffer contains invalid data.
5053
*/
5154
export function decode<ContextType = undefined>(
5255
buffer: ArrayLike<number> | BufferSource,
@@ -67,6 +70,9 @@ export function decode<ContextType = undefined>(
6770
/**
6871
* It decodes multiple MessagePack objects in a buffer.
6972
* This is corresponding to {@link decodeMultiStream()}.
73+
*
74+
* @throws {@link RangeError} if the buffer is incomplete, including the case where the buffer is empty.
75+
* @throws {@link DecodeError} if the buffer contains invalid data.
7076
*/
7177
export function decodeMulti<ContextType = undefined>(
7278
buffer: ArrayLike<number> | BufferSource,

src/decodeAsync.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@ import type { ReadableStreamLike } from "./utils/stream";
55
import type { DecodeOptions } from "./decode";
66
import type { SplitUndefined } from "./context";
77

8-
export async function decodeAsync<ContextType>(
8+
/**
9+
* @throws {@link RangeError} if the buffer is incomplete, including the case where the buffer is empty.
10+
* @throws {@link DecodeError} if the buffer contains invalid data.
11+
*/
12+
export async function decodeAsync<ContextType>(
913
streamLike: ReadableStreamLike<ArrayLike<number> | BufferSource>,
1014
options: DecodeOptions<SplitUndefined<ContextType>> = defaultDecodeOptions as any,
1115
): Promise<unknown> {
@@ -23,7 +27,11 @@ export async function decodeAsync<ContextType>(
2327
return decoder.decodeAsync(stream);
2428
}
2529

26-
export function decodeArrayStream<ContextType>(
30+
/**
31+
* @throws {@link RangeError} if the buffer is incomplete, including the case where the buffer is empty.
32+
* @throws {@link DecodeError} if the buffer contains invalid data.
33+
*/
34+
export function decodeArrayStream<ContextType>(
2735
streamLike: ReadableStreamLike<ArrayLike<number> | BufferSource>,
2836
options: DecodeOptions<SplitUndefined<ContextType>> = defaultDecodeOptions as any,
2937
): AsyncGenerator<unknown, void, unknown> {
@@ -42,6 +50,10 @@ export function decodeArrayStream<ContextType>(
4250
return decoder.decodeArrayStream(stream);
4351
}
4452

53+
/**
54+
* @throws {@link RangeError} if the buffer is incomplete, including the case where the buffer is empty.
55+
* @throws {@link DecodeError} if the buffer contains invalid data.
56+
*/
4557
export function decodeMultiStream<ContextType>(
4658
streamLike: ReadableStreamLike<ArrayLike<number> | BufferSource>,
4759
options: DecodeOptions<SplitUndefined<ContextType>> = defaultDecodeOptions as any,

test/edge-cases.test.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// kind of hand-written fuzzing data
22
// any errors should not break Encoder/Decoder instance states
33
import assert from "assert";
4-
import { encode, decode, Encoder, Decoder } from "../src";
4+
import { encode, decodeAsync, decode, Encoder, Decoder } from "../src";
55
import { DataViewIndexOutOfBoundsError } from "../src/Decoder";
66

77
function testEncoder(encoder: Encoder): void {
@@ -147,4 +147,22 @@ describe("edge cases", () => {
147147
testDecoder(decoder);
148148
});
149149
});
150+
151+
context("try to decode an empty input", () => {
152+
it("throws RangeError (synchronous)", () => {
153+
assert.throws(() => {
154+
decode([]);
155+
}, RangeError);
156+
});
157+
158+
it("throws RangeError (asynchronous)", async () => {
159+
const createStream = async function* () {
160+
yield [];
161+
};
162+
163+
assert.rejects(async () => {
164+
await decodeAsync(createStream());
165+
}, RangeError);
166+
});
167+
});
150168
});

0 commit comments

Comments
 (0)