-
-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Ensure flushing doesn't cause a read error which closes the port
- Loading branch information
Showing
10 changed files
with
243 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,3 +21,4 @@ node_modules | |
npm-debug.log | ||
coverage | ||
.mailmap | ||
package-lock.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,49 +1,47 @@ | ||
{ | ||
'targets': [ | ||
{ | ||
'target_name': 'serialport', | ||
'sources': [ | ||
'src/serialport.cpp' | ||
], | ||
'include_dirs': [ | ||
'<!(node -e "require(\'nan\')")' | ||
], | ||
'conditions': [ | ||
['OS=="win"', | ||
{ | ||
'sources': [ | ||
'src/serialport_win.cpp' | ||
], | ||
'msvs_settings': { | ||
'VCCLCompilerTool': { | ||
'ExceptionHandling': '2', | ||
'DisableSpecificWarnings': [ '4530', '4506' ], | ||
}, | ||
}, | ||
}, | ||
], | ||
['OS=="mac"', | ||
{ | ||
'sources': [ | ||
'src/serialport_unix.cpp', | ||
'src/poller.cpp' | ||
], | ||
'xcode_settings': { | ||
'OTHER_LDFLAGS': [ | ||
'-framework CoreFoundation -framework IOKit' | ||
] | ||
'targets': [{ | ||
'target_name': 'serialport', | ||
'sources': [ | ||
'src/serialport.cpp' | ||
], | ||
'include_dirs': [ | ||
'<!(node -e "require(\'nan\')")' | ||
], | ||
'conditions': [ | ||
['OS=="win"', | ||
{ | ||
'sources': [ | ||
'src/serialport_win.cpp' | ||
], | ||
'msvs_settings': { | ||
'VCCLCompilerTool': { | ||
'ExceptionHandling': '2', | ||
'DisableSpecificWarnings': [ '4530', '4506' ], | ||
} | ||
} | ||
], | ||
['OS!="win"', | ||
{ | ||
'sources': [ | ||
'src/serialport_unix.cpp', | ||
'src/poller.cpp' | ||
], | ||
} | ||
], | ||
['OS=="mac"', | ||
{ | ||
'sources': [ | ||
'src/serialport_unix.cpp', | ||
'src/poller.cpp' | ||
], | ||
'xcode_settings': { | ||
'OTHER_LDFLAGS': [ | ||
'-framework CoreFoundation -framework IOKit' | ||
] | ||
} | ||
], | ||
} | ||
], | ||
} | ||
], | ||
['OS!="win"', | ||
{ | ||
'sources': [ | ||
'src/serialport_unix.cpp', | ||
'src/poller.cpp' | ||
] | ||
} | ||
] | ||
] | ||
}], | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
'use strict'; | ||
const Buffer = require('safe-buffer').Buffer; | ||
const inherits = require('util').inherits; | ||
const Transform = require('stream').Transform; | ||
|
||
function ReadyParser(options) { | ||
if (!(this instanceof ReadyParser)) { | ||
return new ReadyParser(options); | ||
} | ||
Transform.call(this, options); | ||
|
||
options = options || {}; | ||
|
||
if (options.delimiter === undefined) { | ||
throw new TypeError('"delimiter" is not a bufferable object'); | ||
} | ||
|
||
if (options.delimiter.length === 0) { | ||
throw new TypeError('"delimiter" has a 0 or undefined length'); | ||
} | ||
|
||
this.delimiter = Buffer.from(options.delimiter); | ||
this.readOffset = 0; | ||
this.ready = false; | ||
} | ||
|
||
inherits(ReadyParser, Transform); | ||
|
||
ReadyParser.prototype._transform = function(chunk, encoding, cb) { | ||
if (this.ready) { | ||
this.push(chunk); | ||
return cb(); | ||
} | ||
const delimiter = this.delimiter; | ||
let chunkOffset = 0; | ||
while (this.readOffset < delimiter.length && chunkOffset < chunk.length) { | ||
if (delimiter[this.readOffset] === chunk[chunkOffset]) { | ||
this.readOffset++; | ||
} else { | ||
this.readOffset = 0; | ||
} | ||
chunkOffset++; | ||
} | ||
if (this.readOffset === delimiter.length) { | ||
this.ready = true; | ||
this.emit('ready'); | ||
const chunkRest = chunk.slice(chunkOffset); | ||
if (chunkRest.length > 0) { | ||
this.push(chunkRest); | ||
} | ||
} | ||
cb(); | ||
}; | ||
|
||
module.exports = ReadyParser; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
'use strict'; | ||
/* eslint-disable no-new */ | ||
|
||
const Buffer = require('safe-buffer').Buffer; | ||
const assert = require('chai').assert; | ||
const sinon = require('sinon'); | ||
|
||
const ReadyParser = require('../lib/parsers/ready'); | ||
|
||
describe('ReadyParser', () => { | ||
it('works without new', () => { | ||
// eslint-disable-next-line new-cap | ||
const parser = ReadyParser({ delimiter: Buffer.from([0]) }); | ||
assert.instanceOf(parser, ReadyParser); | ||
}); | ||
|
||
it('emits data received after the ready data', () => { | ||
const spy = sinon.spy(); | ||
const parser = new ReadyParser({ | ||
delimiter: Buffer.from('\n') | ||
}); | ||
parser.on('data', spy); | ||
parser.write(Buffer.from('which will you get?')); | ||
parser.write(Buffer.from('garbage\ngold')); | ||
parser.write(Buffer.from('just for you')); | ||
|
||
assert.deepEqual(spy.getCall(0).args[0], Buffer.from('gold')); | ||
assert.deepEqual(spy.getCall(1).args[0], Buffer.from('just for you')); | ||
assert(spy.calledTwice); | ||
}); | ||
|
||
it('emits the ready event before the data event', () => { | ||
const spy = sinon.spy(); | ||
const parser = new ReadyParser({ delimiter: '!' }); | ||
parser.on('ready', () => { | ||
parser.on('data', spy); | ||
}); | ||
parser.write(Buffer.from('!hi')); | ||
assert(spy.calledOnce); | ||
}); | ||
|
||
it('has a ready property', () => { | ||
const parser = new ReadyParser({ | ||
delimiter: Buffer.from('\n') | ||
}); | ||
parser.resume(); | ||
assert.isFalse(parser.ready); | ||
parser.write(Buffer.from('not the new line')); | ||
assert.isFalse(parser.ready); | ||
parser.write(Buffer.from('this is the \n')); | ||
assert.isTrue(parser.ready); | ||
}); | ||
|
||
it('throws when not provided with a delimiter', () => { | ||
assert.throws(() => { | ||
new ReadyParser({}); | ||
}); | ||
}); | ||
|
||
it('throws when called with a 0 length delimiter', () => { | ||
assert.throws(() => { | ||
new ReadyParser({ | ||
delimiter: Buffer.alloc(0) | ||
}); | ||
}); | ||
|
||
assert.throws(() => { | ||
new ReadyParser({ | ||
delimiter: '' | ||
}); | ||
}); | ||
|
||
assert.throws(() => { | ||
new ReadyParser({ | ||
delimiter: [] | ||
}); | ||
}); | ||
}); | ||
|
||
it('allows setting of the delimiter with a string', () => { | ||
new ReadyParser({ delimiter: 'string' }); | ||
}); | ||
|
||
it('allows setting of the delimiter with a buffer', () => { | ||
new ReadyParser({ delimiter: Buffer.from([1]) }); | ||
}); | ||
|
||
it('allows setting of the delimiter with an array of bytes', () => { | ||
new ReadyParser({ delimiter: [1] }); | ||
}); | ||
|
||
it('allows receiving the delimiter over small writes', () => { | ||
const spy = sinon.spy(); | ||
const parser = new ReadyParser({ | ||
delimiter: Buffer.from('READY') | ||
}); | ||
parser.on('data', spy); | ||
parser.write(Buffer.from('bad data then REA')); | ||
parser.write(Buffer.from('D')); | ||
parser.write(Buffer.from('Y')); | ||
parser.write(Buffer.from('!!!!!!')); | ||
|
||
assert.deepEqual(spy.getCall(0).args[0], Buffer.from('!!!!!!')); | ||
assert(spy.calledOnce); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters