@@ -457,6 +457,7 @@ when = \cond action -> if cond then action else yield {}
457min = \a b -> if a < b then a else b
457min = \a b -> if a < b then a else b
458max = \a b -> if a > b then a else b
458max = \a b -> if a > b then a else b
459clamp = \lo hi x -> max lo (min hi x)
459clamp = \lo hi x -> max lo (min hi x)
460+mod = \n m -> n - n / m * m
461-- Dedup: keeps first occurrence (O(n^2)).
462-- Dedup: keeps first occurrence (O(n^2)).
462unique = \items -> fold (\acc x -> if elem acc x then acc else union acc [x]) [] items
463unique = \items -> fold (\acc x -> if elem acc x then acc else union acc [x]) [] items
@@ -544,9 +545,9 @@ mapEach = \items getKey action -> case headOf items of
544 rest <- mapEach (filter items (\y -> getKey y != getKey x)) getKey action
545 rest <- mapEach (filter items (\y -> getKey y != getKey x)) getKey action
545 yield (union [r] rest)
546 yield (union [r] rest)
547−-- Hex tokens (modulo lives inside hexDigit, so callers just pass raw bits).
548+-- Hex tokens (callers just pass raw bits).
548hexDigit : Int -> Text
549hexDigit : Int -> Text
549−hexDigit = \n -> take 1 (drop (n - n / 16 * 16) "0123456789abcdef")
550+hexDigit = \n -> take 1 (drop (mod n 16) "0123456789abcdef")
551byteToHex : Int -> Text
552byteToHex : Int -> Text
552byteToHex = \n -> hexDigit (n / 16) ++ hexDigit n
553byteToHex = \n -> hexDigit (n / 16) ++ hexDigit n
@@ -562,12 +563,12 @@ genTokenN = \n -> if n <= 0 then yield "" else do
562genToken = genTokenN 8
563genToken = genTokenN 8
564tooLong : Text -> Int -> Bool
565tooLong : Text -> Int -> Bool
565−tooLong = \s maxLen -> drop maxLen s != ""
566+tooLong = \s maxLen -> count (chars s) > maxLen
567isValidHex : Text -> Bool
568isValidHex : Text -> Bool
568isValidHex = \s ->
569isValidHex = \s ->
569− let n = count (chars s) in
570+ let cs = chars s in
570− n > 0 && n / 2 * 2 == n && all (chars s) (\c -> contains c "0123456789abcdef")
571+ count cs > 0 && mod (count cs) 2 == 0 && all cs (\c -> contains c "0123456789abcdef")
572normalizeHex : Text -> Text
573normalizeHex : Text -> Text
573normalizeHex = \s -> bytesToHex (bytesFromHex s)
574normalizeHex = \s -> bytesToHex (bytesFromHex s)