encoder.js 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.SlipEncoder = void 0;
  4. const stream_1 = require("stream");
  5. /**
  6. * A transform stream that emits SLIP-encoded data for each incoming packet.
  7. *
  8. * Runs in O(n) time, adding a 0xC0 character at the end of each
  9. * received packet and escaping characters, according to RFC 1055.
  10. */
  11. class SlipEncoder extends stream_1.Transform {
  12. opts;
  13. constructor(options = {}) {
  14. super(options);
  15. const { START, ESC = 0xdb, END = 0xc0, ESC_START, ESC_END = 0xdc, ESC_ESC = 0xdd, bluetoothQuirk = false } = options;
  16. this.opts = {
  17. START,
  18. ESC,
  19. END,
  20. ESC_START,
  21. ESC_END,
  22. ESC_ESC,
  23. bluetoothQuirk,
  24. };
  25. }
  26. _transform(chunk, encoding, cb) {
  27. const chunkLength = chunk.length;
  28. if (this.opts.bluetoothQuirk && chunkLength === 0) {
  29. // Edge case: push no data. Bluetooth-quirky SLIP parsers don't like
  30. // lots of 0xC0s together.
  31. return cb();
  32. }
  33. // Allocate memory for the worst-case scenario: all bytes are escaped,
  34. // plus start and end separators.
  35. const encoded = Buffer.alloc(chunkLength * 2 + 2);
  36. let j = 0;
  37. if (this.opts.bluetoothQuirk == true) {
  38. encoded[j++] = this.opts.END;
  39. }
  40. if (this.opts.START !== undefined) {
  41. encoded[j++] = this.opts.START;
  42. }
  43. for (let i = 0; i < chunkLength; i++) {
  44. let byte = chunk[i];
  45. if (byte === this.opts.START && this.opts.ESC_START) {
  46. encoded[j++] = this.opts.ESC;
  47. byte = this.opts.ESC_START;
  48. }
  49. else if (byte === this.opts.END) {
  50. encoded[j++] = this.opts.ESC;
  51. byte = this.opts.ESC_END;
  52. }
  53. else if (byte === this.opts.ESC) {
  54. encoded[j++] = this.opts.ESC;
  55. byte = this.opts.ESC_ESC;
  56. }
  57. encoded[j++] = byte;
  58. }
  59. encoded[j++] = this.opts.END;
  60. cb(null, encoded.slice(0, j));
  61. }
  62. }
  63. exports.SlipEncoder = SlipEncoder;