@cbortech/cbor 0.26.8 → 0.27.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.ja.md +120 -28
- package/README.md +121 -29
- package/dist/ast/CborAppSeqResult.d.ts +22 -0
- package/dist/ast/CborByteString.d.ts +16 -0
- package/dist/ast/CborEmbeddedCBOR.d.ts +1 -1
- package/dist/ast/CborFloat.d.ts +1 -1
- package/dist/ast/CborIndefiniteByteString.d.ts +24 -0
- package/dist/ast/CborIndefiniteTextString.d.ts +16 -0
- package/dist/ast/CborItem.d.ts +44 -4
- package/dist/ast/CborTag.d.ts +27 -0
- package/dist/ast/CborTextString.d.ts +2 -1
- package/dist/ast/CborUnresolvedAppExt.d.ts +2 -2
- package/dist/ast/index.cjs +1 -1
- package/dist/ast/index.js +2 -2
- package/dist/cddl/index.cjs +1 -1
- package/dist/cddl/index.js +1 -1
- package/dist/cdn/index.cjs +2 -2
- package/dist/cdn/index.cjs.map +1 -1
- package/dist/cdn/index.js +18 -18
- package/dist/cdn/index.js.map +1 -1
- package/dist/cdn/serialize-utils.d.ts +207 -8
- package/dist/cdn/tokenizer.d.ts +12 -11
- package/dist/extensions/builtins.d.ts +5 -5
- package/dist/extensions/cri.d.ts +2 -2
- package/dist/extensions/ip.d.ts +1 -1
- package/dist/extensions/types.d.ts +4 -4
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +158 -158
- package/dist/index.js.map +1 -1
- package/dist/mapEntries-C1f7G0AM.cjs +13 -0
- package/dist/mapEntries-C1f7G0AM.cjs.map +1 -0
- package/dist/{mapEntries-Ci_dppP6.js → mapEntries-CvLdiN0h.js} +1362 -1219
- package/dist/mapEntries-CvLdiN0h.js.map +1 -0
- package/dist/{schema-y8G5mDIS.js → schema-CNfrVRYp.js} +294 -294
- package/dist/{schema-y8G5mDIS.js.map → schema-CNfrVRYp.js.map} +1 -1
- package/dist/schema-iXpYtKQl.cjs +63 -0
- package/dist/{schema-DgnkH0P6.cjs.map → schema-iXpYtKQl.cjs.map} +1 -1
- package/dist/{tokenizer-N-vAvRdj.js → serialize-utils-BuIZPaUc.js} +626 -358
- package/dist/serialize-utils-BuIZPaUc.js.map +1 -0
- package/dist/serialize-utils-CjTqQivB.cjs +37 -0
- package/dist/serialize-utils-CjTqQivB.cjs.map +1 -0
- package/dist/types.d.ts +235 -58
- package/dist/utils/base64.d.ts +1 -1
- package/dist/utils/hexfloat.d.ts +1 -1
- package/dist/utils/strip-comments.d.ts +1 -1
- package/package.json +8 -6
- package/dist/mapEntries-BJzyBUH5.cjs +0 -13
- package/dist/mapEntries-BJzyBUH5.cjs.map +0 -1
- package/dist/mapEntries-Ci_dppP6.js.map +0 -1
- package/dist/schema-DgnkH0P6.cjs +0 -63
- package/dist/tokenizer-BD08xbyd.cjs +0 -36
- package/dist/tokenizer-BD08xbyd.cjs.map +0 -1
- package/dist/tokenizer-N-vAvRdj.js.map +0 -1
package/README.ja.md
CHANGED
|
@@ -385,18 +385,22 @@ CBOR.format("h'68' + b64'aQ'", {
|
|
|
385
385
|
// b64'aQ'
|
|
386
386
|
```
|
|
387
387
|
|
|
388
|
-
|
|
388
|
+
保持した連結を `+` ではなく draft-27 の `t1<<...>>` / `b1<<...>>` 記法で
|
|
389
|
+
出力するには、[文字列連結と不定長文字列](#文字列連結と不定長文字列) の
|
|
390
|
+
`modernConcat` を参照してください。
|
|
391
|
+
|
|
392
|
+
### app-string / -sequence 記法を保持する
|
|
389
393
|
|
|
390
394
|
一部の組み込み拡張(`dt`/`DT`、`ip`/`IP`)は同じ値に対して `prefix'...'`
|
|
391
|
-
(
|
|
392
|
-
`prefix<<...>>`(
|
|
395
|
+
(app-string)、`` prefix`...` ``(backtick app-string)、
|
|
396
|
+
`prefix<<...>>`(app-sequence)、生のタグリテラル(`N(...)`)の
|
|
393
397
|
いずれの記法もサポートしていますが、デフォルトでは `CBOR.format()` を呼ぶ
|
|
394
398
|
たびに解決済みの値から `prefix'...'` を再生成します。そのため
|
|
395
399
|
`` DT`1969-07-21T02:56:16Z` `` も `DT<<'1969-07-21T02:56:16Z'>>` も、生の
|
|
396
400
|
タグ記法 `1(1749772800)` さえも、すべて `DT'...'` 記法に正規化され、さら
|
|
397
401
|
に非正規な `DT'...'` の表記(例えば `Z` の代わりに `+00:00` を使った場合
|
|
398
|
-
など)も書き換えられます。`
|
|
399
|
-
れていた表記のまま保持します。`
|
|
402
|
+
など)も書き換えられます。`preserveAppPrefix` を指定すると、実際に使わ
|
|
403
|
+
れていた表記のまま保持します。`appPrefix: false` を同時に指定した場合は
|
|
400
404
|
効果がありません(どちらにせよ元の表記に関わらず生のタグ記法になるため)。
|
|
401
405
|
これらの記法からパースされていない値にも効果はありません。
|
|
402
406
|
|
|
@@ -406,16 +410,50 @@ import { CBOR } from '@cbortech/cbor';
|
|
|
406
410
|
CBOR.format('1(1749772800)');
|
|
407
411
|
// "DT'2025-06-13T00:00:00Z'"
|
|
408
412
|
|
|
409
|
-
CBOR.format('1(1749772800)', {
|
|
413
|
+
CBOR.format('1(1749772800)', { preserveAppPrefix: true });
|
|
410
414
|
// "1(1749772800)"
|
|
411
415
|
|
|
412
|
-
CBOR.format("DT<<'1969-07-21T02:56:16Z'>>", {
|
|
416
|
+
CBOR.format("DT<<'1969-07-21T02:56:16Z'>>", { preserveAppPrefix: true });
|
|
413
417
|
// "DT<<'1969-07-21T02:56:16Z'>>"
|
|
414
418
|
|
|
415
|
-
CBOR.format('DT`1969-07-21T02:56:16Z`', {
|
|
419
|
+
CBOR.format('DT`1969-07-21T02:56:16Z`', { preserveAppPrefix: true });
|
|
416
420
|
// "DT`1969-07-21T02:56:16Z`"
|
|
417
421
|
```
|
|
418
422
|
|
|
423
|
+
### コメントを保持する
|
|
424
|
+
|
|
425
|
+
デフォルトでは、`CBOR.fromCDN()` はコメントを破棄し、`CBOR.format()` も
|
|
426
|
+
コメントを出力しません。`preserveComments: true` を指定すると、パース時に
|
|
427
|
+
コメントを取り込み、元々書かれていたマーカー(`#`・`//`・`/* */`・`/ /`)の
|
|
428
|
+
まま再出力します。
|
|
429
|
+
|
|
430
|
+
```ts
|
|
431
|
+
import { CBOR } from '@cbortech/cbor';
|
|
432
|
+
|
|
433
|
+
const text = '{ "a": 1 } # trailing comment';
|
|
434
|
+
|
|
435
|
+
CBOR.format(text, { indent: 2 });
|
|
436
|
+
// '{\n "a": 1\n}'
|
|
437
|
+
|
|
438
|
+
CBOR.format(text, { indent: 2, preserveComments: true });
|
|
439
|
+
// '{\n "a": 1\n} # trailing comment'
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
書かれていたマーカーを混在させたまま保持するのではなく、すべてのコメントの
|
|
443
|
+
マーカーを正規化したい場合は `comments` を使います — `'c-style'` は
|
|
444
|
+
`//` と `/* */`、`'cdn-style'` は `#` と `/ /` に正規化します。
|
|
445
|
+
`preserveComments: true` が指定されている場合は効果がありません(verbatim
|
|
446
|
+
が優先されます)。コメントを完全に削除するには `comments: 'strip'` を
|
|
447
|
+
明示的に指定するか(あるいは両方とも未指定のままにするか)します。
|
|
448
|
+
|
|
449
|
+
```ts
|
|
450
|
+
CBOR.format(text, { indent: 2, comments: 'c-style' });
|
|
451
|
+
// '{\n "a": 1\n} // trailing comment'
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
`indent` を指定して整形出力する場合のみ効果があります。1 行出力では改行で
|
|
455
|
+
終端する必要がある行コメントの性質上、コメントは常に取り除かれます。
|
|
456
|
+
|
|
419
457
|
### 空行を保持する
|
|
420
458
|
|
|
421
459
|
デフォルトでは、`CBOR.format()` は配列・マップの要素間(および `(_ ...)`
|
|
@@ -672,7 +710,7 @@ console.log(text);
|
|
|
672
710
|
|
|
673
711
|
## 文字列連結と不定長文字列
|
|
674
712
|
|
|
675
|
-
draft-ietf-cbor-edn-literals-
|
|
713
|
+
draft-ietf-cbor-edn-literals-27(§3.5 / §3.6)の app-extension
|
|
676
714
|
`t1` / `b1` / `ilbs` / `ilts` は、デフォルトで有効です。
|
|
677
715
|
|
|
678
716
|
`t1<<...>>` と `b1<<...>>` は、(テキストまたはバイト)文字列の引数を左から
|
|
@@ -683,11 +721,11 @@ draft-ietf-cbor-edn-literals-26(§3.4 / §3.5)の application extension
|
|
|
683
721
|
import { CBOR } from '@cbortech/cbor';
|
|
684
722
|
|
|
685
723
|
const text = CBOR.fromCDN('t1<<"Hello ", "world">>');
|
|
686
|
-
console.log(text.toCDN({
|
|
724
|
+
console.log(text.toCDN({ appPrefix: false }));
|
|
687
725
|
// "Hello world"
|
|
688
726
|
|
|
689
727
|
const bytes = CBOR.fromCDN("b1<<'Hello ', h'776f726c64'>>");
|
|
690
|
-
console.log(bytes.toCDN({
|
|
728
|
+
console.log(bytes.toCDN({ appPrefix: false }));
|
|
691
729
|
// 'Hello world'
|
|
692
730
|
```
|
|
693
731
|
|
|
@@ -701,29 +739,82 @@ streamstring 構文の置き換えですが、本ライブラリは従来構文
|
|
|
701
739
|
import { CBOR } from '@cbortech/cbor';
|
|
702
740
|
|
|
703
741
|
const v = CBOR.fromCDN("ilbs<<'Hello ', 'world'>>");
|
|
704
|
-
console.log(v.toCDN({
|
|
742
|
+
console.log(v.toCDN({ appPrefix: false }));
|
|
705
743
|
// (_ 'Hello ','world')
|
|
706
744
|
```
|
|
707
745
|
|
|
746
|
+
### `t1`/`b1`/`ilbs`/`ilts` 記法を出力する
|
|
747
|
+
|
|
748
|
+
パース側はすでに `t1`/`b1`/`ilbs`/`ilts` 記法を受理しますが、`toCDN()` /
|
|
749
|
+
`CBOR.format()` はデフォルトではこれらを自ら出力しません。保持した連結
|
|
750
|
+
(`preserveConcatenation`)は従来どおり `+` で、不定長文字列は従来どおり
|
|
751
|
+
`(_ ...)` streamstring 形式でレンダリングされます。`modernConcat` と
|
|
752
|
+
`modernStreamSyntax` を `true` にすると draft-27 の記法での出力を選択でき
|
|
753
|
+
ます。どちらもデフォルトは `false`(従来構文)で、`appPrefix` が `false`
|
|
754
|
+
の場合は従来構文にフォールバックします。
|
|
755
|
+
|
|
756
|
+
```ts
|
|
757
|
+
import { CBOR } from '@cbortech/cbor';
|
|
758
|
+
|
|
759
|
+
CBOR.format('"a" + "b"', {
|
|
760
|
+
indent: 2,
|
|
761
|
+
preserveConcatenation: true,
|
|
762
|
+
modernConcat: true,
|
|
763
|
+
});
|
|
764
|
+
// t1<<"a", "b">>
|
|
765
|
+
|
|
766
|
+
CBOR.format('(_ "a", "b")', { modernStreamSyntax: true });
|
|
767
|
+
// ilts<<"a","b">>
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
`modernConcat` は `...` による省略連結(§5.2)にも適用され、
|
|
771
|
+
`"a" + ... + "b"` は `t1<<"a", ..., "b">>` としてレンダリングされます。
|
|
772
|
+
通常の連結と異なり、これは `preserveConcatenation` の値に関わらず適用され
|
|
773
|
+
ます — 省略連結にはそもそも1つのリテラルに畳み込んだ状態が存在しないため
|
|
774
|
+
です。
|
|
775
|
+
|
|
776
|
+
> [!NOTE]
|
|
777
|
+
> どちらのオプションも `t1`/`b1`/`ilbs`/`ilts` のソースを従来記法に
|
|
778
|
+
> 変換するものではありません。`t1<<...>>`(や `ilbs<<...>>` など)
|
|
779
|
+
> からパースされた値は、`appPrefix` が `false` でなく、
|
|
780
|
+
> `encodingIndicators` が `'auto'`(どちらもデフォルト)であり、かつ
|
|
781
|
+
> ソースが単一行、または `indent` 指定時であれば、`modernConcat` /
|
|
782
|
+
> `modernStreamSyntax` の値に関わらずそのままの記法で出力されます。
|
|
783
|
+
> `encodingIndicators: 'always'`/`'never'` や `appPrefix: false` を指定
|
|
784
|
+
> した場合は、他の app-string 値と同様に正規化されます(例:
|
|
785
|
+
> `encodingIndicators: 'always'` では `t1<<"a", "b">>` が `"ab"_i` に
|
|
786
|
+
> なります)。また、複数行のソースは `indent` 未指定(1行出力)の場合、
|
|
787
|
+
> そのレイアウトを再現できないため正規化されます:
|
|
788
|
+
>
|
|
789
|
+
> ```ts
|
|
790
|
+
> CBOR.format('t1<<\n "a",\n "b"\n>>');
|
|
791
|
+
> // '"ab"' — indent未指定のため正規化される
|
|
792
|
+
> CBOR.format('t1<<\n "a",\n "b"\n>>', { indent: 2 });
|
|
793
|
+
> // 't1<<\n "a",\n "b"\n>>' — そのまま保持される
|
|
794
|
+
> ```
|
|
795
|
+
>
|
|
796
|
+
> 両オプションが影響するのは `+` チェーンや `(_ ...)` チャンク列から
|
|
797
|
+
> 再構築された値の出力のみです。
|
|
798
|
+
|
|
708
799
|
> [!NOTE]
|
|
709
|
-
> `t1` / `b1` という識別子は draft-
|
|
800
|
+
> `t1` / `b1` という識別子は draft-27 でも暫定(provisional)と明記されて
|
|
710
801
|
> おり、CBOR ワーキンググループにより改名される可能性があります。
|
|
711
802
|
|
|
712
803
|
## float
|
|
713
804
|
|
|
714
805
|
16 進数のビットパターンを IEEE 754 浮動小数点値として解釈します
|
|
715
|
-
(draft-ietf-cbor-edn-literals-
|
|
806
|
+
(draft-ietf-cbor-edn-literals-27 §3.8)。デフォルトで有効です。
|
|
716
807
|
|
|
717
808
|
```ts
|
|
718
809
|
import { CBOR } from '@cbortech/cbor';
|
|
719
810
|
|
|
720
811
|
const v = CBOR.fromCDN("float'7e00'");
|
|
721
|
-
console.log(v.toCDN({
|
|
812
|
+
console.log(v.toCDN({ appPrefix: false }));
|
|
722
813
|
// NaN
|
|
723
814
|
|
|
724
815
|
// バイト列から解釈する場合
|
|
725
816
|
const v2 = CBOR.fromCDN("float<<h'3f800000'>>");
|
|
726
|
-
console.log(v2.toCDN({
|
|
817
|
+
console.log(v2.toCDN({ appPrefix: false }));
|
|
727
818
|
// 1.0_2
|
|
728
819
|
```
|
|
729
820
|
|
|
@@ -736,7 +827,7 @@ extension があります。必要なものを `import` し、
|
|
|
736
827
|
### b32 / h32
|
|
737
828
|
|
|
738
829
|
[RFC 4648](https://www.rfc-editor.org/rfc/rfc4648) の Base32 エンコードによるバイト列リテラルです。
|
|
739
|
-
[RFC 8949](https://www.rfc-editor.org/rfc/rfc8949) §8 に記載があり、[draft-ietf-cbor-edn-literals](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/
|
|
830
|
+
[RFC 8949](https://www.rfc-editor.org/rfc/rfc8949) §8 に記載があり、[draft-ietf-cbor-edn-literals](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/27/) でも触れられています。
|
|
740
831
|
|
|
741
832
|
- `b32` — §6 Base32(`A–Z 2–7` アルファベット)
|
|
742
833
|
- `h32` — §7 Base32Hex(`0–9 A–V` アルファベット)
|
|
@@ -745,11 +836,11 @@ extension があります。必要なものを `import` し、
|
|
|
745
836
|
import { CBOR, b32, h32 } from '@cbortech/cbor';
|
|
746
837
|
|
|
747
838
|
const v1 = CBOR.fromCDN("b32'AEBAGBA'", { extensions: [b32] });
|
|
748
|
-
console.log(v1.toCDN({
|
|
839
|
+
console.log(v1.toCDN({ appPrefix: false }));
|
|
749
840
|
// h'01020304'
|
|
750
841
|
|
|
751
842
|
const v2 = CBOR.fromCDN("h32'00P00'", { extensions: [h32] });
|
|
752
|
-
console.log(v2.toCDN({
|
|
843
|
+
console.log(v2.toCDN({ appPrefix: false }));
|
|
753
844
|
// h'003200'
|
|
754
845
|
```
|
|
755
846
|
|
|
@@ -763,25 +854,24 @@ console.log(v2.toCDN({ appStrings: false }));
|
|
|
763
854
|
```ts
|
|
764
855
|
import { CBOR, same } from '@cbortech/cbor';
|
|
765
856
|
|
|
766
|
-
// すべての要素が同じバイト列かを検証し、最初の要素を返す
|
|
767
857
|
const v = CBOR.fromCDN("same<<h'0102', h'0102'>>", { extensions: [same] });
|
|
768
|
-
console.log(v.toCDN({
|
|
858
|
+
console.log(v.toCDN({ appPrefix: false }));
|
|
769
859
|
// h'0102'
|
|
770
860
|
|
|
771
861
|
// 要素が 1 つでも有効(常にパスする)
|
|
772
862
|
const v2 = CBOR.fromCDN('same<<42>>', { extensions: [same] });
|
|
773
|
-
console.log(v2.toCDN({
|
|
863
|
+
console.log(v2.toCDN({ appPrefix: false }));
|
|
774
864
|
// 42
|
|
775
865
|
```
|
|
776
866
|
|
|
777
867
|
---
|
|
778
868
|
|
|
779
|
-
追加の
|
|
869
|
+
追加の app-extension は別パッケージとして公開されています。必要なものを
|
|
780
870
|
インストールし、`extensions` オプションに渡して使います。
|
|
781
871
|
|
|
782
872
|
### hash
|
|
783
873
|
|
|
784
|
-
`hash` は [draft-ietf-cbor-edn-literals](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/
|
|
874
|
+
`hash` は [draft-ietf-cbor-edn-literals](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/27/) §3.4 で定義された標準の app-extension です。
|
|
785
875
|
ハッシュアルゴリズムと値を `hash'algorithm:value'` の形式で表現します。
|
|
786
876
|
実装には外部の暗号ライブラリが必要なため、[@cbortech/hash-extension](https://www.npmjs.com/package/@cbortech/hash-extension) として
|
|
787
877
|
別パッケージで提供しています。
|
|
@@ -806,7 +896,7 @@ const digest = cbor.parse(
|
|
|
806
896
|
|
|
807
897
|
### uuid
|
|
808
898
|
|
|
809
|
-
`uuid` はこのライブラリ独自の
|
|
899
|
+
`uuid` はこのライブラリ独自の app-extension です。
|
|
810
900
|
[@cbortech/uuid-extension](https://www.npmjs.com/package/@cbortech/uuid-extension) として別パッケージで提供しています。
|
|
811
901
|
|
|
812
902
|
```bash
|
|
@@ -826,7 +916,7 @@ const id = cbor.parse("uuid'550e8400-e29b-41d4-a716-446655440000'");
|
|
|
826
916
|
### set / map
|
|
827
917
|
|
|
828
918
|
`SET` と `MAP` は、タグ付きの Set / Map 値を扱うための、このライブラリ独自の
|
|
829
|
-
|
|
919
|
+
app-extension です。
|
|
830
920
|
[@cbortech/set-map-extensions](https://www.npmjs.com/package/@cbortech/set-map-extensions)
|
|
831
921
|
としてまとめて別パッケージで提供しています。`SET<<[...]>>` は配列に CBOR tag
|
|
832
922
|
258 を付けた値、`MAP<<{...}>>` は map に CBOR tag 259 を付けた値を生成します。
|
|
@@ -1083,9 +1173,11 @@ CDDL コンパイラは `@cbortech/cbor/cddl`
|
|
|
1083
1173
|
|
|
1084
1174
|
- CBOR
|
|
1085
1175
|
- [RFC 8949](https://www.rfc-editor.org/rfc/rfc8949)
|
|
1176
|
+
- CBOR Sequences
|
|
1177
|
+
- [RFC 8742](https://www.rfc-editor.org/rfc/rfc8742)
|
|
1086
1178
|
- CDN (CBOR-EDN)
|
|
1087
1179
|
- [draft-ietf-cbor-edn-literals-25](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/25/)
|
|
1088
|
-
- [draft-ietf-cbor-edn-literals-
|
|
1180
|
+
- [draft-ietf-cbor-edn-literals-27](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/27/)
|
|
1089
1181
|
- CDDL
|
|
1090
1182
|
- [RFC 8610](https://www.rfc-editor.org/rfc/rfc8610)
|
|
1091
1183
|
- [RFC 9682](https://www.rfc-editor.org/rfc/rfc9682)
|
|
@@ -1093,7 +1185,7 @@ CDDL コンパイラは `@cbortech/cbor/cddl`
|
|
|
1093
1185
|
|
|
1094
1186
|
補足:
|
|
1095
1187
|
|
|
1096
|
-
- CDN は draft-
|
|
1188
|
+
- CDN は draft-27 に準拠しつつ、draft-25 の `(_ ...)` streamstring 構文と
|
|
1097
1189
|
`+` による文字列連結構文も引き続きサポートしています。
|
|
1098
1190
|
- CDDL は RFC 8610 のすべての control operator と、RFC 9165 の `.plus`、
|
|
1099
1191
|
`.cat`、`.feature` をサポートしています。
|
package/README.md
CHANGED
|
@@ -392,19 +392,23 @@ CBOR.format("h'68' + b64'aQ'", {
|
|
|
392
392
|
// b64'aQ'
|
|
393
393
|
```
|
|
394
394
|
|
|
395
|
-
|
|
395
|
+
To render the preserved concatenation using draft-27's `t1<<...>>` /
|
|
396
|
+
`b1<<...>>` notation instead of `+`, see `modernConcat` in
|
|
397
|
+
[String Concatenation and Indefinite-Length Strings](#string-concatenation-and-indefinite-length-strings).
|
|
398
|
+
|
|
399
|
+
### Preserve app-string/-sequence notation
|
|
396
400
|
|
|
397
401
|
Some built-in extensions (`dt`/`DT`, `ip`/`IP`) support `prefix'...'`
|
|
398
|
-
(
|
|
399
|
-
`prefix<<...>>` (
|
|
402
|
+
(app-string), `` prefix`...` `` (backtick app-string),
|
|
403
|
+
`prefix<<...>>` (app-sequence), and a raw tag literal (`N(...)`)
|
|
400
404
|
notation for the same value, and by default regenerate `prefix'...'` from
|
|
401
405
|
the resolved value on every `CBOR.format()` call — so
|
|
402
406
|
`` DT`1969-07-21T02:56:16Z` ``, `DT<<'1969-07-21T02:56:16Z'>>`, and even the
|
|
403
407
|
raw tag form `1(1749772800)` all normalize to `DT'...'` notation, and a
|
|
404
408
|
non-canonical `DT'...'` spelling (e.g. a `+00:00` offset instead of `Z`)
|
|
405
|
-
gets rewritten too. `
|
|
409
|
+
gets rewritten too. `preserveAppPrefix` keeps the original spelling
|
|
406
410
|
instead — whichever form was used. It has no effect when
|
|
407
|
-
`
|
|
411
|
+
`appPrefix: false` is also set (raw tag notation is used either way
|
|
408
412
|
regardless of the original spelling), or on values not parsed from one of
|
|
409
413
|
these forms.
|
|
410
414
|
|
|
@@ -414,16 +418,50 @@ import { CBOR } from '@cbortech/cbor';
|
|
|
414
418
|
CBOR.format('1(1749772800)');
|
|
415
419
|
// "DT'2025-06-13T00:00:00Z'"
|
|
416
420
|
|
|
417
|
-
CBOR.format('1(1749772800)', {
|
|
421
|
+
CBOR.format('1(1749772800)', { preserveAppPrefix: true });
|
|
418
422
|
// "1(1749772800)"
|
|
419
423
|
|
|
420
|
-
CBOR.format("DT<<'1969-07-21T02:56:16Z'>>", {
|
|
424
|
+
CBOR.format("DT<<'1969-07-21T02:56:16Z'>>", { preserveAppPrefix: true });
|
|
421
425
|
// "DT<<'1969-07-21T02:56:16Z'>>"
|
|
422
426
|
|
|
423
|
-
CBOR.format('DT`1969-07-21T02:56:16Z`', {
|
|
427
|
+
CBOR.format('DT`1969-07-21T02:56:16Z`', { preserveAppPrefix: true });
|
|
424
428
|
// "DT`1969-07-21T02:56:16Z`"
|
|
425
429
|
```
|
|
426
430
|
|
|
431
|
+
### Preserve comments
|
|
432
|
+
|
|
433
|
+
By default, `CBOR.fromCDN()` discards comments and `CBOR.format()` emits
|
|
434
|
+
none. `preserveComments: true` captures them while parsing and re-emits each
|
|
435
|
+
comment verbatim, with whichever marker (`#`, `//`, `/* */`, `/ /`) it was
|
|
436
|
+
originally written with.
|
|
437
|
+
|
|
438
|
+
```ts
|
|
439
|
+
import { CBOR } from '@cbortech/cbor';
|
|
440
|
+
|
|
441
|
+
const text = '{ "a": 1 } # trailing comment';
|
|
442
|
+
|
|
443
|
+
CBOR.format(text, { indent: 2 });
|
|
444
|
+
// '{\n "a": 1\n}'
|
|
445
|
+
|
|
446
|
+
CBOR.format(text, { indent: 2, preserveComments: true });
|
|
447
|
+
// '{\n "a": 1\n} # trailing comment'
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
To normalize every comment's marker instead of keeping the mix as originally
|
|
451
|
+
written, use `comments` — `'c-style'` for `//` and `/* */`, or
|
|
452
|
+
`'cdn-style'` for `#` and `/ /`. It has no effect when `preserveComments` is
|
|
453
|
+
`true` (verbatim wins); explicitly set `comments: 'strip'` (or leave
|
|
454
|
+
both options unset) to drop comments entirely.
|
|
455
|
+
|
|
456
|
+
```ts
|
|
457
|
+
CBOR.format(text, { indent: 2, comments: 'c-style' });
|
|
458
|
+
// '{\n "a": 1\n} // trailing comment'
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
Only effective when `indent` enables pretty-printing: single-line output
|
|
462
|
+
strips all comments regardless, since line comments can only be terminated
|
|
463
|
+
by a newline.
|
|
464
|
+
|
|
427
465
|
### Preserve blank lines
|
|
428
466
|
|
|
429
467
|
By default, `CBOR.format()` drops blank lines between array/map entries (and
|
|
@@ -683,8 +721,8 @@ console.log(text);
|
|
|
683
721
|
|
|
684
722
|
## String Concatenation and Indefinite-Length Strings
|
|
685
723
|
|
|
686
|
-
The `t1` / `b1` / `ilbs` / `ilts`
|
|
687
|
-
draft-ietf-cbor-edn-literals-
|
|
724
|
+
The `t1` / `b1` / `ilbs` / `ilts` app-extensions from
|
|
725
|
+
draft-ietf-cbor-edn-literals-27 (§3.5 / §3.6) are enabled by default.
|
|
688
726
|
|
|
689
727
|
`t1<<...>>` and `b1<<...>>` join (text or byte) string arguments from left to
|
|
690
728
|
right into a single text string (`t1`) or byte string (`b1`). Arguments may
|
|
@@ -694,11 +732,11 @@ also be ellipses (`...`) to elide parts of a string.
|
|
|
694
732
|
import { CBOR } from '@cbortech/cbor';
|
|
695
733
|
|
|
696
734
|
const text = CBOR.fromCDN('t1<<"Hello ", "world">>');
|
|
697
|
-
console.log(text.toCDN({
|
|
735
|
+
console.log(text.toCDN({ appPrefix: false }));
|
|
698
736
|
// "Hello world"
|
|
699
737
|
|
|
700
738
|
const bytes = CBOR.fromCDN("b1<<'Hello ', h'776f726c64'>>");
|
|
701
|
-
console.log(bytes.toCDN({
|
|
739
|
+
console.log(bytes.toCDN({ appPrefix: false }));
|
|
702
740
|
// 'Hello world'
|
|
703
741
|
```
|
|
704
742
|
|
|
@@ -711,29 +749,81 @@ documents; this library keeps accepting the legacy syntax on input.
|
|
|
711
749
|
import { CBOR } from '@cbortech/cbor';
|
|
712
750
|
|
|
713
751
|
const v = CBOR.fromCDN("ilbs<<'Hello ', 'world'>>");
|
|
714
|
-
console.log(v.toCDN({
|
|
752
|
+
console.log(v.toCDN({ appPrefix: false }));
|
|
715
753
|
// (_ 'Hello ','world')
|
|
716
754
|
```
|
|
717
755
|
|
|
756
|
+
### Emitting `t1`/`b1`/`ilbs`/`ilts` notation
|
|
757
|
+
|
|
758
|
+
Parsing already accepts `t1`/`b1`/`ilbs`/`ilts` notation, but by default
|
|
759
|
+
`toCDN()`/`CBOR.format()` never emit it on their own: a preserved
|
|
760
|
+
concatenation (`preserveConcatenation`) still renders as `+`, and an
|
|
761
|
+
indefinite-length string still renders as the legacy `(_ ...)` streamstring
|
|
762
|
+
form. `modernConcat` and `modernStreamSyntax` opt into emitting the draft-27
|
|
763
|
+
notation instead — both default to `false` (the legacy syntax), and both fall
|
|
764
|
+
back to it when `appPrefix` is `false`.
|
|
765
|
+
|
|
766
|
+
```ts
|
|
767
|
+
import { CBOR } from '@cbortech/cbor';
|
|
768
|
+
|
|
769
|
+
CBOR.format('"a" + "b"', {
|
|
770
|
+
indent: 2,
|
|
771
|
+
preserveConcatenation: true,
|
|
772
|
+
modernConcat: true,
|
|
773
|
+
});
|
|
774
|
+
// t1<<"a", "b">>
|
|
775
|
+
|
|
776
|
+
CBOR.format('(_ "a", "b")', { modernStreamSyntax: true });
|
|
777
|
+
// ilts<<"a","b">>
|
|
778
|
+
```
|
|
779
|
+
|
|
780
|
+
`modernConcat` also applies within a `...` elision chain (§5.2), rendering
|
|
781
|
+
`"a" + ... + "b"` as `t1<<"a", ..., "b">>` — unlike plain concatenation, this
|
|
782
|
+
happens regardless of `preserveConcatenation`, since an elision chain has no
|
|
783
|
+
single-literal collapsed form to fall back to in the first place.
|
|
784
|
+
|
|
785
|
+
> [!NOTE]
|
|
786
|
+
> Neither option converts `t1`/`b1`/`ilbs`/`ilts` source back to the
|
|
787
|
+
> legacy notation: a value parsed from `t1<<...>>` (or `ilbs<<...>>`, etc.)
|
|
788
|
+
> keeps that exact spelling on output regardless of `modernConcat` /
|
|
789
|
+
> `modernStreamSyntax` — as long as `appPrefix` is not `false`,
|
|
790
|
+
> `encodingIndicators` is `'auto'` (both defaults), and the source is either
|
|
791
|
+
> single-line or being rendered with `indent` enabled. `encodingIndicators:
|
|
792
|
+
'always'`/`'never'` or `appPrefix: false` still normalize it like any
|
|
793
|
+
> other app-string value (e.g. `t1<<"a", "b">>` becomes `"ab"_i`
|
|
794
|
+
> under `encodingIndicators: 'always'`), and a multi-line source falls back
|
|
795
|
+
> to normalized output in single-line mode (that layout can't be reproduced
|
|
796
|
+
> without `indent`):
|
|
797
|
+
>
|
|
798
|
+
> ```ts
|
|
799
|
+
> CBOR.format('t1<<\n "a",\n "b"\n>>');
|
|
800
|
+
> // '"ab"' — falls back: multi-line source, no `indent`
|
|
801
|
+
> CBOR.format('t1<<\n "a",\n "b"\n>>', { indent: 2 });
|
|
802
|
+
> // 't1<<\n "a",\n "b"\n>>' — kept verbatim
|
|
803
|
+
> ```
|
|
804
|
+
>
|
|
805
|
+
> Both options only affect how a value reconstructed from a `+` chain or a
|
|
806
|
+
> `(_ ...)` chunk list is _newly_ rendered.
|
|
807
|
+
|
|
718
808
|
> [!NOTE]
|
|
719
|
-
> The identifiers `t1` and `b1` are explicitly provisional in draft-
|
|
809
|
+
> The identifiers `t1` and `b1` are explicitly provisional in draft-27 and
|
|
720
810
|
> may be renamed by the CBOR working group.
|
|
721
811
|
|
|
722
812
|
## float
|
|
723
813
|
|
|
724
814
|
Interprets a hex bit-pattern as an IEEE 754 floating-point value
|
|
725
|
-
(draft-ietf-cbor-edn-literals-
|
|
815
|
+
(draft-ietf-cbor-edn-literals-27 §3.8). Enabled by default.
|
|
726
816
|
|
|
727
817
|
```ts
|
|
728
818
|
import { CBOR } from '@cbortech/cbor';
|
|
729
819
|
|
|
730
820
|
const v = CBOR.fromCDN("float'7e00'");
|
|
731
|
-
console.log(v.toCDN({
|
|
821
|
+
console.log(v.toCDN({ appPrefix: false }));
|
|
732
822
|
// NaN
|
|
733
823
|
|
|
734
824
|
// Interpret bytes as float bits
|
|
735
825
|
const v2 = CBOR.fromCDN("float<<h'3f800000'>>");
|
|
736
|
-
console.log(v2.toCDN({
|
|
826
|
+
console.log(v2.toCDN({ appPrefix: false }));
|
|
737
827
|
// 1.0_2
|
|
738
828
|
```
|
|
739
829
|
|
|
@@ -747,7 +837,7 @@ default. Import what you need and pass it through the `extensions` option.
|
|
|
747
837
|
Byte-string literals using [RFC 4648](https://www.rfc-editor.org/rfc/rfc4648)
|
|
748
838
|
Base32 encoding. These prefixes are described in §8 of
|
|
749
839
|
[RFC 8949](https://www.rfc-editor.org/rfc/rfc8949) and also mentioned in
|
|
750
|
-
[draft-ietf-cbor-edn-literals](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/
|
|
840
|
+
[draft-ietf-cbor-edn-literals](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/27/).
|
|
751
841
|
|
|
752
842
|
- `b32` — §6 Base32 (`A–Z 2–7` alphabet)
|
|
753
843
|
- `h32` — §7 Base32Hex (`0–9 A–V` alphabet)
|
|
@@ -756,11 +846,11 @@ Base32 encoding. These prefixes are described in §8 of
|
|
|
756
846
|
import { CBOR, b32, h32 } from '@cbortech/cbor';
|
|
757
847
|
|
|
758
848
|
const v1 = CBOR.fromCDN("b32'AEBAGBA'", { extensions: [b32] });
|
|
759
|
-
console.log(v1.toCDN({
|
|
849
|
+
console.log(v1.toCDN({ appPrefix: false }));
|
|
760
850
|
// h'01020304'
|
|
761
851
|
|
|
762
852
|
const v2 = CBOR.fromCDN("h32'00P00'", { extensions: [h32] });
|
|
763
|
-
console.log(v2.toCDN({
|
|
853
|
+
console.log(v2.toCDN({ appPrefix: false }));
|
|
764
854
|
// h'003200'
|
|
765
855
|
```
|
|
766
856
|
|
|
@@ -774,24 +864,24 @@ identical CBOR bytes and returns the first item. This extension is described in
|
|
|
774
864
|
import { CBOR, same } from '@cbortech/cbor';
|
|
775
865
|
|
|
776
866
|
const v = CBOR.fromCDN("same<<h'0102', h'0102'>>", { extensions: [same] });
|
|
777
|
-
console.log(v.toCDN({
|
|
867
|
+
console.log(v.toCDN({ appPrefix: false }));
|
|
778
868
|
// h'0102'
|
|
779
869
|
|
|
780
870
|
// A single-item sequence always passes
|
|
781
871
|
const v2 = CBOR.fromCDN('same<<42>>', { extensions: [same] });
|
|
782
|
-
console.log(v2.toCDN({
|
|
872
|
+
console.log(v2.toCDN({ appPrefix: false }));
|
|
783
873
|
// 42
|
|
784
874
|
```
|
|
785
875
|
|
|
786
876
|
---
|
|
787
877
|
|
|
788
|
-
Additional
|
|
878
|
+
Additional app-extensions are published as separate packages. Install
|
|
789
879
|
the ones you need and pass them through the `extensions` option.
|
|
790
880
|
|
|
791
881
|
### hash
|
|
792
882
|
|
|
793
|
-
`hash` is an
|
|
794
|
-
[draft-ietf-cbor-edn-literals](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/
|
|
883
|
+
`hash` is an app-extension defined in §3.4 of
|
|
884
|
+
[draft-ietf-cbor-edn-literals](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/27/).
|
|
795
885
|
It represents cryptographic hash values in the form `hash'algorithm:value'`.
|
|
796
886
|
Because it requires an external cryptographic library, it is provided separately
|
|
797
887
|
as [@cbortech/hash-extension](https://www.npmjs.com/package/@cbortech/hash-extension).
|
|
@@ -816,7 +906,7 @@ const digest = cbor.parse(
|
|
|
816
906
|
|
|
817
907
|
### uuid
|
|
818
908
|
|
|
819
|
-
`uuid` is a library-specific
|
|
909
|
+
`uuid` is a library-specific app-extension, provided separately as
|
|
820
910
|
[@cbortech/uuid-extension](https://www.npmjs.com/package/@cbortech/uuid-extension).
|
|
821
911
|
|
|
822
912
|
```bash
|
|
@@ -835,7 +925,7 @@ const id = cbor.parse("uuid'550e8400-e29b-41d4-a716-446655440000'");
|
|
|
835
925
|
|
|
836
926
|
### set / map
|
|
837
927
|
|
|
838
|
-
`SET` and `MAP` are library-specific
|
|
928
|
+
`SET` and `MAP` are library-specific app-extensions for tagged Set and
|
|
839
929
|
Map values. They are provided together as
|
|
840
930
|
[@cbortech/set-map-extensions](https://www.npmjs.com/package/@cbortech/set-map-extensions).
|
|
841
931
|
`SET<<[...]>>` produces CBOR tag 258 over an array, and `MAP<<{...}>>` produces
|
|
@@ -1093,9 +1183,11 @@ types).
|
|
|
1093
1183
|
|
|
1094
1184
|
- CBOR
|
|
1095
1185
|
- [RFC 8949](https://www.rfc-editor.org/rfc/rfc8949)
|
|
1186
|
+
- CBOR Sequences
|
|
1187
|
+
- [RFC 8742](https://www.rfc-editor.org/rfc/rfc8742)
|
|
1096
1188
|
- CDN (CBOR-EDN)
|
|
1097
1189
|
- [draft-ietf-cbor-edn-literals-25](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/25/)
|
|
1098
|
-
- [draft-ietf-cbor-edn-literals-
|
|
1190
|
+
- [draft-ietf-cbor-edn-literals-27](https://datatracker.ietf.org/doc/draft-ietf-cbor-edn-literals/27/)
|
|
1099
1191
|
- CDDL
|
|
1100
1192
|
- [RFC 8610](https://www.rfc-editor.org/rfc/rfc8610)
|
|
1101
1193
|
- [RFC 9682](https://www.rfc-editor.org/rfc/rfc9682)
|
|
@@ -1103,7 +1195,7 @@ types).
|
|
|
1103
1195
|
|
|
1104
1196
|
Implementation notes:
|
|
1105
1197
|
|
|
1106
|
-
- CDN follows draft-
|
|
1198
|
+
- CDN follows draft-27 while retaining draft-25's `(_ ...)` streamstring syntax
|
|
1107
1199
|
and `+` string-concatenation syntax.
|
|
1108
1200
|
- CDDL implements every RFC 8610 control operator, plus RFC 9165's `.plus`,
|
|
1109
1201
|
`.cat`, and `.feature`.
|
|
@@ -21,6 +21,28 @@ export declare class CborAppSeqResult extends CborItem {
|
|
|
21
21
|
readonly ednSource: string;
|
|
22
22
|
constructor(inner: CborItem, ednSource: string);
|
|
23
23
|
get _containsCdnContainer(): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Same approach as `CborTag`: tokenize this wrapper's own `_toCDN()`
|
|
26
|
+
* output rather than delegating to `this.inner._isMultiWordText()`.
|
|
27
|
+
* Delegating to `this.inner` was tried and found wrong: for
|
|
28
|
+
* `ilbs<<h'68656c6c6f20776f726c64'>>`, the chunk's raw bytes decode to
|
|
29
|
+
* printable "hello world", so `this.inner`'s own semantic check reports
|
|
30
|
+
* it as multi-word — but the *actual* rendering is the preserved
|
|
31
|
+
* `ilbs<<...>>` app-sequence spelling, where that chunk appears as a
|
|
32
|
+
* `h'...'` literal, never as decoded text; the semantic prediction and
|
|
33
|
+
* the real output disagree. Tokenizing `this._toCDN()` directly sees
|
|
34
|
+
* whichever one actually happens: the preserved `ednSource` verbatim
|
|
35
|
+
* (`isMultiWordRenderedLiteral` peels the `prefix<<...>>` wrapper and
|
|
36
|
+
* checks each item under the loose rule, same as `<<...>>` — a
|
|
37
|
+
* multi-word text item like `ilts<<"two words">>` still always counts,
|
|
38
|
+
* a prefixed-literal item like `ilbs<<h'00'>>` does not) or, in the
|
|
39
|
+
* 'always'/'never' `encodingIndicators` modes, a pure passthrough to
|
|
40
|
+
* `this.inner._toCDN()` with no extra wrapping (any node needing that to
|
|
41
|
+
* be caught, like a self-disqualifying `CborIndefiniteByteString`, has
|
|
42
|
+
* already produced a `\n` in that string, which the caller's own
|
|
43
|
+
* `s.includes('\n')` check picks up independently either way).
|
|
44
|
+
*/
|
|
45
|
+
_isMultiWordText(options: ToCDNOptions | undefined, strict?: boolean): boolean;
|
|
24
46
|
_encodeTo(writer: CborWriter, options?: ToCBOROptions): void;
|
|
25
47
|
_toCDN(options: ToCDNOptions | undefined, depth: number): string;
|
|
26
48
|
_toJS(options?: ToJSOptions): unknown;
|
|
@@ -48,6 +48,22 @@ export declare class CborByteString extends CborItem {
|
|
|
48
48
|
ednCommentSyntax?: ByteCommentSyntax;
|
|
49
49
|
ednParts?: readonly CborByteStringPart[];
|
|
50
50
|
});
|
|
51
|
+
/**
|
|
52
|
+
* Only the "bare sqstr text with 2+ words" case — the "is this a
|
|
53
|
+
* prefixed literal" question is deliberately *not* predicted here from
|
|
54
|
+
* raw bytes at all (a subclass like `CborIpExt` might override `_toCDN()`
|
|
55
|
+
* to render something else entirely, e.g. a preserved
|
|
56
|
+
* `ip<<'192.0.2.42'>>` app-sequence spelling, that raw-byte prediction
|
|
57
|
+
* knows nothing about — see `isMultiWordByteString`'s doc). That
|
|
58
|
+
* question is instead answered from the *actual rendering*: for a bare
|
|
59
|
+
* entry, `serializeContainer`'s own `isPrefixedLiteralText(s)` check
|
|
60
|
+
* already covers it (this node's render *is* `s`, unobscured); for one
|
|
61
|
+
* wrapped in a `CborTag`, `CborTag._isMultiWordText`'s
|
|
62
|
+
* `isMultiWordRenderedLiteral` check covers it instead. `strict` isn't
|
|
63
|
+
* needed here at all now — it's accepted purely for interface
|
|
64
|
+
* consistency with the base class.
|
|
65
|
+
*/
|
|
66
|
+
_isMultiWordText(options: ToCDNOptions | undefined, _strict?: boolean): boolean;
|
|
51
67
|
_encodeTo(writer: CborWriter, _options?: ToCBOROptions): void;
|
|
52
68
|
_toCDN(options: ToCDNOptions | undefined, _depth: number): string;
|
|
53
69
|
_toJS(_options?: ToJSOptions): unknown;
|
|
@@ -2,7 +2,7 @@ import { ToCDNOptions, ToJSOptions, ToCBOROptions } from '../types';
|
|
|
2
2
|
import { CborItem, AnnotatedLine } from './CborItem';
|
|
3
3
|
import { CborWriter, EncodingWidth } from '../cbor/encode';
|
|
4
4
|
/**
|
|
5
|
-
* CBOR Sequence Literal (§2.
|
|
5
|
+
* CBOR Sequence Literal (§2.3.4) — `<<item, item, ...>>`.
|
|
6
6
|
*
|
|
7
7
|
* Encodes as a definite-length byte string whose value is the concatenation
|
|
8
8
|
* of the CBOR encodings of the contained items.
|
package/dist/ast/CborFloat.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ export declare class CborFloat extends CborItem {
|
|
|
22
22
|
/**
|
|
23
23
|
* Original app-string source (e.g. `float'7e00'`), set by the parser when
|
|
24
24
|
* this float is the result of a `float'...'` app-string. Used by toCDN()
|
|
25
|
-
* to round-trip the literal when `
|
|
25
|
+
* to round-trip the literal when `appPrefix` is not false.
|
|
26
26
|
*/
|
|
27
27
|
ednSource?: string;
|
|
28
28
|
/**
|