Skip to content

Commit 6cb60eb

Browse files
committed
null cannot be type mapped. Add output function for keys added to dictionary.
1 parent f6669f6 commit 6cb60eb

4 files changed

Lines changed: 45 additions & 29 deletions

File tree

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,17 @@ const decoded = CBOR.Decoder.decode(frozen);
3939

4040
### ESM
4141
```
42-
import { Encoder, Decoder } from "./node_modules/@cdot/cbor/src/index.js";
42+
import { Encoder, Decoder } from "@cdot/cbor";
4343
const frozen = Encoder.encode(data);
4444
```
4545
### CommonJS
4646
```
47-
const CBOR = require("@cdot/cbor");
48-
const frozen = CBOR.Encoder.encode(data);
47+
const { Encoder, Decoder } = require("@cdot/cbor");
48+
const frozen = Encoder.encode(data);
4949
```
50-
## `requirejs`
50+
## AMD
5151
```
52-
requirejs(["@cdot/cbor"], CBOR => {
52+
require(["@cdot/cbor"], CBOR => {
5353
const frozen = CBOR.Encoder.encode(data);
5454
});
5555
```

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@cdot/cbor",
3-
"version": "1.0.1",
3+
"version": "1.0.2",
44
"description": "CBOR implementation using streams",
55
"type": "module",
66
"main": "dist/cjs/index.js",

src/KeyDictionaryHandler.js

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,18 @@
22
License MIT. See README.md at the root of this distribution for full copyright
33
and license information.*/
44

5-
// Rename keys from their temporary index form to the actual key
6-
// looked up in the key dictionary. This is only used when a key
7-
// dictionary is read from the end of the input data.
8-
const key_re = /^_#_(.+)$/;
9-
const PROCESSED = "#(^)#";
5+
// Placeholder key construction. Mixed unicode scripts are used to
6+
// minimise risk of collision with real key names.
7+
const SECRET = "ആଈ";
8+
9+
// Rename keys from their placeholder form to the actual key looked up
10+
// in the key dictionary.
11+
const key_re = new RegExp(`^${SECRET}(.+)$`);
12+
13+
// Key used when a datum has already been processed - removed after
14+
// key remapping. Mixed unicode scripts are used to minimise risk of
15+
// collision with real key names.
16+
const PROCESSED = "ρѓσςεรຂεϑ";
1017

1118
/**
1219
* Locate uses of key placeholders in data and replace them with
@@ -17,7 +24,7 @@ function remapKeys(data, i2k) {
1724
const processed = [];
1825

1926
function _remapKeys(data) {
20-
if (typeof data === "object") {
27+
if (typeof data === "object" && data !== null) {
2128
if (Array.isArray(data)) {
2229
for (const d of data)
2330
_remapKeys(d);
@@ -44,26 +51,23 @@ function remapKeys(data, i2k) {
4451
}
4552

4653
/**
47-
* To reduce data volume, it is possible to use a key dictionary (a
48-
* list of all known keys used in JS objects). This can save a lot of
49-
* space when a lot of similar objects are used.
50-
* This mixin can be used in 3 modes:
51-
* * known keys, where the caller provides a list of keys they expect
52-
* to be there.
53-
* * partial keys, where some (but not necessarily all) keys are known
54-
* at write time.
55-
* * unknown keys, where no keys are known.
56-
* The size of the generated binary will vary according to which mode
57-
* is used, with known keys being the smallest and fastest, and unknown
58-
* keys the largest and slowest.
54+
* To reduce data volume, use a key dictionary (a list of all known
55+
* keys used in JS objects). This can save a lot of space when a lot
56+
* of similar objects are used.
5957
* @mixin KeyDictionaryHandler
6058
*/
6159
const KeyDictionaryHandler = superclass => class extends superclass {
6260

6361
/**
6462
* The same parameters have to be provided to the tag handlers
6563
* at both ends of the communication.
66-
* @param {string[]} options.keys list of keys for the key dictionary
64+
* @param {string[]} options.keys list of known keys for the key.
65+
* Minimum output size will be achieved when this list is complete
66+
* i.e. all possible keys are known in advance.
67+
* @param {function?} options.added optional function called when an
68+
* unknown key is added to the key set. Passed the key and the id it was
69+
* assigned. This can be useful when building a comprehensive key set
70+
* for communication in complex code.
6771
*/
6872
constructor(options) {
6973
super(options);
@@ -140,10 +144,12 @@ const KeyDictionaryHandler = superclass => class extends superclass {
140144
return key;
141145
let id = this.k2i[key];
142146
if (typeof id === "undefined") {
143-
/* istanbul ignore if */
147+
// It might seem tempting to compare the encoding length of the
148+
// id against the raw key length, but it rarely improves the
149+
// data volume enough to make the complexity worthwhile.
144150
this.k2i[key] = id = this.i2k.length + this.i2k_added.length;
145-
if (this.options.debug)
146-
this.options.debug(`\tKDh add ${key} ${id}`);
151+
if (this.options.added)
152+
this.options.added(key, id);
147153
this.i2k_added.push(key);
148154
}
149155
return id;
@@ -165,7 +171,7 @@ const KeyDictionaryHandler = superclass => class extends superclass {
165171
// the dictionary.
166172
// SMELL: there's a vanishingly small risk that this might
167173
// duplicate a "real" key.
168-
return `_#_${id}`;
174+
return `${SECRET}${id}`;
169175
}
170176
};
171177

test/KeyDictionary.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,4 +107,14 @@ describe("KeyDictionary", () => {
107107

108108
assert.deepEqual(thawed, ABC);
109109
});
110+
111+
/*it("data length", () => {
112+
const none = new TagHandler();
113+
const some = new (KeyDictionaryHandler(TagHandler))({ added: console.log });
114+
const abc = { "a": 1, "ab": 2, "abc": 3, "abcd": 4, "abcde": 5 };
115+
116+
const ABC = [ abc, abc, abc, abc, abc, abc, abc, abc, abc, abc ];
117+
console.log(Encoder.encode(ABC, none).byteLength);
118+
console.log(Encoder.encode(ABC, some).byteLength);
119+
});*/
110120
});

0 commit comments

Comments
 (0)