~/bend-docscommunity

lib.bend source

lib.bend on the hub · documented module

# Hex — strict hexadecimal codec for Base List<&2, U32> and String.# Base-only, no termination escapes. Encoding is lowercase and octet-oriented.import Base# Digits 0..15 are emitted as lowercase 0-9a-f.def Hex.digit(+n: U32) -> Char:  Bool.pick(Char, U32.is_lt(n, 10),    Chr{U32.add(48, n)}, Chr{U32.add(87, n)})# Encode one octet. As with Bytes.hex, only the low eight bits participate.def Hex.encode.byte(+b: U32) -> String:  +octet = U32.and(b, 255)  +hi = U32.div(octet, 16)  +lo = U32.mod(octet, 16)  SCon{Hex.digit(hi), SCon{Hex.digit(lo), SNil{}}}def Hex.encode.go(xs: List<&2, U32>) -> String:  match xs:    case Nil{}:      SNil{}    case h <> t:      String.append(Hex.encode.byte(h), Hex.encode.go(t))def Hex.encode(xs: List<&2, U32>) -> String:  Hex.encode.go(xs)# Convert one accepted hexadecimal character to its nibble value.# Both cases are accepted; no whitespace or prefixes are accepted.def Hex.value(+c: Char) -> Maybe<&2, U32>:  +x = Char.to_u32(c)  Bool.pick(Maybe<&2, U32>,    Bool.and(U32.is_ge(x, 48), U32.is_le(x, 57)),    Some{U32.sub(x, 48)},    Bool.pick(Maybe<&2, U32>,      Bool.and(U32.is_ge(x, 65), U32.is_le(x, 70)),      Some{U32.add(10, U32.sub(x, 65))},      Bool.pick(Maybe<&2, U32>,        Bool.and(U32.is_ge(x, 97), U32.is_le(x, 102)),        Some{U32.add(10, U32.sub(x, 97))},        None{})))# Prepend one decoded octet to a successful tail; preserve failure.def Hex.decode.prefix(  +hi: U32, +lo: U32, r: Maybe<&2, List<&2, U32>>) -> Maybe<&2, List<&2, U32>>:  match r:    case None{}:      None{}    case Some{rest}:      Some{U32.add(U32.shln(hi, 4n), lo) <> rest}# Decode exactly two hex characters. The recursive decoder supplies r, so any# malformed suffix makes the whole result None.def Hex.decode.pair(  r: Maybe<&2, List<&2, U32>>,  ma: Maybe<&2, U32>, mb: Maybe<&2, U32>) -> Maybe<&2, List<&2, U32>>:  match ma mb:    case Some{+hi} Some{+lo}:      Hex.decode.prefix(hi, lo, r)    case _ _:      None{}# Strict decoding: input must have even length and every character must be# 0-9, a-f, or A-F. Empty input decodes to Some{Nil{}}.def Hex.decode.go(s: String) -> Maybe<&2, List<&2, U32>>:  match s:    case SNil{}:      Some{Nil{}}    case SCon{+a, SCon{+b, tail}}:      +ma = Hex.value(a)      +mb = Hex.value(b)      Hex.decode.pair(Hex.decode.go(tail), ma, mb)    case _:      None{}def Hex.decode(s: String) -> Maybe<&2, List<&2, U32>>:  Hex.decode.go(s)