Fix canonical encoding of Set and Dictionary
This commit is contained in:
parent
4022b76650
commit
a05bf0cb7a
|
@ -60,10 +60,16 @@ export class Dictionary<V, T extends object = DefaultPointer> extends FlexMap<Va
|
||||||
|
|
||||||
[PreserveOn](encoder: Encoder<T>) {
|
[PreserveOn](encoder: Encoder<T>) {
|
||||||
if (encoder.canonical) {
|
if (encoder.canonical) {
|
||||||
const pieces = Array.from(this).map(([k, v]) =>
|
const entries = Array.from(this);
|
||||||
Bytes.concat([canonicalEncode(k), canonicalEncode(v)]));
|
const pieces = entries.map<[Bytes, number]>(([k, _v], i) => [canonicalEncode(k), i]);
|
||||||
pieces.sort(Bytes.compare);
|
pieces.sort((a, b) => Bytes.compare(a[0], b[0]));
|
||||||
encoder.encoderawvalues(Tag.Dictionary, pieces);
|
encoder.emitbyte(Tag.Dictionary);
|
||||||
|
pieces.forEach(([_encodedKey, i]) => {
|
||||||
|
const [k, v] = entries[i];
|
||||||
|
encoder.push(k);
|
||||||
|
encoder.push(v as unknown as Value<T>); // Suuuuuuuper unsound
|
||||||
|
});
|
||||||
|
encoder.emitbyte(Tag.End);
|
||||||
} else {
|
} else {
|
||||||
encoder.emitbyte(Tag.Dictionary);
|
encoder.emitbyte(Tag.Dictionary);
|
||||||
this.forEach((v, k) => {
|
this.forEach((v, k) => {
|
||||||
|
@ -116,9 +122,9 @@ export class Set<T extends object = DefaultPointer> extends FlexSet<Value<T>> {
|
||||||
|
|
||||||
[PreserveOn](encoder: Encoder<T>) {
|
[PreserveOn](encoder: Encoder<T>) {
|
||||||
if (encoder.canonical) {
|
if (encoder.canonical) {
|
||||||
const pieces = Array.from(this).map(k => canonicalEncode(k));
|
const pieces = Array.from(this).map<[Bytes, Value<T>]>(k => [canonicalEncode(k), k]);
|
||||||
pieces.sort(Bytes.compare);
|
pieces.sort((a, b) => Bytes.compare(a[0], b[0]));
|
||||||
encoder.encoderawvalues(Tag.Set, pieces);
|
encoder.encodevalues(Tag.Set, pieces.map(e => e[1]));
|
||||||
} else {
|
} else {
|
||||||
encoder.encodevalues(Tag.Set, this);
|
encoder.encodevalues(Tag.Set, this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Tag } from "./constants";
|
import { Tag } from "./constants";
|
||||||
import { Bytes, BytesLike, underlying } from "./bytes";
|
import { Bytes } from "./bytes";
|
||||||
import { Value } from "./values";
|
import { Value } from "./values";
|
||||||
import { PreserveOn } from "./symbols";
|
import { PreserveOn } from "./symbols";
|
||||||
import { EncodeError } from "./codec";
|
import { EncodeError } from "./codec";
|
||||||
|
@ -137,12 +137,6 @@ export class Encoder<T extends object> {
|
||||||
this.emitbyte(Tag.End);
|
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<T>) {
|
push(v: Encodable<T>) {
|
||||||
if (isPreservable<never>(v)) {
|
if (isPreservable<never>(v)) {
|
||||||
v[PreserveOn](this as unknown as Encoder<never>);
|
v[PreserveOn](this as unknown as Encoder<never>);
|
||||||
|
|
Loading…
Reference in New Issue