parser-ready/ready.js



const Transform = require('stream').Transform;

/**
 * A transform stream that waits for a sequence of "ready" bytes before emitting a ready event and emitting data events
 * @summary To use the `Ready` parser provide a byte start sequence. After the bytes have been received a ready event is fired and data events are passed through.
 * @extends Transform
 * @example
const SerialPort = require('serialport')
const Ready = require('@serialport/parser-ready')
const port = new SerialPort('/dev/tty-usbserial1')
const parser = port.pipe(new Ready({ delimiter: 'READY' }))
parser.on('ready', () => console.log('the ready byte sequence has been received'))
parser.on('data', console.log) // all data after READY is received
 */
class ReadyParser extends Transform {
  /**
   *
   * @param {object} options options for the parser
   * @param {string|Buffer|array} options.delimiter data to look for before emitted "ready"
   */
  constructor(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');
    }

    super(options);
    this.delimiter = Buffer.from(options.delimiter);
    this.readOffset = 0;
    this.ready = false;
  }

  _transform(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;