src/crypto/blake/blake2b/hex.bend
0x9ee2e9a299991dcc089fe22c7f3ceb5f · 34 lines · 0 definitions
1# Lowercase hex of a 64-byte BLAKE2b digest (sixteen little-endian words).
2import Base
3
4def hex_digit_if(x: U32, small: Bool) -> Char:
5 match small:
6 case True{}:
7 Chr{(48 + x : U32)}
8 case False{}:
9 Chr{(87 + x : U32)}
10
11def hex_digit(+x: U32) -> Char:
12 hex_digit_if(x, U32.is_lt(x, 10))
13
14def hex_word_go(n: Nat, +x: U32, acc: String) -> String:
15 match n:
16 case 0n:
17 acc
18 case 1n+p:
19 hex_word_go(p, U32.shrn(x, 4n), SCon{hex_digit((x .&. 15 : U32)), acc})
20
21def hex_byte(+x: U32) -> String:
22 SCon{hex_digit(U32.shrn(x,4n)),SCon{hex_digit(U32.and(x,15)),SNil{}}}
23
24def hex_word(+x: U32) -> String:
25 hex_byte(U32.and(x,255)) ++ hex_byte(U32.and(U32.shrn(x,8n),255)) ++ hex_byte(U32.and(U32.shrn(x,16n),255)) ++ hex_byte(U32.shrn(x,24n))
26
27# Formatting helper walks the sixteen digest words; it does not create a digest list.
28def hex_walk(n: Nat, +index: U32, pair: Array<U32> & U32) -> String:
29 match n pair:
30 case 0n Tuple{a,w}: hex_word(w)
31 case 1n+p Tuple{a,w}: hex_word(w) ++ hex_walk(p,U32.inc(index),Array.get(U32,a,index))
32
33def hex(a: Array<U32>) -> String:
34 hex_walk(15n,1,Array.get(U32,a,0))