Skip to content

Commit 78248cd

Browse files
committed
Support bundle reader for Node
1 parent aa455bf commit 78248cd

File tree

5 files changed

+81
-35
lines changed

5 files changed

+81
-35
lines changed

packages/firestore/src/platform/platform.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ export interface Platform {
5050
*/
5151
randomBytes(nBytes: number): Uint8Array;
5252

53+
toByteStreamReader(source: unknown): ByteStreamReader;
54+
5355
/** The Platform's 'window' implementation or null if not available. */
5456
readonly window: Window | null;
5557

@@ -60,6 +62,36 @@ export interface Platform {
6062
readonly base64Available: boolean;
6163
}
6264

65+
export interface ByteStreamReader {
66+
read(): Promise<ByteStreamReadResult>;
67+
}
68+
69+
export interface ByteStreamReadResult {
70+
done: boolean;
71+
value: Uint8Array;
72+
}
73+
74+
export function toByteStreamReader(
75+
source: Uint8Array,
76+
bytesPerRead = 10240
77+
): ByteStreamReader {
78+
let readFrom = 0;
79+
return new (class implements ByteStreamReader {
80+
async read(): Promise<ByteStreamReadResult> {
81+
if (readFrom < source.byteLength) {
82+
const result = {
83+
value: source.slice(readFrom, readFrom + bytesPerRead),
84+
done: false
85+
};
86+
readFrom += bytesPerRead;
87+
return result;
88+
}
89+
90+
return { value: new Uint8Array(), done: true };
91+
}
92+
})();
93+
}
94+
6395
/**
6496
* Provides singleton helpers where setup code can inject a platform at runtime.
6597
* setPlatform needs to be set before Firestore is used and must be set exactly

packages/firestore/src/platform_browser/browser_platform.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@
1616
*/
1717

1818
import { DatabaseId, DatabaseInfo } from '../core/database_info';
19-
import { Platform } from '../platform/platform';
19+
import {
20+
ByteStreamReader,
21+
ByteStreamReadResult,
22+
Platform,
23+
toByteStreamReader
24+
} from '../platform/platform';
2025
import { Connection } from '../remote/connection';
2126
import { JsonProtoSerializer } from '../remote/serializer';
2227
import { ConnectivityMonitor } from './../remote/connectivity_monitor';
@@ -93,4 +98,24 @@ export class BrowserPlatform implements Platform {
9398
}
9499
return bytes;
95100
}
101+
102+
toByteStreamReader(source: unknown): ByteStreamReader {
103+
if (source instanceof Uint8Array) {
104+
return toByteStreamReader(source);
105+
}
106+
if (source instanceof ArrayBuffer) {
107+
return toByteStreamReader(new Uint8Array(source));
108+
}
109+
if (source instanceof ReadableStream) {
110+
const reader = source.getReader();
111+
return new (class implements ByteStreamReader {
112+
read(): Promise<ByteStreamReadResult> {
113+
return reader.read();
114+
}
115+
})();
116+
}
117+
throw new Error(
118+
'Source of `toByteStreamReader` has to be Uint8Array, ArrayBuffer or ReadableStream'
119+
);
120+
}
96121
}

packages/firestore/src/platform_node/node_platform.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@ import { randomBytes } from 'crypto';
1919
import { inspect } from 'util';
2020

2121
import { DatabaseId, DatabaseInfo } from '../core/database_info';
22-
import { Platform } from '../platform/platform';
22+
import {
23+
ByteStreamReader,
24+
Platform,
25+
toByteStreamReader
26+
} from '../platform/platform';
2327
import { Connection } from '../remote/connection';
2428
import { JsonProtoSerializer } from '../remote/serializer';
2529
import { Code, FirestoreError } from '../util/error';
@@ -83,4 +87,11 @@ export class NodePlatform implements Platform {
8387

8488
return randomBytes(nBytes);
8589
}
90+
91+
toByteStreamReader(source: unknown): ByteStreamReader {
92+
if (source instanceof Uint8Array) {
93+
return toByteStreamReader(source);
94+
}
95+
throw new Error('Source of `toByteStreamReader` has to be Uint8Array');
96+
}
8697
}

packages/firestore/src/util/bundle_reader.ts

Lines changed: 6 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
BundleElement,
2020
BundleMetadata
2121
} from '../protos/firestore_bundle_proto';
22+
import { ByteStreamReader, PlatformSupport } from '../platform/platform';
2223

2324
/**
2425
* A complete element in the bundle stream, together with the byte length it
@@ -36,29 +37,6 @@ export class SizedBundleElement {
3637
}
3738
}
3839

39-
/**
40-
* Create a `ReadableStream` from a underlying buffer.
41-
*
42-
* @param data: Underlying buffer.
43-
* @param bytesPerRead: How many bytes to read from the underlying buffer from each read through the stream.
44-
*/
45-
export function toReadableStream(
46-
data: Uint8Array | ArrayBuffer,
47-
bytesPerRead = 10240
48-
): ReadableStream<Uint8Array | ArrayBuffer> {
49-
let readFrom = 0;
50-
return new ReadableStream({
51-
start(controller) {},
52-
async pull(controller): Promise<void> {
53-
controller.enqueue(data.slice(readFrom, readFrom + bytesPerRead));
54-
readFrom += bytesPerRead;
55-
if (readFrom >= data.byteLength) {
56-
controller.close();
57-
}
58-
}
59-
});
60-
}
61-
6240
/**
6341
* A class representing a bundle.
6442
*
@@ -68,8 +46,8 @@ export function toReadableStream(
6846
export class BundleReader {
6947
// Cached bundle metadata.
7048
private metadata?: BundleMetadata | null;
71-
// The reader instance of the given ReadableStream.
72-
private reader: ReadableStreamDefaultReader;
49+
// The reader to read from underlying binary bundle data source.
50+
private reader: ByteStreamReader;
7351
// Internal buffer to hold bundle content, accumulating incomplete element content.
7452
private buffer: Uint8Array = new Uint8Array();
7553
private textDecoder = new TextDecoder('utf-8');
@@ -80,13 +58,9 @@ export class BundleReader {
8058
| Uint8Array
8159
| ArrayBuffer
8260
) {
83-
if (
84-
bundleStream instanceof Uint8Array ||
85-
bundleStream instanceof ArrayBuffer
86-
) {
87-
this.bundleStream = toReadableStream(bundleStream);
88-
}
89-
this.reader = (this.bundleStream as ReadableStream).getReader();
61+
this.reader = PlatformSupport.getPlatform().toByteStreamReader(
62+
bundleStream
63+
);
9064
}
9165

9266
/**

packages/firestore/test/util/test_platform.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
*/
1717

1818
import { DatabaseId, DatabaseInfo } from '../../src/core/database_info';
19-
import { Platform } from '../../src/platform/platform';
19+
import { ByteStreamReader, Platform } from '../../src/platform/platform';
2020
import { Connection } from '../../src/remote/connection';
2121
import { JsonProtoSerializer } from '../../src/remote/serializer';
2222
import { debugAssert, fail } from '../../src/util/assert';
@@ -270,6 +270,10 @@ export class TestPlatform implements Platform {
270270
randomBytes(nBytes: number): Uint8Array {
271271
return this.basePlatform.randomBytes(nBytes);
272272
}
273+
274+
toByteStreamReader(source: unknown): ByteStreamReader {
275+
return this.basePlatform.toByteStreamReader(source);
276+
}
273277
}
274278

275279
/** Returns true if we are running under Node. */

0 commit comments

Comments
 (0)