Skip to content

Commit 04e2270

Browse files
authored
Merge pull request #155 from msgpack/buffer-source
fix: make decodeAsync(), decodeStream(), and decodeArrayStream() to take BufferSource
2 parents 6c225f3 + a3f7167 commit 04e2270

File tree

5 files changed

+40
-25
lines changed

5 files changed

+40
-25
lines changed

README.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,11 @@ deepStrictEqual(decode(encoded), object);
4545
- [API](#api)
4646
- [`encode(data: unknown, options?: EncodeOptions): Uint8Array`](#encodedata-unknown-options-encodeoptions-uint8array)
4747
- [`EncodeOptions`](#encodeoptions)
48-
- [`decode(buffer: ArrayLike<number> | ArrayBuffer, options?: DecodeOptions): unknown`](#decodebuffer-arraylikenumber--arraybuffer-options-decodeoptions-unknown)
48+
- [`decode(buffer: ArrayLike<number> | BufferSource, options?: DecodeOptions): unknown`](#decodebuffer-arraylikenumber--buffersource-options-decodeoptions-unknown)
4949
- [`DecodeOptions`](#decodeoptions)
50-
- [`decodeAsync(stream: AsyncIterable<ArrayLike<number>> | ReadableStream<ArrayLike<number>>, options?: DecodeAsyncOptions): Promise<unknown>`](#decodeasyncstream-asynciterablearraylikenumber--readablestreamarraylikenumber-options-decodeasyncoptions-promiseunknown)
51-
- [`decodeArrayStream(stream: AsyncIterable<ArrayLike<number>> | ReadableStream<ArrayLike<number>>, options?: DecodeAsyncOptions): AsyncIterable<unknown>`](#decodearraystreamstream-asynciterablearraylikenumber--readablestreamarraylikenumber-options-decodeasyncoptions-asynciterableunknown)
52-
- [`decodeStream(stream: AsyncIterable<ArrayLike<number>> | ReadableStream<ArrayLike<number>>, options?: DecodeAsyncOptions): AsyncIterable<unknown>`](#decodestreamstream-asynciterablearraylikenumber--readablestreamarraylikenumber-options-decodeasyncoptions-asynciterableunknown)
50+
- [`decodeAsync(stream: ReadableStreamLike<ArrayLike<number> | BufferSource>, options?: DecodeAsyncOptions): Promise<unknown>`](#decodeasyncstream-readablestreamlikearraylikenumber--buffersource-options-decodeasyncoptions-promiseunknown)
51+
- [`decodeArrayStream(stream: ReadableStreamLike<ArrayLike<number> | BufferSource>, options?: DecodeAsyncOptions): AsyncIterable<unknown>`](#decodearraystreamstream-readablestreamlikearraylikenumber--buffersource-options-decodeasyncoptions-asynciterableunknown)
52+
- [`decodeStream(stream: ReadableStreamLike<ArrayLike<number> | BufferSource>, options?: DecodeAsyncOptions): AsyncIterable<unknown>`](#decodestreamstream-readablestreamlikearraylikenumber--buffersource-options-decodeasyncoptions-asynciterableunknown)
5353
- [Reusing Encoder and Decoder instances](#reusing-encoder-and-decoder-instances)
5454
- [Extension Types](#extension-types)
5555
- [ExtensionCodec context](#extensioncodec-context)
@@ -123,11 +123,11 @@ forceIntegerToFloat | boolean | false
123123
ignoreUndefined | boolean | false
124124
context | user-defined | -
125125

126-
### `decode(buffer: ArrayLike<number> | ArrayBuffer, options?: DecodeOptions): unknown`
126+
### `decode(buffer: ArrayLike<number> | BufferSource, options?: DecodeOptions): unknown`
127127

128128
It decodes `buffer` encoded in MessagePack, and returns a decoded object as `unknown`.
129129

130-
`buffer` must be an array of bytes, which is typically `Uint8Array` or `ArrayBuffer`, but `Array<number>` is okay.
130+
`buffer` must be an array of bytes, which is typically `Uint8Array` or `ArrayBuffer`. `BufferSource` is defined as `ArrayBuffer | ArrayBufferView`.
131131

132132
for example:
133133

@@ -145,7 +145,7 @@ NodeJS `Buffer` is also acceptable because it is a subclass of `Uint8Array`.
145145

146146
Name|Type|Default
147147
----|----|----
148-
extensionCodec | ExtensionCodec | `ExtensinCodec.defaultCodec`
148+
extensionCodec | ExtensionCodec | `ExtensionCodec.defaultCodec`
149149
maxStrLength | number | `4_294_967_295` (UINT32_MAX)
150150
maxBinLength | number | `4_294_967_295` (UINT32_MAX)
151151
maxArrayLength | number | `4_294_967_295` (UINT32_MAX)
@@ -155,9 +155,9 @@ context | user-defined | -
155155

156156
You can use `max${Type}Length` to limit the length of each type decoded.
157157

158-
### `decodeAsync(stream: AsyncIterable<ArrayLike<number>> | ReadableStream<ArrayLike<number>>, options?: DecodeAsyncOptions): Promise<unknown>`
158+
### `decodeAsync(stream: ReadableStreamLike<ArrayLike<number> | BufferSource>, options?: DecodeAsyncOptions): Promise<unknown>`
159159

160-
It decodes `stream` in an async iterable of byte arrays, and returns decoded object as `uknown` type, wrapped in `Promise`. This function works asyncronously.
160+
It decodes `stream`, where `ReadableStreamLike<T>` is defined as `ReadableStream<T> | AsyncIterable<T>`, in an async iterable of byte arrays, and returns decoded object as `unknown` type, wrapped in `Promise`. This function works asynchronously.
161161

162162
`DecodeAsyncOptions` is the same as `DecodeOptions` for `decode()`.
163163

@@ -176,7 +176,7 @@ if (contentType && contentType.startsWith(MSGPACK_TYPE) && response.body != null
176176
} else { /* handle errors */ }
177177
```
178178

179-
### `decodeArrayStream(stream: AsyncIterable<ArrayLike<number>> | ReadableStream<ArrayLike<number>>, options?: DecodeAsyncOptions): AsyncIterable<unknown>`
179+
### `decodeArrayStream(stream: ReadableStreamLike<ArrayLike<number> | BufferSource>, options?: DecodeAsyncOptions): AsyncIterable<unknown>`
180180

181181
It is alike to `decodeAsync()`, but only accepts an array of items as the input `stream`, and emits the decoded item one by one.
182182

@@ -196,7 +196,7 @@ for await (const item of decodeArrayStream(stream)) {
196196
```
197197

198198

199-
### `decodeStream(stream: AsyncIterable<ArrayLike<number>> | ReadableStream<ArrayLike<number>>, options?: DecodeAsyncOptions): AsyncIterable<unknown>`
199+
### `decodeStream(stream: ReadableStreamLike<ArrayLike<number> | BufferSource>, options?: DecodeAsyncOptions): AsyncIterable<unknown>`
200200

201201
It is alike to `decodeAsync()` and `decodeArrayStream()`, but the input `stream` consists of independent MessagePack items.
202202

src/Decoder.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,13 @@ export class Decoder<ContextType> {
8585
this.headByte = HEAD_BYTE_REQUIRED;
8686
}
8787

88-
private setBuffer(buffer: ArrayLike<number> | ArrayBuffer): void {
88+
private setBuffer(buffer: ArrayLike<number> | BufferSource): void {
8989
this.bytes = ensureUint8Array(buffer);
9090
this.view = createDataView(this.bytes);
9191
this.pos = 0;
9292
}
9393

94-
private appendBuffer(buffer: ArrayLike<number>) {
94+
private appendBuffer(buffer: ArrayLike<number> | BufferSource) {
9595
if (this.headByte === HEAD_BYTE_REQUIRED && !this.hasRemaining()) {
9696
this.setBuffer(buffer);
9797
} else {
@@ -114,7 +114,7 @@ export class Decoder<ContextType> {
114114
return new RangeError(`Extra ${view.byteLength - pos} of ${view.byteLength} byte(s) found at buffer[${posToShow}]`);
115115
}
116116

117-
public decode(buffer: ArrayLike<number> | ArrayBuffer): unknown {
117+
public decode(buffer: ArrayLike<number> | BufferSource): unknown {
118118
this.reinitializeState();
119119
this.setBuffer(buffer);
120120

@@ -125,7 +125,7 @@ export class Decoder<ContextType> {
125125
return object;
126126
}
127127

128-
public async decodeAsync(stream: AsyncIterable<ArrayLike<number>>): Promise<unknown> {
128+
public async decodeAsync(stream: AsyncIterable<ArrayLike<number> | BufferSource>): Promise<unknown> {
129129
let decoded = false;
130130
let object: unknown;
131131
for await (const buffer of stream) {
@@ -160,15 +160,15 @@ export class Decoder<ContextType> {
160160
);
161161
}
162162

163-
public decodeArrayStream(stream: AsyncIterable<ArrayLike<number>>) {
163+
public decodeArrayStream(stream: AsyncIterable<ArrayLike<number> | BufferSource>) {
164164
return this.decodeMultiAsync(stream, true);
165165
}
166166

167-
public decodeStream(stream: AsyncIterable<ArrayLike<number>>) {
167+
public decodeStream(stream: AsyncIterable<ArrayLike<number> | BufferSource>) {
168168
return this.decodeMultiAsync(stream, false);
169169
}
170170

171-
private async *decodeMultiAsync(stream: AsyncIterable<ArrayLike<number>>, isArray: boolean) {
171+
private async *decodeMultiAsync(stream: AsyncIterable<ArrayLike<number> | BufferSource>, isArray: boolean) {
172172
let isArrayHeaderRequired = isArray;
173173
let arrayItemsLeft = -1;
174174

src/decode.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export const defaultDecodeOptions: DecodeOptions = {};
4343
* This is a synchronous decoding function. See other variants for asynchronous decoding: `decodeAsync()`, `decodeStream()`, `decodeArrayStream()`.
4444
*/
4545
export function decode<ContextType = undefined>(
46-
buffer: ArrayLike<number> | ArrayBuffer,
46+
buffer: ArrayLike<number> | BufferSource,
4747
options: DecodeOptions<SplitUndefined<ContextType>> = defaultDecodeOptions as any,
4848
): unknown {
4949
const decoder = new Decoder(

src/decodeAsync.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import { Decoder } from "./Decoder";
2-
import { defaultDecodeOptions, DecodeOptions } from "./decode";
3-
import { ensureAsyncIterable, ReadableStreamLike } from "./utils/stream";
4-
import { SplitUndefined } from "./context";
2+
import { ensureAsyncIterable } from "./utils/stream";
3+
import { defaultDecodeOptions } from "./decode";
4+
import type { ReadableStreamLike } from "./utils/stream";
5+
import type { DecodeOptions } from "./decode";
6+
import type { SplitUndefined } from "./context";
57

68
export async function decodeAsync<ContextType>(
7-
streamLike: ReadableStreamLike<ArrayLike<number>>,
9+
streamLike: ReadableStreamLike<ArrayLike<number> | BufferSource>,
810
options: DecodeOptions<SplitUndefined<ContextType>> = defaultDecodeOptions as any,
911
): Promise<unknown> {
1012
const stream = ensureAsyncIterable(streamLike);
@@ -22,7 +24,7 @@ export async function decodeAsync<ContextType>(
2224
}
2325

2426
export function decodeArrayStream<ContextType>(
25-
streamLike: ReadableStreamLike<ArrayLike<number>>,
27+
streamLike: ReadableStreamLike<ArrayLike<number> | BufferSource>,
2628
options: DecodeOptions<SplitUndefined<ContextType>> = defaultDecodeOptions as any,
2729
) {
2830
const stream = ensureAsyncIterable(streamLike);
@@ -41,7 +43,7 @@ export function decodeArrayStream<ContextType>(
4143
}
4244

4345
export function decodeStream<ContextType>(
44-
streamLike: ReadableStreamLike<ArrayLike<number>>,
46+
streamLike: ReadableStreamLike<ArrayLike<number> | BufferSource>,
4547
options: DecodeOptions<SplitUndefined<ContextType>> = defaultDecodeOptions as any,
4648
) {
4749
const stream = ensureAsyncIterable(streamLike);

test/decodeAsync.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,4 +107,17 @@ describe("decodeAsync", () => {
107107
};
108108
assert.deepStrictEqual(await decodeAsync(createStream()), object);
109109
});
110+
111+
it("decodes BufferSource", async () => {
112+
// https://developer.mozilla.org/en-US/docs/Web/API/BufferSource
113+
const createStream = async function* () {
114+
yield [0x81] as ArrayLike<number>; // fixmap size=1
115+
yield encode("foo") as BufferSource;
116+
yield encode("bar") as BufferSource;
117+
};
118+
119+
// createStream() returns AsyncGenerator<ArrayLike<number> | BufferSource, ...>
120+
const object = await decodeAsync(createStream());
121+
assert.deepStrictEqual(object, { "foo": "bar" });
122+
});
110123
});

0 commit comments

Comments
 (0)