@pamoja/serial 0.1.15 → 0.1.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Ergonomic facade over the generated serial-framing binding.
3
+ *
4
+ * A serial line is a stream of bytes with no packet boundaries, so something has
5
+ * to mark where one message ends and the next begins. SLIP and COBS are the two
6
+ * ways to do that, and each is offered both as a one-shot call over a complete
7
+ * frame and as a streaming decoder for the arbitrary chunks a port delivers.
8
+ *
9
+ * The streaming decoders are what a real read loop uses. A corrupt frame does not
10
+ * throw, because the frames around it are still good; it is dropped and counted
11
+ * on {@link SlipDecoder.discarded}.
12
+ *
13
+ * @packageDocumentation
14
+ */
15
+ /** One of the two byte-stuffing framings this module offers. */
16
+ export interface Framing {
17
+ /**
18
+ * Frames a payload for the wire.
19
+ *
20
+ * @param payload - The bytes to send.
21
+ * @returns The frame, delimiter included.
22
+ */
23
+ encode(payload: Uint8Array): Buffer;
24
+ /**
25
+ * Reads the payload back out of a complete frame.
26
+ *
27
+ * @param frame - The frame as it arrived.
28
+ * @returns The payload.
29
+ * @throws If the frame is corrupt.
30
+ */
31
+ decode(frame: Uint8Array): Buffer;
32
+ /**
33
+ * Returns the largest frame a payload of this length can produce.
34
+ *
35
+ * @param payloadLen - The payload length in bytes.
36
+ * @returns The worst-case frame length.
37
+ */
38
+ maxEncodedLen(payloadLen: number): number;
39
+ }
40
+ /** The SLIP byte that ends a frame (RFC 1055). */
41
+ export declare const SLIP_END_BYTE: number;
42
+ /** The SLIP byte that escapes a reserved value inside a frame (RFC 1055). */
43
+ export declare const SLIP_ESC_BYTE: number;
44
+ /** The byte that follows an escape to stand for a literal end byte. */
45
+ export declare const SLIP_ESC_END_BYTE: number;
46
+ /** The byte that follows an escape to stand for a literal escape byte. */
47
+ export declare const SLIP_ESC_ESC_BYTE: number;
48
+ /** The byte that delimits a COBS frame, which never appears inside one. */
49
+ export declare const COBS_DELIMITER_BYTE: number;
50
+ /** SLIP (RFC 1055): an `END` byte ends a packet, and an escape pair carries it in the data. */
51
+ export declare const slip: Framing;
52
+ /** COBS: removes the zero byte from the payload so one zero delimits packets unambiguously. */
53
+ export declare const cobs: Framing;
54
+ /**
55
+ * Reassembles whole SLIP frames from the chunks a serial port delivers.
56
+ *
57
+ * @example
58
+ * ```ts
59
+ * const decoder = new SlipDecoder()
60
+ * port.on('data', (chunk) => {
61
+ * for (const frame of decoder.feed(chunk)) handle(frame)
62
+ * })
63
+ * ```
64
+ */
65
+ export declare class SlipDecoder {
66
+ #private;
67
+ /** Creates an empty decoder, ready for the first chunk. */
68
+ constructor();
69
+ /**
70
+ * Feeds a chunk of the stream.
71
+ *
72
+ * @param chunk - The bytes just read from the port.
73
+ * @returns Every frame this chunk completed, in order, which is often none.
74
+ */
75
+ feed(chunk: Uint8Array): Buffer[];
76
+ /** How many corrupt frames this decoder has discarded. */
77
+ get discarded(): number;
78
+ /** Discards any partly assembled frame. */
79
+ reset(): void;
80
+ }
81
+ /**
82
+ * Reassembles whole COBS frames from the chunks a serial port delivers.
83
+ *
84
+ * The counterpart to {@link SlipDecoder}, for links where the framing overhead
85
+ * has to stay small and predictable.
86
+ */
87
+ export declare class CobsDecoder {
88
+ #private;
89
+ /** Creates an empty decoder, ready for the first chunk. */
90
+ constructor();
91
+ /**
92
+ * Feeds a chunk of the stream.
93
+ *
94
+ * @param chunk - The bytes just read from the port.
95
+ * @returns Every frame this chunk completed, in order.
96
+ */
97
+ feed(chunk: Uint8Array): Buffer[];
98
+ /** How many corrupt frames this decoder has discarded. */
99
+ get discarded(): number;
100
+ /** Discards any partly assembled frame. */
101
+ reset(): void;
102
+ }
package/dist/index.js ADDED
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ /**
3
+ * Ergonomic facade over the generated serial-framing binding.
4
+ *
5
+ * A serial line is a stream of bytes with no packet boundaries, so something has
6
+ * to mark where one message ends and the next begins. SLIP and COBS are the two
7
+ * ways to do that, and each is offered both as a one-shot call over a complete
8
+ * frame and as a streaming decoder for the arbitrary chunks a port delivers.
9
+ *
10
+ * The streaming decoders are what a real read loop uses. A corrupt frame does not
11
+ * throw, because the frames around it are still good; it is dropped and counted
12
+ * on {@link SlipDecoder.discarded}.
13
+ *
14
+ * @packageDocumentation
15
+ */
16
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
17
+ if (kind === "m") throw new TypeError("Private method is not writable");
18
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
19
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
20
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
21
+ };
22
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
23
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
24
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
25
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
26
+ };
27
+ var _SlipDecoder_native, _CobsDecoder_native;
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.CobsDecoder = exports.SlipDecoder = exports.cobs = exports.slip = exports.COBS_DELIMITER_BYTE = exports.SLIP_ESC_ESC_BYTE = exports.SLIP_ESC_END_BYTE = exports.SLIP_ESC_BYTE = exports.SLIP_END_BYTE = void 0;
30
+ const native_1 = require("@pamoja/native");
31
+ /** The SLIP byte that ends a frame (RFC 1055). */
32
+ exports.SLIP_END_BYTE = native_1.SLIP_END;
33
+ /** The SLIP byte that escapes a reserved value inside a frame (RFC 1055). */
34
+ exports.SLIP_ESC_BYTE = native_1.SLIP_ESC;
35
+ /** The byte that follows an escape to stand for a literal end byte. */
36
+ exports.SLIP_ESC_END_BYTE = native_1.SLIP_ESC_END;
37
+ /** The byte that follows an escape to stand for a literal escape byte. */
38
+ exports.SLIP_ESC_ESC_BYTE = native_1.SLIP_ESC_ESC;
39
+ /** The byte that delimits a COBS frame, which never appears inside one. */
40
+ exports.COBS_DELIMITER_BYTE = native_1.COBS_DELIMITER;
41
+ /** SLIP (RFC 1055): an `END` byte ends a packet, and an escape pair carries it in the data. */
42
+ exports.slip = {
43
+ encode: (payload) => (0, native_1.slipEncode)(Buffer.from(payload)),
44
+ decode: (frame) => (0, native_1.slipDecode)(Buffer.from(frame)),
45
+ maxEncodedLen: (payloadLen) => (0, native_1.slipMaxEncodedLen)(payloadLen),
46
+ };
47
+ /** COBS: removes the zero byte from the payload so one zero delimits packets unambiguously. */
48
+ exports.cobs = {
49
+ encode: (payload) => (0, native_1.cobsEncode)(Buffer.from(payload)),
50
+ decode: (frame) => (0, native_1.cobsDecode)(Buffer.from(frame)),
51
+ maxEncodedLen: (payloadLen) => (0, native_1.cobsMaxEncodedLen)(payloadLen),
52
+ };
53
+ /**
54
+ * Reassembles whole SLIP frames from the chunks a serial port delivers.
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * const decoder = new SlipDecoder()
59
+ * port.on('data', (chunk) => {
60
+ * for (const frame of decoder.feed(chunk)) handle(frame)
61
+ * })
62
+ * ```
63
+ */
64
+ class SlipDecoder {
65
+ /** Creates an empty decoder, ready for the first chunk. */
66
+ constructor() {
67
+ _SlipDecoder_native.set(this, void 0);
68
+ __classPrivateFieldSet(this, _SlipDecoder_native, new native_1.SlipDecoder(), "f");
69
+ }
70
+ /**
71
+ * Feeds a chunk of the stream.
72
+ *
73
+ * @param chunk - The bytes just read from the port.
74
+ * @returns Every frame this chunk completed, in order, which is often none.
75
+ */
76
+ feed(chunk) {
77
+ return __classPrivateFieldGet(this, _SlipDecoder_native, "f").feed(Buffer.from(chunk));
78
+ }
79
+ /** How many corrupt frames this decoder has discarded. */
80
+ get discarded() {
81
+ return __classPrivateFieldGet(this, _SlipDecoder_native, "f").discarded;
82
+ }
83
+ /** Discards any partly assembled frame. */
84
+ reset() {
85
+ __classPrivateFieldGet(this, _SlipDecoder_native, "f").reset();
86
+ }
87
+ }
88
+ exports.SlipDecoder = SlipDecoder;
89
+ _SlipDecoder_native = new WeakMap();
90
+ /**
91
+ * Reassembles whole COBS frames from the chunks a serial port delivers.
92
+ *
93
+ * The counterpart to {@link SlipDecoder}, for links where the framing overhead
94
+ * has to stay small and predictable.
95
+ */
96
+ class CobsDecoder {
97
+ /** Creates an empty decoder, ready for the first chunk. */
98
+ constructor() {
99
+ _CobsDecoder_native.set(this, void 0);
100
+ __classPrivateFieldSet(this, _CobsDecoder_native, new native_1.CobsDecoder(), "f");
101
+ }
102
+ /**
103
+ * Feeds a chunk of the stream.
104
+ *
105
+ * @param chunk - The bytes just read from the port.
106
+ * @returns Every frame this chunk completed, in order.
107
+ */
108
+ feed(chunk) {
109
+ return __classPrivateFieldGet(this, _CobsDecoder_native, "f").feed(Buffer.from(chunk));
110
+ }
111
+ /** How many corrupt frames this decoder has discarded. */
112
+ get discarded() {
113
+ return __classPrivateFieldGet(this, _CobsDecoder_native, "f").discarded;
114
+ }
115
+ /** Discards any partly assembled frame. */
116
+ reset() {
117
+ __classPrivateFieldGet(this, _CobsDecoder_native, "f").reset();
118
+ }
119
+ }
120
+ exports.CobsDecoder = CobsDecoder;
121
+ _CobsDecoder_native = new WeakMap();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pamoja/serial",
3
- "version": "0.1.15",
3
+ "version": "0.1.16",
4
4
  "description": "SLIP and COBS byte stuffing with streaming decoders, so a UART byte stream carries discrete packets.",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -34,6 +34,6 @@
34
34
  "node": ">= 16"
35
35
  },
36
36
  "dependencies": {
37
- "@pamoja/native": "0.1.15"
37
+ "@pamoja/native": "0.1.16"
38
38
  }
39
39
  }