88import fs = require( 'fs' ) ;
99import stream = require( 'stream' ) ;
1010
11+ import { TPromise } from 'vs/base/common/winjs.base' ;
12+
13+ export interface ReadResult {
14+ buffer : NodeBuffer ;
15+ bytesRead : number ;
16+ }
17+
1118/**
1219 * Reads up to total bytes from the provided stream.
1320 */
14- export function readExactlyByStream ( stream : stream . Readable , totalBytes : number , callback : ( err : Error , buffer : NodeBuffer , bytesRead : number ) => void ) : void {
15- let done = false ;
16- let buffer = new Buffer ( totalBytes ) ;
17- let bytesRead = 0 ;
18-
19- stream . on ( 'data' , ( data : NodeBuffer ) => {
20- let bytesToRead = Math . min ( totalBytes - bytesRead , data . length ) ;
21- data . copy ( buffer , bytesRead , 0 , bytesToRead ) ;
22- bytesRead += bytesToRead ;
23-
24- if ( bytesRead === totalBytes ) {
25- stream . destroy ( ) ; // Will trigger the close event eventually
26- }
27- } ) ;
28-
29- stream . on ( 'error' , ( e : Error ) => {
30- if ( ! done ) {
31- done = true ;
32- callback ( e , null , null ) ;
33- }
34- } ) ;
35-
36- let onSuccess = ( ) => {
37- if ( ! done ) {
38- done = true ;
39- callback ( null , buffer , bytesRead ) ;
40- }
41- } ;
42-
43- stream . on ( 'close' , onSuccess ) ;
21+ export function readExactlyByStream ( stream : stream . Readable , totalBytes : number ) : TPromise < ReadResult > {
22+ return new TPromise ( ( complete , error ) => {
23+ let done = false ;
24+ let buffer = new Buffer ( totalBytes ) ;
25+ let bytesRead = 0 ;
26+
27+ stream . on ( 'data' , ( data : NodeBuffer ) => {
28+ let bytesToRead = Math . min ( totalBytes - bytesRead , data . length ) ;
29+ data . copy ( buffer , bytesRead , 0 , bytesToRead ) ;
30+ bytesRead += bytesToRead ;
31+
32+ if ( bytesRead === totalBytes ) {
33+ stream . destroy ( ) ; // Will trigger the close event eventually
34+ }
35+ } ) ;
36+
37+ stream . on ( 'error' , ( e : Error ) => {
38+ if ( ! done ) {
39+ done = true ;
40+ error ( e ) ;
41+ }
42+ } ) ;
43+
44+ let onSuccess = ( ) => {
45+ if ( ! done ) {
46+ done = true ;
47+ complete ( { buffer, bytesRead } ) ;
48+ }
49+ } ;
50+
51+ stream . on ( 'close' , onSuccess ) ;
52+ } ) ;
4453}
4554
4655/**
4756 * Reads totalBytes from the provided file.
4857 */
49- export function readExactlyByFile ( file : string , totalBytes : number , callback : ( error : Error , buffer : NodeBuffer , bytesRead : number ) => void ) : void {
50- fs . open ( file , 'r' , null , ( err , fd ) => {
51- if ( err ) {
52- return callback ( err , null , 0 ) ;
53- }
54-
55- function end ( err : Error , resultBuffer : NodeBuffer , bytesRead : number ) : void {
56- fs . close ( fd , ( closeError : Error ) => {
57- if ( closeError ) {
58- return callback ( closeError , null , bytesRead ) ;
59- }
60-
61- if ( err && ( < any > err ) . code === 'EISDIR' ) {
62- return callback ( err , null , bytesRead ) ; // we want to bubble this error up (file is actually a folder)
63- }
64-
65- return callback ( null , resultBuffer , bytesRead ) ;
66- } ) ;
67- }
68-
69- let buffer = new Buffer ( totalBytes ) ;
70- let bytesRead = 0 ;
71- let zeroAttempts = 0 ;
72- function loop ( ) : void {
73- fs . read ( fd , buffer , bytesRead , totalBytes - bytesRead , null , ( err , moreBytesRead ) => {
74- if ( err ) {
75- return end ( err , null , 0 ) ;
76- }
77-
78- // Retry up to N times in case 0 bytes where read
79- if ( moreBytesRead === 0 ) {
80- if ( ++ zeroAttempts === 10 ) {
81- return end ( null , buffer , bytesRead ) ;
82- }
83-
84- return loop ( ) ;
85- }
86-
87- bytesRead += moreBytesRead ;
88-
89- if ( bytesRead === totalBytes ) {
90- return end ( null , buffer , bytesRead ) ;
91- }
92-
93- return loop ( ) ;
94- } ) ;
95- }
96-
97- loop ( ) ;
98- } ) ;
58+ export function readExactlyByFile ( file : string , totalBytes : number ) : TPromise < ReadResult > {
59+ return new TPromise ( ( complete , error ) => {
60+ fs . open ( file , 'r' , null , ( err , fd ) => {
61+ if ( err ) {
62+ return error ( err ) ;
63+ }
64+
65+ function end ( err : Error , resultBuffer : NodeBuffer , bytesRead : number ) : void {
66+ fs . close ( fd , ( closeError : Error ) => {
67+ if ( closeError ) {
68+ return error ( closeError ) ;
69+ }
70+
71+ if ( err && ( < any > err ) . code === 'EISDIR' ) {
72+ return error ( err ) ; // we want to bubble this error up (file is actually a folder)
73+ }
74+
75+ return complete ( { buffer :resultBuffer , bytesRead } ) ;
76+ } ) ;
77+ }
78+
79+ let buffer = new Buffer ( totalBytes ) ;
80+ let bytesRead = 0 ;
81+ let zeroAttempts = 0 ;
82+ function loop ( ) : void {
83+ fs . read ( fd , buffer , bytesRead , totalBytes - bytesRead , null , ( err , moreBytesRead ) => {
84+ if ( err ) {
85+ return end ( err , null , 0 ) ;
86+ }
87+
88+ // Retry up to N times in case 0 bytes where read
89+ if ( moreBytesRead === 0 ) {
90+ if ( ++ zeroAttempts === 10 ) {
91+ return end ( null , buffer , bytesRead ) ;
92+ }
93+
94+ return loop ( ) ;
95+ }
96+
97+ bytesRead += moreBytesRead ;
98+
99+ if ( bytesRead === totalBytes ) {
100+ return end ( null , buffer , bytesRead ) ;
101+ }
102+
103+ return loop ( ) ;
104+ } ) ;
105+ }
106+
107+ loop ( ) ;
108+ } ) ;
109+ } ) ;
99110}
100111
101112/**
@@ -107,59 +118,61 @@ export function readExactlyByFile(file: string, totalBytes: number, callback: (e
107118 * @param maximumBytesToRead The maximum number of bytes to read before giving up.
108119 * @param callback The finished callback.
109120 */
110- export function readToMatchingString ( file : string , matchingString : string , chunkBytes : number , maximumBytesToRead : number , callback : ( error : Error , result : string ) => void ) : void {
111- fs . open ( file , 'r' , null , ( err , fd ) => {
112- if ( err ) {
113- return callback ( err , null ) ;
114- }
115-
116- function end ( err : Error , result : string ) : void {
117- fs . close ( fd , ( closeError : Error ) => {
118- if ( closeError ) {
119- return callback ( closeError , null ) ;
120- }
121-
122- if ( err && ( < any > err ) . code === 'EISDIR' ) {
123- return callback ( err , null ) ; // we want to bubble this error up (file is actually a folder)
124- }
125-
126- return callback ( null , result ) ;
127- } ) ;
128- }
129-
130- let buffer = new Buffer ( maximumBytesToRead ) ;
131- let bytesRead = 0 ;
132- let zeroAttempts = 0 ;
133- function loop ( ) : void {
134- fs . read ( fd , buffer , bytesRead , chunkBytes , null , ( err , moreBytesRead ) => {
135- if ( err ) {
136- return end ( err , null ) ;
137- }
138-
139- // Retry up to N times in case 0 bytes where read
140- if ( moreBytesRead === 0 ) {
141- if ( ++ zeroAttempts === 10 ) {
142- return end ( null , null ) ;
143- }
144-
145- return loop ( ) ;
146- }
147-
148- bytesRead += moreBytesRead ;
149-
150- const newLineIndex = buffer . indexOf ( matchingString ) ;
151- if ( newLineIndex >= 0 ) {
152- return end ( null , buffer . toString ( 'utf8' ) . substr ( 0 , newLineIndex ) ) ;
153- }
154-
155- if ( bytesRead >= maximumBytesToRead ) {
156- return end ( new Error ( `Could not find ${ matchingString } in first ${ maximumBytesToRead } bytes of ${ file } ` ) , null ) ;
157- }
158-
159- return loop ( ) ;
160- } ) ;
161- }
162-
163- loop ( ) ;
164- } ) ;
121+ export function readToMatchingString ( file : string , matchingString : string , chunkBytes : number , maximumBytesToRead : number ) : TPromise < string > {
122+ return new TPromise ( ( complete , error ) =>
123+ fs . open ( file , 'r' , null , ( err , fd ) => {
124+ if ( err ) {
125+ return error ( err ) ;
126+ }
127+
128+ function end ( err : Error , result : string ) : void {
129+ fs . close ( fd , ( closeError : Error ) => {
130+ if ( closeError ) {
131+ return error ( closeError ) ;
132+ }
133+
134+ if ( err && ( < any > err ) . code === 'EISDIR' ) {
135+ return error ( err ) ; // we want to bubble this error up (file is actually a folder)
136+ }
137+
138+ return complete ( result ) ;
139+ } ) ;
140+ }
141+
142+ let buffer = new Buffer ( maximumBytesToRead ) ;
143+ let bytesRead = 0 ;
144+ let zeroAttempts = 0 ;
145+ function loop ( ) : void {
146+ fs . read ( fd , buffer , bytesRead , chunkBytes , null , ( err , moreBytesRead ) => {
147+ if ( err ) {
148+ return end ( err , null ) ;
149+ }
150+
151+ // Retry up to N times in case 0 bytes where read
152+ if ( moreBytesRead === 0 ) {
153+ if ( ++ zeroAttempts === 10 ) {
154+ return end ( null , null ) ;
155+ }
156+
157+ return loop ( ) ;
158+ }
159+
160+ bytesRead += moreBytesRead ;
161+
162+ const newLineIndex = buffer . indexOf ( matchingString ) ;
163+ if ( newLineIndex >= 0 ) {
164+ return end ( null , buffer . toString ( 'utf8' ) . substr ( 0 , newLineIndex ) ) ;
165+ }
166+
167+ if ( bytesRead >= maximumBytesToRead ) {
168+ return end ( new Error ( `Could not find ${ matchingString } in first ${ maximumBytesToRead } bytes of ${ file } ` ) , null ) ;
169+ }
170+
171+ return loop ( ) ;
172+ } ) ;
173+ }
174+
175+ loop ( ) ;
176+ } )
177+ ) ;
165178}
0 commit comments