unisonweb / base

Unison base libraries
https://share.unison-lang.org/@unison/base
18 stars 6 forks source link

Add base 32 hex coding for `Bytes`, with some random additions for testing. #92

Closed dolio closed 2 years ago

dolio commented 2 years ago

This PR adds functions for encoding bytes using base 32 hex encoding. This encoding extends the usual hexadecimal digits rather than starting at A. Both encoding and decoding are written in unison, with an encoding function to both Text and Bytes, and a decoding function from Bytes.

When writing tests, using Gen didn't seem to give very good coverage of byte/hex strings, so I cloned some helpful Gen functions as the better performing Random ability. On top of that, I built a random generator for base 32 hex byte strings that represent byte-aligned source values. That is used to test that the round-trip through encoding and decoding gives back the original result.

I believe I've documented everything, too. Let me know if any changes are necessary.

Code review

The changes summarized below are available for you to review, using the following command:

pull-request.load https://github.com/unisonweb/base:v3:.trunk https://github.com/dolio/unison-codebase:.base.hex32

Added definitions:

 structural type Bytes.base32Hex.Hex32Piece (+2 metadata)
 Bytes.base32Hex.Hex32Piece.Double    : Nat
                                      -> Nat
                                      -> Nat
                                      -> Bytes
                                      -> Hex32Piece
 Bytes.base32Hex.Hex32Piece.Single    : Nat -> Nat -> Bytes -> Hex32Piece
 Bytes.fromBase32Hex.alignment        : Nat -> Nat (+2 metadata)

The changes summarized below are available for you to review, using the following command:

pull-request.load https://github.com/unisonweb/base:v3:.trunk https://gith

ub.com/dolio/unison-codebase:.base.hex32 Added definitions:

 structural type Bytes.base32Hex.Hex32Piece (+2 metadata)
 Bytes.base32Hex.Hex32Piece.Double    : Nat
                                      -> Nat
                                      -> Nat
                                      -> Bytes
                                      -> Hex32Piece
 Bytes.base32Hex.Hex32Piece.Single    : Nat -> Nat -> Bytes -> Hex32Piece
 Bytes.base32Hex.b32h                 : Nat -> Char (+2 metadata)
 Bytes.base32Hex                      : Bytes -> Text (+2 metadata)
 abilities.Random.bytes.base32Hex     : '{Random} Bytes (+2 metadata)
 abilities.Random.char.base32Hex      : '{Random} Char (+2 metadata)
 abilities.Random.text.base32Hex      : '{Random} Text (+2 metadata)
 abilities.Random.char.digit          : '{Random} Char (+2 metadata)
 Bytes.fromBase32Hex.alignment.doc    : Doc (+2 metadata)
 Bytes.base32Hex.b32h.doc             : Doc (+2 metadata)
 Bytes.base32Hex.doc                  : Doc (+2 metadata)
 abilities.Random.bytes.base32Hex.doc : Doc (+2 metadata)
 abilities.Random.char.base32Hex.doc  : Doc (+2 metadata)
 abilities.Random.text.base32Hex.doc  : Doc (+2 metadata)
 abilities.Random.char.digit.doc      : Doc (+2 metadata)
 abilities.Random.either.doc          : Doc (+2 metadata)
 Bytes.base32Hex.encodeChunk.doc      : Doc (+2 metadata)
 Bytes.fromBase32Hex.finalize.doc     : Doc (+2 metadata)
 Bytes.fromBase32Hex.doc              : Doc (+2 metadata)
 Bytes.base32Hex.grab.doc             : Doc (+2 metadata)
 Bytes.base32Hex.grab1.doc            : Doc (+2 metadata)
 Bytes.fromBase32Hex.h32b.doc         : Doc (+2 metadata)
 abilities.Random.char.hex.doc        : Doc (+2 metadata)
 abilities.Random.char.interval.doc   : Doc (+2 metadata)
 abilities.Random.oneOf.doc           : Doc (+2 metadata)
 Bytes.fromBase32Hex.push.doc         : Doc (+2 metadata)
 Bytes.toBase32Hex.doc                : Doc (+2 metadata)
 abilities.Random.either              : '{Random} r
                                      -> '{Random} r
                                      ->{Random} r (+2 metadata)
 Bytes.base32Hex.encodeChunk          : Nat -> Nat -> Text (+2 metadata)
 Bytes.fromBase32Hex.finalize         : Nat -> Nat -> Bytes (+2 metadata)
 Bytes.fromBase32Hex                  : Bytes
                                      -> Either Text Bytes (+2 metadata)
 Bytes.base32Hex.grab                 : Bytes
                                      -> Optional Hex32Piece (+2 metadata)
 Bytes.base32Hex.grab1                : Bytes
                                      -> Optional Hex32Piece (+2 metadata)
 Bytes.fromBase32Hex.h32b             : Nat
 Bytes.fromBase32Hex.h32b             : Nat
                                      -> Either Text Nat (+2 metadata)
 abilities.Random.char.hex            : '{Random} Char (+2 metadata)
 abilities.Random.char.interval       : Char
                                      -> Char
                                      ->{Random} Char (+2 metadata)
 Bytes.fromBase32Hex.tests.inverse    : [Result] (+3 metadata)
 Bytes.toBase32Hex.tests.inverse      : [Result] (+3 metadata)
 abilities.Random.oneOf               : [a] ->{Random} a (+2 metadata)
 Bytes.fromBase32Hex.push             : Nat
                                      -> Nat
                                      -> Nat
                                      -> Either Nat (Bytes, Nat) (+2 metadata)
 Bytes.toBase32Hex                    : Bytes -> Bytes (+2 metadata)
dolio commented 2 years ago

Just swapped out uses of toBase32 with base32Hex in the scheme stuff, and now I get output for references that I can successfully look up with find in ucm. So that seems like a good indication that it's actually working as expected.

runarorama commented 2 years ago

Merged into base v4 branch. 🌈 ⭐