Skip to content

Commit 4002404

Browse files
author
Benjamin Pasero
committed
files - reduce need for stream transformer in io.ts
1 parent d7aaede commit 4002404

3 files changed

Lines changed: 46 additions & 28 deletions

File tree

src/vs/platform/files/common/fileService.ts

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { isReadableStream, transform, ReadableStreamEvents, consumeReadableWithL
1818
import { Queue } from 'vs/base/common/async';
1919
import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cancellation';
2020
import { Schemas } from 'vs/base/common/network';
21-
import { createReadStream } from 'vs/platform/files/common/io';
21+
import { createVSBufferReadStream } from 'vs/platform/files/common/io';
2222

2323
export class FileService extends Disposable implements IFileService {
2424

@@ -461,23 +461,18 @@ export class FileService extends Disposable implements IFileService {
461461
private readFileStreamed(provider: IFileSystemProviderWithFileReadStreamCapability, resource: URI, token: CancellationToken, options: IReadFileOptions = Object.create(null)): VSBufferReadableStream {
462462
const fileStream = provider.readFileStream(resource, options, token);
463463

464-
return this.transformFileReadStream(resource, fileStream, options);
464+
return transform(fileStream, {
465+
data: data => data instanceof VSBuffer ? data : VSBuffer.wrap(data),
466+
error: error => new FileOperationError(localize('err.read', "Unable to read file '{0}' ({1})", this.resourceForError(resource), ensureFileSystemProviderError(error).toString()), toFileOperationResult(error), options)
467+
}, data => VSBuffer.concat(data));
465468
}
466469

467470
private readFileBuffered(provider: IFileSystemProviderWithOpenReadWriteCloseCapability, resource: URI, token: CancellationToken, options: IReadFileOptions = Object.create(null)): VSBufferReadableStream {
468-
const fileStream = createReadStream(provider, resource, {
471+
return createVSBufferReadStream(provider, resource, {
469472
...options,
470-
bufferSize: this.BUFFER_SIZE
473+
bufferSize: this.BUFFER_SIZE,
474+
errorTransformer: error => new FileOperationError(localize('err.read', "Unable to read file '{0}' ({1})", this.resourceForError(resource), ensureFileSystemProviderError(error).toString()), toFileOperationResult(error), options)
471475
}, token);
472-
473-
return this.transformFileReadStream(resource, fileStream, options);
474-
}
475-
476-
private transformFileReadStream(resource: URI, stream: ReadableStreamEvents<Uint8Array | VSBuffer>, options: IReadFileOptions): VSBufferReadableStream {
477-
return transform(stream, {
478-
data: data => data instanceof VSBuffer ? data : VSBuffer.wrap(data),
479-
error: error => new FileOperationError(localize('err.read', "Unable to read file '{0}' ({1})", this.resourceForError(resource), ensureFileSystemProviderError(error).toString()), toFileOperationResult(error), options)
480-
}, data => VSBuffer.concat(data));
481476
}
482477

483478
private async readFileUnbuffered(provider: IFileSystemProviderWithFileReadWriteCapability, resource: URI, options?: IReadFileOptions): Promise<VSBufferReadableStream> {

src/vs/platform/files/common/io.ts

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,58 @@
55

66
import { localize } from 'vs/nls';
77
import { URI } from 'vs/base/common/uri';
8-
import { VSBuffer, VSBufferWriteableStream, newWriteableBufferStream, VSBufferReadableStream } from 'vs/base/common/buffer';
8+
import { VSBuffer, newWriteableBufferStream, VSBufferReadableStream } from 'vs/base/common/buffer';
99
import { CancellationToken } from 'vs/base/common/cancellation';
1010
import { IFileSystemProviderWithOpenReadWriteCloseCapability, FileReadStreamOptions, createFileSystemProviderError, FileSystemProviderErrorCode, ensureFileSystemProviderError } from 'vs/platform/files/common/files';
1111
import { canceled } from 'vs/base/common/errors';
12+
import { IErrorTransformer, IDataTransformer, ReadableStream, WriteableStream, newWriteableStream } from 'vs/base/common/stream';
1213

1314
export interface ICreateReadStreamOptions extends FileReadStreamOptions {
1415

1516
/**
1617
* The size of the buffer to use before sending to the stream.
1718
*/
1819
bufferSize: number;
20+
21+
/**
22+
* Allows to massage any possibly error that happens during reading.
23+
*/
24+
errorTransformer?: IErrorTransformer;
1925
}
2026

21-
export function createReadStream(provider: IFileSystemProviderWithOpenReadWriteCloseCapability, resource: URI, options: ICreateReadStreamOptions, token?: CancellationToken): VSBufferReadableStream {
27+
export function createVSBufferReadStream(provider: IFileSystemProviderWithOpenReadWriteCloseCapability, resource: URI, options: ICreateReadStreamOptions, token?: CancellationToken): VSBufferReadableStream {
2228
const stream = newWriteableBufferStream();
2329

24-
// do not await reading but simply return the stream directly since it operates
25-
// via events. finally end the stream and send through the possible error
26-
let error: Error | undefined = undefined;
30+
readFileIntoStream(provider, resource, stream, data => data, options, token);
2731

28-
doReadFileIntoStream(provider, resource, stream, options, token).then(undefined, err => error = err).finally(() => stream.end(error));
32+
return stream;
33+
}
34+
35+
export function createUint8ArrayReadStream(provider: IFileSystemProviderWithOpenReadWriteCloseCapability, resource: URI, options: ICreateReadStreamOptions, token?: CancellationToken): ReadableStream<Uint8Array> {
36+
const stream = newWriteableStream<Uint8Array>(data => VSBuffer.concat(data.map(data => VSBuffer.wrap(data))).buffer);
37+
38+
readFileIntoStream(provider, resource, stream, data => data.buffer, options, token);
2939

3040
return stream;
3141
}
3242

33-
async function doReadFileIntoStream(provider: IFileSystemProviderWithOpenReadWriteCloseCapability, resource: URI, stream: VSBufferWriteableStream, options: ICreateReadStreamOptions, token?: CancellationToken): Promise<void> {
43+
async function readFileIntoStream<T>(provider: IFileSystemProviderWithOpenReadWriteCloseCapability, resource: URI, stream: WriteableStream<T>, transformer: IDataTransformer<VSBuffer, T>, options: ICreateReadStreamOptions, token?: CancellationToken): Promise<void> {
44+
let error: Error | undefined = undefined;
45+
46+
try {
47+
await doReadFileIntoStream(provider, resource, stream, transformer, options, token);
48+
} catch (err) {
49+
error = err;
50+
} finally {
51+
if (error && options.errorTransformer) {
52+
error = options.errorTransformer(error);
53+
}
54+
55+
stream.end(error);
56+
}
57+
}
58+
59+
async function doReadFileIntoStream<T>(provider: IFileSystemProviderWithOpenReadWriteCloseCapability, resource: URI, stream: WriteableStream<T>, transformer: IDataTransformer<VSBuffer, T>, options: ICreateReadStreamOptions, token?: CancellationToken): Promise<void> {
3460

3561
// Check for cancellation
3662
throwIfCancelled(token);
@@ -65,7 +91,7 @@ async function doReadFileIntoStream(provider: IFileSystemProviderWithOpenReadWri
6591

6692
// when buffer full, create a new one and emit it through stream
6793
if (posInBuffer === buffer.byteLength) {
68-
stream.write(buffer);
94+
stream.write(transformer(buffer));
6995

7096
buffer = VSBuffer.alloc(Math.min(options.bufferSize, typeof allowedRemainingBytes === 'number' ? allowedRemainingBytes : options.bufferSize));
7197

@@ -80,7 +106,7 @@ async function doReadFileIntoStream(provider: IFileSystemProviderWithOpenReadWri
80106
lastChunkLength = Math.min(posInBuffer, allowedRemainingBytes);
81107
}
82108

83-
stream.write(buffer.slice(0, lastChunkLength));
109+
stream.write(transformer(buffer.slice(0, lastChunkLength)));
84110
}
85111
} catch (error) {
86112
throw ensureFileSystemProviderError(error);

src/vs/platform/files/node/diskFileSystemProvider.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,9 @@ import { FileWatcher as UnixWatcherService } from 'vs/platform/files/node/watche
2222
import { FileWatcher as WindowsWatcherService } from 'vs/platform/files/node/watcher/win32/watcherService';
2323
import { FileWatcher as NsfwWatcherService } from 'vs/platform/files/node/watcher/nsfw/watcherService';
2424
import { FileWatcher as NodeJSWatcherService } from 'vs/platform/files/node/watcher/nodejs/watcherService';
25-
import { VSBuffer } from 'vs/base/common/buffer';
2625
import { CancellationToken } from 'vs/base/common/cancellation';
27-
import { ReadableStreamEvents, transform } from 'vs/base/common/stream';
28-
import { createReadStream } from 'vs/platform/files/common/io';
26+
import { ReadableStreamEvents } from 'vs/base/common/stream';
27+
import { createUint8ArrayReadStream } from 'vs/platform/files/common/io';
2928
import { insert } from 'vs/base/common/arrays';
3029

3130
export interface IWatcherOptions {
@@ -155,12 +154,10 @@ export class DiskFileSystemProvider extends Disposable implements
155154
}
156155

157156
readFileStream(resource: URI, opts: FileReadStreamOptions, token?: CancellationToken): ReadableStreamEvents<Uint8Array> {
158-
const fileStream = createReadStream(this, resource, {
157+
return createUint8ArrayReadStream(this, resource, {
159158
...opts,
160159
bufferSize: this.BUFFER_SIZE
161160
}, token);
162-
163-
return transform(fileStream, { data: data => data.buffer }, data => VSBuffer.concat(data.map(data => VSBuffer.wrap(data))).buffer);
164161
}
165162

166163
async writeFile(resource: URI, content: Uint8Array, opts: FileWriteOptions): Promise<void> {

0 commit comments

Comments
 (0)