Skip to main content

Module canonical

Module canonical 

Source
Expand description

The one form two implementations’ values can be compared in.

A pairwise run compares what came out of B against what went into A. Both sides are written in the same representation, and a representation usually has more than one way to write the same value: in JSON, 2.0 and 2.0e0, {"a":1,"b":2} and {"b":2,"a":1}, 12345678901234567890 as a number and as a string. Comparing the two texts would report a difference in formatting as a difference in wire behaviour.

§Why the normalisation is type-directed

A normaliser that only knew JSON could sort keys and reprint numbers, and would still be wrong twice:

  • A float member carries a value the JSON was written with in full double precision — 0.1 in the file, 0.10000000149011612 coming back out of thirty-two bits. Neither side is wrong and the texts differ. Only the type says which of the two is the value.
  • A long long is a string, because a JSON number is a double and loses the low bits past 2^53. A type-blind normaliser cannot tell a 64-bit integer that must stay a string from a long that must not become one.

So canonicalise walks the type beside the value, the same walk encode and decode make, and rebuilds the value in the one form the table in crate documents. Running it over the case’s own value file and over a probe’s output puts both in that form before anything is compared.

§What it also does

It validates. A key that names no member, a missing member that is not @optional, an explicit null — all are errors here, with the path, for the same reason they are errors in encode.

Structs§

Difference
One place two values disagree.

Functions§

canonicalise
Put one value into canonical form against its type.
difference
Where two canonical values first differ, as a path and the two forms.
text
The canonical text of a canonical value.