cborg 1.6.1 → 1.8.0

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.
package/README.md CHANGED
@@ -10,9 +10,18 @@
10
10
 
11
11
  * [Example](#example)
12
12
  * [CLI](#cli)
13
- * [`cborg json2hex '<json string>'`](#cborg-json2hex-json-string)
14
- * [`cborg hex2json [--pretty] <hex string>`](#cborg-hex2json---pretty-hex-string)
15
- * [`cborg hex2diag <hex string>`](#cborg-hex2diag-hex-string)
13
+ * [`cborg bin2diag [binary input]`](#cborg-bin2diag-binary-input)
14
+ * [`cborg bin2hex [binary string]`](#cborg-bin2hex-binary-string)
15
+ * [`cborg bin2json [--pretty] [binary input]`](#cborg-bin2json---pretty-binary-input)
16
+ * [`cborg diag2bin [diagnostic string]`](#cborg-diag2bin-diagnostic-string)
17
+ * [`cborg diag2hex [diagnostic string]`](#cborg-diag2hex-diagnostic-string)
18
+ * [`cborg diag2json [--pretty] [diagnostic string]`](#cborg-diag2json---pretty-diagnostic-string)
19
+ * [`cborg hex2bin [hex string]`](#cborg-hex2bin-hex-string)
20
+ * [`cborg hex2diag [hex string]`](#cborg-hex2diag-hex-string)
21
+ * [`cborg hex2json [--pretty] [hex string]`](#cborg-hex2json---pretty-hex-string)
22
+ * [`cborg json2bin [json string]`](#cborg-json2bin-json-string)
23
+ * [`cborg json2diag [json string]`](#cborg-json2diag-json-string)
24
+ * [`cborg json2hex '[json string]'`](#cborg-json2hex-json-string)
16
25
  * [API](#api)
17
26
  * [`encode(object[, options])`](#encodeobject-options)
18
27
  * [Options](#options)
@@ -50,18 +59,87 @@ encoded: Uint8Array(21) [
50
59
 
51
60
  When installed globally via `npm` (with `npm install cborg --global`), the `cborg` command will be available that provides some handy CBOR CLI utilities. Run with `cborg help` for additional details.
52
61
 
53
- ### `cborg json2hex '<json string>'`
62
+ The following commands take either input from the command line, or if no input is supplied will read from stdin. Output is printed to stdout. So you can `cat foo | cborg <command>`.
54
63
 
55
- Convert a JSON object into CBOR bytes in hexadecimal format.
64
+ ### `cborg bin2diag [binary input]`
65
+
66
+ Convert CBOR from binary input to a CBOR diagnostic output format which explains the byte contents.
56
67
 
57
68
  ```
58
- $ cborg json2hex '["a", "b", 1, "😀"]'
69
+ $ cborg hex2bin 84616161620164f09f9880 | cborg bin2diag
70
+ 84 # array(4)
71
+ 61 # string(1)
72
+ 61 # "a"
73
+ 61 # string(1)
74
+ 62 # "b"
75
+ 01 # uint(1)
76
+ 64 f09f # string(2)
77
+ f09f9880 # "😀"
78
+ ```
79
+
80
+ ### `cborg bin2hex [binary string]`
81
+
82
+ A utility method to convert a binary input (stdin only) to hexadecimal output (does not involve CBOR).
83
+
84
+ ### `cborg bin2json [--pretty] [binary input]`
85
+
86
+ Convert CBOR from binary input to JSON format.
87
+
88
+ ```
89
+ $ cborg hex2bin 84616161620164f09f9880 | cborg bin2json
90
+ ["a","b",1,"😀"]
91
+ ```
92
+
93
+ ### `cborg diag2bin [diagnostic string]`
94
+
95
+ Convert a CBOR diagnostic string to a binary data form of the CBOR.
96
+
97
+ ```
98
+ $ cborg json2diag '["a","b",1,"😀"]' | cborg diag2bin | cborg bin2hex
59
99
  84616161620164f09f9880
60
100
  ```
61
101
 
62
- ### `cborg hex2json [--pretty] <hex string>`
102
+ ### `cborg diag2hex [diagnostic string]`
63
103
 
64
- Convert a hexadecimal string to a JSON format.
104
+ Convert a CBOR diagnostic string to the CBOR bytes in hexadecimal format.
105
+
106
+ ```
107
+ $ cborg json2diag '["a","b",1,"😀"]' | cborg diag2hex
108
+ 84616161620164f09f9880
109
+ ```
110
+
111
+ ### `cborg diag2json [--pretty] [diagnostic string]`
112
+
113
+ Convert a CBOR diagnostic string to JSON format.
114
+
115
+ ```
116
+ $ cborg json2diag '["a","b",1,"😀"]' | cborg diag2json
117
+ ["a","b",1,"😀"]
118
+ ```
119
+
120
+ ### `cborg hex2bin [hex string]`
121
+
122
+ A utility method to convert a hex string to binary output (does not involve CBOR).
123
+
124
+ ### `cborg hex2diag [hex string]`
125
+
126
+ Convert CBOR from a hexadecimal string to a CBOR diagnostic output format which explains the byte contents.
127
+
128
+ ```
129
+ $ cborg hex2diag 84616161620164f09f9880
130
+ 84 # array(4)
131
+ 61 # string(1)
132
+ 61 # "a"
133
+ 61 # string(1)
134
+ 62 # "b"
135
+ 01 # uint(1)
136
+ 64 f09f # string(2)
137
+ f09f9880 # "😀"
138
+ ```
139
+
140
+ ### `cborg hex2json [--pretty] [hex string]`
141
+
142
+ Convert CBOR from a hexadecimal string to JSON format.
65
143
 
66
144
  ```
67
145
  $ cborg hex2json 84616161620164f09f9880
@@ -75,12 +153,21 @@ $ cborg hex2json --pretty 84616161620164f09f9880
75
153
  ]
76
154
  ```
77
155
 
78
- ### `cborg hex2diag <hex string>`
156
+ ### `cborg json2bin [json string]`
79
157
 
80
- Convert a hexadecimal string to a CBOR diagnostic output format which explains the byte contents.
158
+ Convert a JSON object into a binary data form of the CBOR.
81
159
 
82
160
  ```
83
- $ cborg hex2diag 84616161620164f09f9880
161
+ $ cborg json2bin '["a","b",1,"😀"]' | cborg bin2hex
162
+ 84616161620164f09f9880
163
+ ```
164
+
165
+ ### `cborg json2diag [json string]`
166
+
167
+ Convert a JSON object into a CBOR diagnostic output format which explains the contents of the CBOR form of the input object.
168
+
169
+ ```
170
+ $ cborg json2diag '["a", "b", 1, "😀"]'
84
171
  84 # array(4)
85
172
  61 # string(1)
86
173
  61 # "a"
@@ -91,6 +178,15 @@ $ cborg hex2diag 84616161620164f09f9880
91
178
  f09f9880 # "😀"
92
179
  ```
93
180
 
181
+ ### `cborg json2hex '[json string]'`
182
+
183
+ Convert a JSON object into CBOR bytes in hexadecimal format.
184
+
185
+ ```
186
+ $ cborg json2hex '["a", "b", 1, "😀"]'
187
+ 84616161620164f09f9880
188
+ ```
189
+
94
190
  ## API
95
191
 
96
192
  ### `encode(object[, options])`
@@ -150,6 +246,7 @@ Decode valid CBOR bytes from a `Uint8Array` (or `Buffer`) and return a JavaScrip
150
246
  * `strict` (boolean, default `false`): when decoding integers, including for lengths (arrays, maps, strings, bytes), values will be checked to see whether they were encoded in their smallest possible form. If not, an error will be thrown.
151
247
  * Currently, this form of deterministic strictness cannot be enforced for float representations, or map key ordering (pull requests _very_ welcome).
152
248
  * `useMaps` (boolean, default `false`): when decoding major 5 (map) entries, use a `Map` rather than a plain `Object`. This will nest for any encountered map. During encode, a `Map` will be interpreted as an `Object` and will round-trip as such unless `useMaps` is supplied, in which case, all `Map`s and `Object`s will round-trip as `Map`s. There is no way to retain the distinction during round-trip without using a custom tag.
249
+ * `retainStringBytes` (boolean, default `false`): when decoding strings, retain the original bytes on the `Token` object as `byteValue`. Since it is possible to encode non-UTF-8 characters in strings in CBOR, and JavaScript doesn't properly handle non-UTF-8 in its conversion from bytes (`TextEncoder` or `Buffer`), this can result in a loss of data (and an inability to round-trip). Where this is important, a token stream should be consumed instead of a plain `decode()` and the `byteValue` property on string tokens can be inspected (see [lib/diagnostic.js](lib/diagnostic.js) for an example of its use.)
153
250
  * `tags` (array): a mapping of tag number to tag decoder function. By default no tags are supported. See [Tag decoders](#tag-decoders).
154
251
  * `tokenizer` (object): an object with two methods, `next()` which returns a `Token` and `done()` which returns a `boolean`. Can be used to implement custom input decoding. See the source code for examples.
155
252
 
@@ -4,6 +4,7 @@ var chai = require('chai');
4
4
  var child_process = require('child_process');
5
5
  var process = require('process');
6
6
  var path = require('path');
7
+ var os = require('os');
7
8
  var url = require('url');
8
9
  require('../lib/bin.js');
9
10
 
@@ -14,6 +15,52 @@ var process__default = /*#__PURE__*/_interopDefaultLegacy(process);
14
15
  var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
15
16
 
16
17
  const {assert} = chai__default["default"];
18
+ const fixture1JsonString = '{"a":1,"b":[2,3],"smile":"\uD83D\uDE00"}';
19
+ const fixture1JsonPrettyString = `{
20
+ "a": 1,
21
+ "b": [
22
+ 2,
23
+ 3
24
+ ],
25
+ "smile": "😀"
26
+ }
27
+ `;
28
+ const fixture1HexString = 'a3616101616282020365736d696c6564f09f9880';
29
+ const fixture1Bin = fromHex(fixture1HexString);
30
+ const fixture1BinString = new TextDecoder().decode(fixture1Bin);
31
+ const fixture1DiagnosticString = `a3 # map(3)
32
+ 61 # string(1)
33
+ 61 # "a"
34
+ 01 # uint(1)
35
+ 61 # string(1)
36
+ 62 # "b"
37
+ 82 # array(2)
38
+ 02 # uint(2)
39
+ 03 # uint(3)
40
+ 65 # string(5)
41
+ 736d696c65 # "smile"
42
+ 64 # string(2)
43
+ f09f9880 # "😀"
44
+ `;
45
+ const fixture2HexString = 'a4616101616282020363627566440102036165736d696c6564f09f9880';
46
+ const fixture2DiagnosticString = `a4 # map(4)
47
+ 61 # string(1)
48
+ 61 # "a"
49
+ 01 # uint(1)
50
+ 61 # string(1)
51
+ 62 # "b"
52
+ 82 # array(2)
53
+ 02 # uint(2)
54
+ 03 # uint(3)
55
+ 63 # string(3)
56
+ 627566 # "buf"
57
+ 44 # bytes(4)
58
+ 01020361 # "\\x01\\x02\\x03a"
59
+ 65 # string(5)
60
+ 736d696c65 # "smile"
61
+ 64 # string(2)
62
+ f09f9880 # "😀"
63
+ `;
17
64
  const binPath = path__default["default"].join(path__default["default"].dirname(url.fileURLToPath((typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('browser-test/node-test-bin.js', document.baseURI).href)))), '../lib/bin.js');
18
65
  function fromHex(hex) {
19
66
  return new Uint8Array(hex.split('').map((c, i, d) => i % 2 === 0 ? `0x${ c }${ d[i + 1] }` : '').filter(Boolean).map(e => parseInt(e, 16)));
@@ -48,15 +95,18 @@ describe('Bin', () => {
48
95
  assert.strictEqual(e.stdout, '');
49
96
  assert.strictEqual(e.stderr, `Usage: cborg <command> <args>
50
97
  Valid commands:
51
- \thex2diag [hex input]
52
- \thex2bin [hex input]
53
- \thex2json [--pretty] [hex input]
54
- \tbin2hex [binary input]
55
98
  \tbin2diag [binary input]
99
+ \tbin2hex [binary input]
56
100
  \tbin2json [--pretty] [binary input]
57
- \tjson2hex '[json input]'
58
- \tjson2diag '[json input]'
101
+ \tdiag2bin [diagnostic input]
102
+ \tdiag2hex [diagnostic input]
103
+ \tdiag2json [--pretty] [diagnostic input]
104
+ \thex2bin [hex input]
105
+ \thex2diag [hex input]
106
+ \thex2json [--pretty] [hex input]
59
107
  \tjson2bin '[json input]'
108
+ \tjson2diag '[json input]'
109
+ \tjson2hex '[json input]'
60
110
  Input may either be supplied as an argument or piped via stdin
61
111
  `);
62
112
  }
@@ -70,15 +120,18 @@ Input may either be supplied as an argument or piped via stdin
70
120
  assert.strictEqual(e.stderr, `Unknown command: 'blip'
71
121
  Usage: cborg <command> <args>
72
122
  Valid commands:
73
- \thex2diag [hex input]
74
- \thex2bin [hex input]
75
- \thex2json [--pretty] [hex input]
76
- \tbin2hex [binary input]
77
123
  \tbin2diag [binary input]
124
+ \tbin2hex [binary input]
78
125
  \tbin2json [--pretty] [binary input]
79
- \tjson2hex '[json input]'
80
- \tjson2diag '[json input]'
126
+ \tdiag2bin [diagnostic input]
127
+ \tdiag2hex [diagnostic input]
128
+ \tdiag2json [--pretty] [diagnostic input]
129
+ \thex2bin [hex input]
130
+ \thex2diag [hex input]
131
+ \thex2json [--pretty] [hex input]
81
132
  \tjson2bin '[json input]'
133
+ \tjson2diag '[json input]'
134
+ \tjson2hex '[json input]'
82
135
  Input may either be supplied as an argument or piped via stdin
83
136
  `);
84
137
  }
@@ -88,135 +141,209 @@ Input may either be supplied as an argument or piped via stdin
88
141
  assert.strictEqual(stdout, '');
89
142
  assert.strictEqual(stderr, `Usage: cborg <command> <args>
90
143
  Valid commands:
91
- \thex2diag [hex input]
92
- \thex2bin [hex input]
93
- \thex2json [--pretty] [hex input]
94
- \tbin2hex [binary input]
95
144
  \tbin2diag [binary input]
145
+ \tbin2hex [binary input]
96
146
  \tbin2json [--pretty] [binary input]
97
- \tjson2hex '[json input]'
98
- \tjson2diag '[json input]'
147
+ \tdiag2bin [diagnostic input]
148
+ \tdiag2hex [diagnostic input]
149
+ \tdiag2json [--pretty] [diagnostic input]
150
+ \thex2bin [hex input]
151
+ \thex2diag [hex input]
152
+ \thex2json [--pretty] [hex input]
99
153
  \tjson2bin '[json input]'
154
+ \tjson2diag '[json input]'
155
+ \tjson2hex '[json input]'
100
156
  Input may either be supplied as an argument or piped via stdin
101
157
  `);
102
158
  });
159
+ it('bin2diag (stdin)', async () => {
160
+ const {stdout, stderr} = await execBin('bin2diag', fixture1Bin);
161
+ assert.strictEqual(stderr, '');
162
+ assert.strictEqual(stdout, fixture1DiagnosticString);
163
+ });
164
+ it('bin2hex (stdin)', async () => {
165
+ const {stdout, stderr} = await execBin('bin2hex', fixture1Bin);
166
+ assert.strictEqual(stderr, '');
167
+ assert.strictEqual(stdout, `${ fixture1HexString }\n`);
168
+ });
169
+ it('bin2json (stdin)', async () => {
170
+ const {stdout, stderr} = await execBin('bin2json', fixture1Bin);
171
+ assert.strictEqual(stderr, '');
172
+ assert.strictEqual(stdout, `${ fixture1JsonString }\n`);
173
+ });
174
+ it('bin2json pretty (stdin)', async () => {
175
+ const {stdout, stderr} = await execBin('bin2json --pretty', fixture1Bin);
176
+ assert.strictEqual(stderr, '');
177
+ assert.strictEqual(stdout, fixture1JsonPrettyString);
178
+ });
103
179
  for (const stdin of [
104
180
  true,
105
181
  false
106
182
  ]) {
107
- it(`hex2json${ stdin ? ' (stdin)' : '' }`, async () => {
108
- const {stdout, stderr} = stdin ? await execBin('hex2json a3616101616282020365736d696c6564f09f9880') : await execBin('hex2json', 'a3616101616282020365736d696c6564f09f9880');
109
- assert.strictEqual(stderr, '');
110
- assert.strictEqual(stdout, '{"a":1,"b":[2,3],"smile":"\uD83D\uDE00"}\n');
111
- });
112
- it(`hex2json pretty${ stdin ? ' (stdin)' : '' }`, async () => {
113
- const {stdout, stderr} = stdin ? await execBin('hex2json --pretty a3616101616282020365736d696c6564f09f9880') : await execBin('hex2json --pretty', 'a3616101616282020365736d696c6564f09f9880');
183
+ if (os.platform() !== 'win32' || stdin) {
184
+ it(`diag2bin${ stdin ? ' (stdin)' : '' }`, async () => {
185
+ const {stdout, stderr} = !stdin ? await execBin(`diag2bin '${ fixture1DiagnosticString }'`) : await execBin('diag2bin', fixture1DiagnosticString);
186
+ assert.strictEqual(stderr, '');
187
+ assert.strictEqual(stdout, fixture1BinString);
188
+ });
189
+ it(`diag2hex${ stdin ? ' (stdin)' : '' }`, async () => {
190
+ const {stdout, stderr} = !stdin ? await execBin(`diag2hex '${ fixture1DiagnosticString }'`) : await execBin('diag2hex', fixture1DiagnosticString);
191
+ assert.strictEqual(stderr, '');
192
+ assert.strictEqual(stdout, `${ fixture1HexString }\n`);
193
+ });
194
+ it(`diag2json${ stdin ? ' (stdin)' : '' }`, async () => {
195
+ const {stdout, stderr} = !stdin ? await execBin(`diag2json '${ fixture1DiagnosticString }'`) : await execBin('diag2json', fixture1DiagnosticString);
196
+ assert.strictEqual(stderr, '');
197
+ assert.strictEqual(stdout, `${ fixture1JsonString }\n`);
198
+ });
199
+ it(`diag2json pretty${ stdin ? ' (stdin)' : '' }`, async () => {
200
+ const {stdout, stderr} = !stdin ? await execBin(`diag2json --pretty '${ fixture1DiagnosticString }'`) : await execBin('diag2json --pretty', fixture1DiagnosticString);
201
+ assert.strictEqual(stderr, '');
202
+ assert.strictEqual(stdout, fixture1JsonPrettyString);
203
+ });
204
+ }
205
+ it(`hex2bin${ stdin ? ' (stdin)' : '' }`, async () => {
206
+ const {stdout, stderr} = !stdin ? await execBin(`hex2bin ${ fixture1HexString }`) : await execBin('hex2bin', fixture1HexString);
114
207
  assert.strictEqual(stderr, '');
115
- assert.strictEqual(stdout, `{
116
- "a": 1,
117
- "b": [
118
- 2,
119
- 3
120
- ],
121
- "smile": "😀"
122
- }
123
- `);
208
+ assert.strictEqual(stdout, fixture1BinString);
124
209
  });
125
210
  it(`hex2diag${ stdin ? ' (stdin)' : '' }`, async () => {
126
- const {stdout, stderr} = stdin ? await execBin('hex2diag a4616101616282020363627566440102036165736d696c6564f09f9880') : await execBin('hex2diag', 'a4616101616282020363627566440102036165736d696c6564f09f9880');
211
+ const {stdout, stderr} = !stdin ? await execBin(`hex2diag ${ fixture2HexString }`) : await execBin('hex2diag', fixture2HexString);
127
212
  assert.strictEqual(stderr, '');
128
- assert.strictEqual(stdout, `a4 # map(4)
129
- 61 # string(1)
130
- 61 # "a"
131
- 01 # uint(1)
132
- 61 # string(1)
133
- 62 # "b"
134
- 82 # array(2)
135
- 02 # uint(2)
136
- 03 # uint(3)
137
- 63 # string(3)
138
- 627566 # "buf"
139
- 44 # bytes(4)
140
- 01020361 # "\\x01\\x02\\x03a"
141
- 65 # string(5)
142
- 736d696c65 # "smile"
143
- 64 f09f # string(2)
144
- f09f9880 # "😀"
145
- `);
213
+ assert.strictEqual(stdout, fixture2DiagnosticString);
146
214
  });
147
- it(`hex2bin${ stdin ? ' (stdin)' : '' }`, async () => {
148
- const {stdout, stderr} = stdin ? await execBin('hex2bin a3616101616282020365736d696c6564f09f9880') : await execBin('hex2bin', 'a3616101616282020365736d696c6564f09f9880');
215
+ it(`hex2json${ stdin ? ' (stdin)' : '' }`, async () => {
216
+ const {stdout, stderr} = !stdin ? await execBin(`hex2json ${ fixture1HexString }`) : await execBin('hex2json', fixture1HexString);
149
217
  assert.strictEqual(stderr, '');
150
- assert.strictEqual(stdout, new TextDecoder().decode(fromHex('a3616101616282020365736d696c6564f09f9880')));
218
+ assert.strictEqual(stdout, `${ fixture1JsonString }\n`);
151
219
  });
152
- it(`json2hex${ stdin ? ' (stdin)' : '' }`, async () => {
153
- const {stdout, stderr} = stdin ? await execBin('json2hex "{\\"a\\":1,\\"b\\":[2,3],\\"smile\\":\\"\uD83D\uDE00\\"}"') : await execBin('json2hex', '{"a":1,"b":[2,3],"smile":"\uD83D\uDE00"}');
220
+ it(`hex2json pretty${ stdin ? ' (stdin)' : '' }`, async () => {
221
+ const {stdout, stderr} = !stdin ? await execBin(`hex2json --pretty ${ fixture1HexString }`) : await execBin('hex2json --pretty', fixture1HexString);
154
222
  assert.strictEqual(stderr, '');
155
- assert.strictEqual(stdout, 'a3616101616282020365736d696c6564f09f9880\n');
223
+ assert.strictEqual(stdout, fixture1JsonPrettyString);
156
224
  });
157
225
  it(`json2bin${ stdin ? ' (stdin)' : '' }`, async () => {
158
- const {stdout, stderr} = stdin ? await execBin('json2bin "{\\"a\\":1,\\"b\\":[2,3],\\"smile\\":\\"\uD83D\uDE00\\"}"') : await execBin('json2bin', '{"a":1,"b":[2,3],"smile":"\uD83D\uDE00"}');
226
+ const {stdout, stderr} = !stdin ? await execBin('json2bin "{\\"a\\":1,\\"b\\":[2,3],\\"smile\\":\\"\uD83D\uDE00\\"}"') : await execBin('json2bin', fixture1JsonString);
159
227
  assert.strictEqual(stderr, '');
160
- assert.strictEqual(stdout, new TextDecoder().decode(fromHex('a3616101616282020365736d696c6564f09f9880')));
228
+ assert.strictEqual(stdout, fixture1BinString);
161
229
  });
162
230
  it(`json2diag${ stdin ? ' (stdin)' : '' }`, async () => {
163
- const {stdout, stderr} = stdin ? await execBin('json2diag "{\\"a\\":1,\\"b\\":[2,3],\\"smile\\":\\"\uD83D\uDE00\\"}"') : await execBin('json2diag', '{"a":1,"b":[2,3],"smile":"\uD83D\uDE00"}');
231
+ const {stdout, stderr} = !stdin ? await execBin('json2diag "{\\"a\\":1,\\"b\\":[2,3],\\"smile\\":\\"\uD83D\uDE00\\"}"') : await execBin('json2diag', fixture1JsonString);
164
232
  assert.strictEqual(stderr, '');
165
- assert.strictEqual(stdout, `a3 # map(3)
166
- 61 # string(1)
167
- 61 # "a"
168
- 01 # uint(1)
169
- 61 # string(1)
170
- 62 # "b"
171
- 82 # array(2)
172
- 02 # uint(2)
173
- 03 # uint(3)
174
- 65 # string(5)
175
- 736d696c65 # "smile"
176
- 64 f09f # string(2)
177
- f09f9880 # "😀"
178
- `);
233
+ assert.strictEqual(stdout, fixture1DiagnosticString);
234
+ });
235
+ it(`json2hex${ stdin ? ' (stdin)' : '' }`, async () => {
236
+ const {stdout, stderr} = !stdin ? await execBin(`json2hex "${ fixture1JsonString.replace(/"/g, '\\"') }"`) : await execBin('json2hex', fixture1JsonString);
237
+ assert.strictEqual(stderr, '');
238
+ assert.strictEqual(stdout, `${ fixture1HexString }\n`);
179
239
  });
180
240
  }
181
- it('bin2diag (stdin)', async () => {
182
- const {stdout, stderr} = await execBin('bin2diag', fromHex('a3616101616282020365736d696c6564f09f9880'));
241
+ it('diag indenting', async () => {
242
+ const {stdout, stderr} = await execBin('json2diag', '{"a":[],"b":{},"c":{"a":1,"b":{"a":{"a":{}}}},"d":{"a":{"a":{"a":1},"b":2,"c":[]}},"e":[[[[{"a":{}}]]]],"f":1}');
183
243
  assert.strictEqual(stderr, '');
184
- assert.strictEqual(stdout, `a3 # map(3)
244
+ assert.strictEqual(stdout, `a6 # map(6)
185
245
  61 # string(1)
186
246
  61 # "a"
187
- 01 # uint(1)
247
+ 80 # array(0)
188
248
  61 # string(1)
189
249
  62 # "b"
190
- 82 # array(2)
191
- 02 # uint(2)
192
- 03 # uint(3)
193
- 65 # string(5)
194
- 736d696c65 # "smile"
195
- 64 f09f # string(2)
196
- f09f9880 # "😀"
250
+ a0 # map(0)
251
+ 61 # string(1)
252
+ 63 # "c"
253
+ a2 # map(2)
254
+ 61 # string(1)
255
+ 61 # "a"
256
+ 01 # uint(1)
257
+ 61 # string(1)
258
+ 62 # "b"
259
+ a1 # map(1)
260
+ 61 # string(1)
261
+ 61 # "a"
262
+ a1 # map(1)
263
+ 61 # string(1)
264
+ 61 # "a"
265
+ a0 # map(0)
266
+ 61 # string(1)
267
+ 64 # "d"
268
+ a1 # map(1)
269
+ 61 # string(1)
270
+ 61 # "a"
271
+ a3 # map(3)
272
+ 61 # string(1)
273
+ 61 # "a"
274
+ a1 # map(1)
275
+ 61 # string(1)
276
+ 61 # "a"
277
+ 01 # uint(1)
278
+ 61 # string(1)
279
+ 62 # "b"
280
+ 02 # uint(2)
281
+ 61 # string(1)
282
+ 63 # "c"
283
+ 80 # array(0)
284
+ 61 # string(1)
285
+ 65 # "e"
286
+ 81 # array(1)
287
+ 81 # array(1)
288
+ 81 # array(1)
289
+ 81 # array(1)
290
+ a1 # map(1)
291
+ 61 # string(1)
292
+ 61 # "a"
293
+ a0 # map(0)
294
+ 61 # string(1)
295
+ 66 # "f"
296
+ 01 # uint(1)
197
297
  `);
198
298
  });
199
- it('bin2json (stdin)', async () => {
200
- const {stdout, stderr} = await execBin('bin2json', fromHex('a3616101616282020365736d696c6564f09f9880'));
201
- assert.strictEqual(stderr, '');
202
- assert.strictEqual(stdout, '{"a":1,"b":[2,3],"smile":"\uD83D\uDE00"}\n');
299
+ describe('diag length bytes', () => {
300
+ it('compact', async () => {
301
+ const {stdout, stderr} = await execBin('json2diag', '"aaaaaaaaaaaaaaaaaaaaaaa"');
302
+ assert.strictEqual(stderr, '');
303
+ assert.strictEqual(stdout, `77 # string(23)
304
+ 6161616161616161616161616161616161616161616161 # "aaaaaaaaaaaaaaaaaaaaaaa"
305
+ `);
306
+ });
307
+ it('1-byte', async () => {
308
+ const {stdout, stderr} = await execBin('json2diag', '"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"');
309
+ assert.strictEqual(stderr, '');
310
+ assert.strictEqual(stdout, `78 23 # string(35)
311
+ 6161616161616161616161616161616161616161616161 # "aaaaaaaaaaaaaaaaaaaaaaa"
312
+ 616161616161616161616161 # "aaaaaaaaaaaa"
313
+ `);
314
+ });
315
+ it('2-byte', async () => {
316
+ const {stdout, stderr} = await execBin('json2diag', '"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"');
317
+ assert.strictEqual(stderr, '');
318
+ assert.strictEqual(stdout, `79 0100 # string(256)
319
+ 6161616161616161616161616161616161616161616161 # "aaaaaaaaaaaaaaaaaaaaaaa"
320
+ 6161616161616161616161616161616161616161616161 # "aaaaaaaaaaaaaaaaaaaaaaa"
321
+ 6161616161616161616161616161616161616161616161 # "aaaaaaaaaaaaaaaaaaaaaaa"
322
+ 6161616161616161616161616161616161616161616161 # "aaaaaaaaaaaaaaaaaaaaaaa"
323
+ 6161616161616161616161616161616161616161616161 # "aaaaaaaaaaaaaaaaaaaaaaa"
324
+ 6161616161616161616161616161616161616161616161 # "aaaaaaaaaaaaaaaaaaaaaaa"
325
+ 6161616161616161616161616161616161616161616161 # "aaaaaaaaaaaaaaaaaaaaaaa"
326
+ 6161616161616161616161616161616161616161616161 # "aaaaaaaaaaaaaaaaaaaaaaa"
327
+ 6161616161616161616161616161616161616161616161 # "aaaaaaaaaaaaaaaaaaaaaaa"
328
+ 6161616161616161616161616161616161616161616161 # "aaaaaaaaaaaaaaaaaaaaaaa"
329
+ 6161616161616161616161616161616161616161616161 # "aaaaaaaaaaaaaaaaaaaaaaa"
330
+ 616161 # "aaa"
331
+ `);
332
+ });
203
333
  });
204
- it('bin2json pretty (stdin)', async () => {
205
- const {stdout, stderr} = await execBin('bin2json --pretty', fromHex('a3616101616282020365736d696c6564f09f9880'));
334
+ it('diag non-utf8 and non-printable ascii', async () => {
335
+ const input = '7864f55ff8f12508b63ef2bfeca7557ae90df6311a5ec1631b4a1fa843310bd9c3a710eaace5a1bdd72ad0bfe049771c11e756338bd93865e645f1adec9b9c99ef407fbd4fc6859e7904c5ad7dc9bd10a5cc16973d5b28ec1a6dd43d9f82f9f18c3d03418e35';
336
+ let {stdout, stderr} = await execBin(`hex2diag ${ input }`);
206
337
  assert.strictEqual(stderr, '');
207
- assert.strictEqual(stdout, `{
208
- "a": 1,
209
- "b": [
210
- 2,
211
- 3
212
- ],
213
- "smile": "😀"
214
- }
338
+ assert.strictEqual(stdout, `78 64 # string(86)
339
+ f55ff8f12508b63ef2bfeca7557ae90df6311a5ec1631b # "õ_øñ%\\x08¶>ò¿ì§Uzé\\x0dö1\\x1a^Ác\\x1b"
340
+ 4a1fa843310bd9c3a710eaace5a1bdd72ad0bfe049771c # "J\\x1f¨C1\\x0bÙç\\x10ê¬å¡½×*пàIw\\x1c"
341
+ 11e756338bd93865e645f1adec9b9c99ef407fbd4fc685 # "\\x11çV3\\x8bÙ8eæEñ\\xadì\\x9b\\x9c\\x99ï@\\x7f½OÆ\\x85"
342
+ 9e7904c5ad7dc9bd10a5cc16973d5b28ec1a6dd43d9f82 # "\\x9ey\\x04Å\\xad}ɽ\\x10¥Ì\\x16\\x97=[(ì\\x1amÔ=\\x9f\\x82"
343
+ f9f18c3d03418e35 # "ùñ\\x8c=\\x03A\\x8e5"
215
344
  `);
216
- });
217
- it('bin2hex (stdin)', async () => {
218
- const {stdout, stderr} = await execBin('bin2hex', fromHex('a3616101616282020365736d696c6564f09f9880'));
345
+ ({stdout, stderr} = await execBin('diag2hex', stdout));
219
346
  assert.strictEqual(stderr, '');
220
- assert.strictEqual(stdout, 'a3616101616282020365736d696c6564f09f9880\n');
347
+ assert.strictEqual(stdout, `${ input }\n`);
221
348
  });
222
349
  });
@@ -8,29 +8,33 @@ var _0uint = require('./0uint.js');
8
8
  var _2bytes = require('./2bytes.js');
9
9
  var byteUtils = require('./byte-utils.js');
10
10
 
11
- function toToken(data, pos, prefix, length) {
11
+ function toToken(data, pos, prefix, length, options) {
12
12
  const totLength = prefix + length;
13
13
  common.assertEnoughData(data, pos, totLength);
14
- return new token.Token(token.Type.string, byteUtils.toString(data, pos + prefix, pos + totLength), totLength);
14
+ const tok = new token.Token(token.Type.string, byteUtils.toString(data, pos + prefix, pos + totLength), totLength);
15
+ if (options.retainStringBytes === true) {
16
+ tok.byteValue = byteUtils.slice(data, pos + prefix, pos + totLength);
17
+ }
18
+ return tok;
15
19
  }
16
- function decodeStringCompact(data, pos, minor, _options) {
17
- return toToken(data, pos, 1, minor);
20
+ function decodeStringCompact(data, pos, minor, options) {
21
+ return toToken(data, pos, 1, minor, options);
18
22
  }
19
23
  function decodeString8(data, pos, _minor, options) {
20
- return toToken(data, pos, 2, _0uint.readUint8(data, pos + 1, options));
24
+ return toToken(data, pos, 2, _0uint.readUint8(data, pos + 1, options), options);
21
25
  }
22
26
  function decodeString16(data, pos, _minor, options) {
23
- return toToken(data, pos, 3, _0uint.readUint16(data, pos + 1, options));
27
+ return toToken(data, pos, 3, _0uint.readUint16(data, pos + 1, options), options);
24
28
  }
25
29
  function decodeString32(data, pos, _minor, options) {
26
- return toToken(data, pos, 5, _0uint.readUint32(data, pos + 1, options));
30
+ return toToken(data, pos, 5, _0uint.readUint32(data, pos + 1, options), options);
27
31
  }
28
32
  function decodeString64(data, pos, _minor, options) {
29
33
  const l = _0uint.readUint64(data, pos + 1, options);
30
34
  if (typeof l === 'bigint') {
31
35
  throw new Error(`${ common.decodeErrPrefix } 64-bit integer string lengths not supported`);
32
36
  }
33
- return toToken(data, pos, 9, l);
37
+ return toToken(data, pos, 9, l, options);
34
38
  }
35
39
  const encodeString = _2bytes.encodeBytes;
36
40