提交 f701dd50 编写于 作者: K katainaka0503

Refactor stream.ts

上级 9ee29afe
......@@ -91,14 +91,5 @@ export function detectEncodingByBOMFromBuffer(buffer: NodeBuffer, bytesRead: num
* If no BOM is detected, null will be passed to callback.
*/
export function detectEncodingByBOM(file: string): TPromise<string> {
return new TPromise((complete, error) => {
stream.readExactlyByFile(file, 3, (err: Error, buffer: NodeBuffer, bytesRead: number) => {
if (err) {
error(err);
} else {
complete(detectEncodingByBOMFromBuffer(buffer, bytesRead));
}
});
});
return stream.readExactlyByFile(file, 3).then(({buffer, bytesRead}) => detectEncodingByBOMFromBuffer(buffer, bytesRead));
}
\ No newline at end of file
......@@ -59,37 +59,14 @@ export interface IMimeAndEncoding {
}
function doDetectMimesFromStream(instream: streams.Readable): TPromise<IMimeAndEncoding> {
return new TPromise((complete, error) =>
stream.readExactlyByStream(instream, BUFFER_READ_MAX_LEN, (err, buffer, bytesRead) => {
if (err) {
error(error);
} else {
complete(detectMimeAndEncodingFromBuffer({ buffer, bytesRead }));
}
})
);
return stream.readExactlyByStream(instream, BUFFER_READ_MAX_LEN).then(detectMimeAndEncodingFromBuffer);
}
function doDetectMimesFromFile(absolutePath: string): TPromise<IMimeAndEncoding> {
return new TPromise((complete, error) =>
stream.readExactlyByFile(absolutePath, BUFFER_READ_MAX_LEN, (err, buffer, bytesRead) => {
if (err) {
error(error);
} else {
complete(detectMimeAndEncodingFromBuffer({ buffer, bytesRead }));
}
})
);
}
export interface ReadResult {
buffer: NodeBuffer;
bytesRead: number;
return stream.readExactlyByFile(absolutePath, BUFFER_READ_MAX_LEN).then(detectMimeAndEncodingFromBuffer);
}
export function detectMimeAndEncodingFromBuffer({buffer, bytesRead}: ReadResult): IMimeAndEncoding {
export function detectMimeAndEncodingFromBuffer({buffer, bytesRead}: stream.ReadResult): IMimeAndEncoding {
let enc = encoding.detectEncodingByBOMFromBuffer(buffer, bytesRead);
// Detect 0 bytes to see if file is binary (ignore for UTF 16 though)
......
......@@ -8,94 +8,105 @@
import fs = require('fs');
import stream = require('stream');
import { TPromise } from 'vs/base/common/winjs.base';
export interface ReadResult {
buffer: NodeBuffer;
bytesRead: number;
}
/**
* Reads up to total bytes from the provided stream.
*/
export function readExactlyByStream(stream: stream.Readable, totalBytes: number, callback: (err: Error, buffer: NodeBuffer, bytesRead: number) => void): void {
let done = false;
let buffer = new Buffer(totalBytes);
let bytesRead = 0;
stream.on('data', (data: NodeBuffer) => {
let bytesToRead = Math.min(totalBytes - bytesRead, data.length);
data.copy(buffer, bytesRead, 0, bytesToRead);
bytesRead += bytesToRead;
if (bytesRead === totalBytes) {
stream.destroy(); // Will trigger the close event eventually
}
});
stream.on('error', (e: Error) => {
if (!done) {
done = true;
callback(e, null, null);
}
});
let onSuccess = () => {
if (!done) {
done = true;
callback(null, buffer, bytesRead);
}
};
stream.on('close', onSuccess);
export function readExactlyByStream(stream: stream.Readable, totalBytes: number): TPromise<ReadResult> {
return new TPromise((complete, error) => {
let done = false;
let buffer = new Buffer(totalBytes);
let bytesRead = 0;
stream.on('data', (data: NodeBuffer) => {
let bytesToRead = Math.min(totalBytes - bytesRead, data.length);
data.copy(buffer, bytesRead, 0, bytesToRead);
bytesRead += bytesToRead;
if (bytesRead === totalBytes) {
stream.destroy(); // Will trigger the close event eventually
}
});
stream.on('error', (e: Error) => {
if (!done) {
done = true;
error(e);
}
});
let onSuccess = () => {
if (!done) {
done = true;
complete({ buffer, bytesRead });
}
};
stream.on('close', onSuccess);
});
}
/**
* Reads totalBytes from the provided file.
*/
export function readExactlyByFile(file: string, totalBytes: number, callback: (error: Error, buffer: NodeBuffer, bytesRead: number) => void): void {
fs.open(file, 'r', null, (err, fd) => {
if (err) {
return callback(err, null, 0);
}
function end(err: Error, resultBuffer: NodeBuffer, bytesRead: number): void {
fs.close(fd, (closeError: Error) => {
if (closeError) {
return callback(closeError, null, bytesRead);
}
if (err && (<any>err).code === 'EISDIR') {
return callback(err, null, bytesRead); // we want to bubble this error up (file is actually a folder)
}
return callback(null, resultBuffer, bytesRead);
});
}
let buffer = new Buffer(totalBytes);
let bytesRead = 0;
let zeroAttempts = 0;
function loop(): void {
fs.read(fd, buffer, bytesRead, totalBytes - bytesRead, null, (err, moreBytesRead) => {
if (err) {
return end(err, null, 0);
}
// Retry up to N times in case 0 bytes where read
if (moreBytesRead === 0) {
if (++zeroAttempts === 10) {
return end(null, buffer, bytesRead);
}
return loop();
}
bytesRead += moreBytesRead;
if (bytesRead === totalBytes) {
return end(null, buffer, bytesRead);
}
return loop();
});
}
loop();
});
export function readExactlyByFile(file: string, totalBytes: number): TPromise<ReadResult> {
return new TPromise((complete, error) => {
fs.open(file, 'r', null, (err, fd) => {
if (err) {
return error(err);
}
function end(err: Error, resultBuffer: NodeBuffer, bytesRead: number): void {
fs.close(fd, (closeError: Error) => {
if (closeError) {
return error(closeError);
}
if (err && (<any>err).code === 'EISDIR') {
return error(err); // we want to bubble this error up (file is actually a folder)
}
return complete({ buffer:resultBuffer, bytesRead });
});
}
let buffer = new Buffer(totalBytes);
let bytesRead = 0;
let zeroAttempts = 0;
function loop(): void {
fs.read(fd, buffer, bytesRead, totalBytes - bytesRead, null, (err, moreBytesRead) => {
if (err) {
return end(err, null, 0);
}
// Retry up to N times in case 0 bytes where read
if (moreBytesRead === 0) {
if (++zeroAttempts === 10) {
return end(null, buffer, bytesRead);
}
return loop();
}
bytesRead += moreBytesRead;
if (bytesRead === totalBytes) {
return end(null, buffer, bytesRead);
}
return loop();
});
}
loop();
});
});
}
/**
......@@ -107,59 +118,61 @@ export function readExactlyByFile(file: string, totalBytes: number, callback: (e
* @param maximumBytesToRead The maximum number of bytes to read before giving up.
* @param callback The finished callback.
*/
export function readToMatchingString(file: string, matchingString: string, chunkBytes: number, maximumBytesToRead: number, callback: (error: Error, result: string) => void): void {
fs.open(file, 'r', null, (err, fd) => {
if (err) {
return callback(err, null);
}
function end(err: Error, result: string): void {
fs.close(fd, (closeError: Error) => {
if (closeError) {
return callback(closeError, null);
}
if (err && (<any>err).code === 'EISDIR') {
return callback(err, null); // we want to bubble this error up (file is actually a folder)
}
return callback(null, result);
});
}
let buffer = new Buffer(maximumBytesToRead);
let bytesRead = 0;
let zeroAttempts = 0;
function loop(): void {
fs.read(fd, buffer, bytesRead, chunkBytes, null, (err, moreBytesRead) => {
if (err) {
return end(err, null);
}
// Retry up to N times in case 0 bytes where read
if (moreBytesRead === 0) {
if (++zeroAttempts === 10) {
return end(null, null);
}
return loop();
}
bytesRead += moreBytesRead;
const newLineIndex = buffer.indexOf(matchingString);
if (newLineIndex >= 0) {
return end(null, buffer.toString('utf8').substr(0, newLineIndex));
}
if (bytesRead >= maximumBytesToRead) {
return end(new Error(`Could not find ${matchingString} in first ${maximumBytesToRead} bytes of ${file}`), null);
}
return loop();
});
}
loop();
});
export function readToMatchingString(file: string, matchingString: string, chunkBytes: number, maximumBytesToRead: number): TPromise<string> {
return new TPromise((complete, error) =>
fs.open(file, 'r', null, (err, fd) => {
if (err) {
return error(err);
}
function end(err: Error, result: string): void {
fs.close(fd, (closeError: Error) => {
if (closeError) {
return error(closeError);
}
if (err && (<any>err).code === 'EISDIR') {
return error(err); // we want to bubble this error up (file is actually a folder)
}
return complete(result);
});
}
let buffer = new Buffer(maximumBytesToRead);
let bytesRead = 0;
let zeroAttempts = 0;
function loop(): void {
fs.read(fd, buffer, bytesRead, chunkBytes, null, (err, moreBytesRead) => {
if (err) {
return end(err, null);
}
// Retry up to N times in case 0 bytes where read
if (moreBytesRead === 0) {
if (++zeroAttempts === 10) {
return end(null, null);
}
return loop();
}
bytesRead += moreBytesRead;
const newLineIndex = buffer.indexOf(matchingString);
if (newLineIndex >= 0) {
return end(null, buffer.toString('utf8').substr(0, newLineIndex));
}
if (bytesRead >= maximumBytesToRead) {
return end(new Error(`Could not find ${matchingString} in first ${maximumBytesToRead} bytes of ${file}`), null);
}
return loop();
});
}
loop();
})
);
}
\ No newline at end of file
......@@ -11,72 +11,61 @@ import fs = require('fs');
import stream = require('vs/base/node/stream');
suite('Stream', () => {
test('readExactlyByFile - ANSI', function (done: () => void) {
test('readExactlyByFile - ANSI', function (done: (err?) => void) {
const file = require.toUrl('./fixtures/file.css');
stream.readExactlyByFile(file, 10, (error: Error, buffer: NodeBuffer, count: number) => {
assert.equal(error, null);
assert.equal(count, 10);
stream.readExactlyByFile(file, 10).then(({buffer, bytesRead}) => {
assert.equal(bytesRead, 10);
assert.equal(buffer.toString(), '/*--------');
done();
});
}, done);
});
test('readExactlyByFile - empty', function (done: () => void) {
test('readExactlyByFile - empty', function (done: (err?: any) => void) {
const file = require.toUrl('./fixtures/empty.txt');
stream.readExactlyByFile(file, 10, (error: Error, buffer: NodeBuffer, count: number) => {
assert.equal(error, null);
assert.equal(count, 0);
stream.readExactlyByFile(file, 10).then(({bytesRead}) => {
assert.equal(bytesRead, 0);
done();
});
}, done);
});
test('readExactlyByStream - ANSI', function (done: () => void) {
test('readExactlyByStream - ANSI', function (done: (err?: any) => void) {
const file = require.toUrl('./fixtures/file.css');
stream.readExactlyByStream(fs.createReadStream(file), 10, (error: Error, buffer: NodeBuffer, count: number) => {
assert.equal(error, null);
assert.equal(count, 10);
stream.readExactlyByStream(fs.createReadStream(file), 10).then(({buffer, bytesRead}) => {
assert.equal(bytesRead, 10);
assert.equal(buffer.toString(), '/*--------');
done();
});
}, done);
});
test('readExactlyByStream - empty', function (done: () => void) {
test('readExactlyByStream - empty', function (done: (err?: any) => void) {
const file = require.toUrl('./fixtures/empty.txt');
stream.readExactlyByStream(fs.createReadStream(file), 10, (error: Error, buffer: NodeBuffer, count: number) => {
assert.equal(error, null);
assert.equal(count, 0);
stream.readExactlyByStream(fs.createReadStream(file), 10).then(({bytesRead}) => {
assert.equal(bytesRead, 0);
done();
});
}, done);
});
test('readToMatchingString - ANSI', function (done: () => void) {
test('readToMatchingString - ANSI', function (done: (err?: any) => void) {
const file = require.toUrl('./fixtures/file.css');
stream.readToMatchingString(file, '\n', 10, 100, (error: Error, result: string) => {
assert.equal(error, null);
stream.readToMatchingString(file, '\n', 10, 100).then ((result: string) => {
// \r may be present on Windows
assert.equal(result.replace('\r', ''), '/*---------------------------------------------------------------------------------------------');
done();
});
}, done);
});
test('readToMatchingString - empty', function (done: () => void) {
test('readToMatchingString - empty', function (done: (err?: any) => void) {
const file = require.toUrl('./fixtures/empty.txt');
stream.readToMatchingString(file, '\n', 10, 100, (error: Error, result: string) => {
assert.equal(error, null);
stream.readToMatchingString(file, '\n', 10, 100).then((result: string) => {
assert.equal(result, null);
done();
});
}, done);
});
});
\ No newline at end of file
......@@ -229,15 +229,10 @@ export class BackupFileService implements IBackupFileService {
const readPromises: TPromise<Uri>[] = [];
model.get().forEach(fileBackup => {
readPromises.push(new TPromise<Uri>((c, e) => {
readToMatchingString(fileBackup.fsPath, BackupFileService.META_MARKER, 2000, 10000, (error, result) => {
if (result === null) {
e(error);
}
c(Uri.parse(result));
});
}));
readPromises.push(
readToMatchingString(fileBackup.fsPath, BackupFileService.META_MARKER, 2000, 10000)
.then(Uri.parse)
);
});
return TPromise.join(readPromises);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册