From a05bf0cb7a2baf569618ccdd850d6dfb32f61a6c Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Fri, 5 Mar 2021 21:14:15 +0100 Subject: [PATCH] Fix canonical encoding of Set and Dictionary --- implementations/javascript/src/dictionary.ts | 20 +++++++++++++------- implementations/javascript/src/encoder.ts | 8 +------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/implementations/javascript/src/dictionary.ts b/implementations/javascript/src/dictionary.ts index d620a93..0352876 100644 --- a/implementations/javascript/src/dictionary.ts +++ b/implementations/javascript/src/dictionary.ts @@ -60,10 +60,16 @@ export class Dictionary extends FlexMap) { if (encoder.canonical) { - const pieces = Array.from(this).map(([k, v]) => - Bytes.concat([canonicalEncode(k), canonicalEncode(v)])); - pieces.sort(Bytes.compare); - encoder.encoderawvalues(Tag.Dictionary, pieces); + const entries = Array.from(this); + const pieces = entries.map<[Bytes, number]>(([k, _v], i) => [canonicalEncode(k), i]); + pieces.sort((a, b) => Bytes.compare(a[0], b[0])); + encoder.emitbyte(Tag.Dictionary); + pieces.forEach(([_encodedKey, i]) => { + const [k, v] = entries[i]; + encoder.push(k); + encoder.push(v as unknown as Value); // Suuuuuuuper unsound + }); + encoder.emitbyte(Tag.End); } else { encoder.emitbyte(Tag.Dictionary); this.forEach((v, k) => { @@ -116,9 +122,9 @@ export class Set extends FlexSet> { [PreserveOn](encoder: Encoder) { if (encoder.canonical) { - const pieces = Array.from(this).map(k => canonicalEncode(k)); - pieces.sort(Bytes.compare); - encoder.encoderawvalues(Tag.Set, pieces); + const pieces = Array.from(this).map<[Bytes, Value]>(k => [canonicalEncode(k), k]); + pieces.sort((a, b) => Bytes.compare(a[0], b[0])); + encoder.encodevalues(Tag.Set, pieces.map(e => e[1])); } else { encoder.encodevalues(Tag.Set, this); } diff --git a/implementations/javascript/src/encoder.ts b/implementations/javascript/src/encoder.ts index 5ef4b8e..9647fee 100644 --- a/implementations/javascript/src/encoder.ts +++ b/implementations/javascript/src/encoder.ts @@ -1,5 +1,5 @@ import { Tag } from "./constants"; -import { Bytes, BytesLike, underlying } from "./bytes"; +import { Bytes } from "./bytes"; import { Value } from "./values"; import { PreserveOn } from "./symbols"; import { EncodeError } from "./codec"; @@ -137,12 +137,6 @@ export class Encoder { this.emitbyte(Tag.End); } - encoderawvalues(tag: Tag, items: BytesLike[]) { - this.emitbyte(tag); - items.forEach((i) => this.emitbytes(underlying(i))); - this.emitbyte(Tag.End); - } - push(v: Encodable) { if (isPreservable(v)) { v[PreserveOn](this as unknown as Encoder);