-- | Produce a 'Hash' from a base32hex-encoded version of its binary representation
fromBase32Hex :: Text -> Maybe Hash
fromBase32Hex txt = case Base32Hex.decode (encodeUtf8 $ Text.toUpper txt <> paddingChars) of
  Left (_, _rem) -> Nothing
  Right h -> pure $ Hash h
  where
  -- The decoder we're using is a base32 uppercase decoder that expects padding,
  -- so we provide it with the appropriate number of padding characters for the
  -- expected hash length.
  --
  -- The decoder requires 40 bit (8 5-bit characters) chunks, so if the number
  -- of characters of the input is not a multiple of 8, we add '=' padding chars
  -- until it is.
  --
  -- See https://tools.ietf.org/html/rfc4648#page-8
  paddingChars :: Text
  paddingChars = case Text.length txt `mod` 8 of
    0 -> ""
    n -> Text.replicate (8 - n) "="

  hashLength :: Int
  hashLength = 512

  _paddingChars :: Text
  _paddingChars = case hashLength `mod` 40 of
    0  -> ""
    8  -> "======"
    16 -> "===="
    24 -> "==="
    32 -> "="
    i  -> error $ "impossible hash length `mod` 40 not in {0,8,16,24,32}: " <> show i
fromBase32Hex :: Text -> Maybe Hash
fromBase32Hex txt = case Base32Hex.decode (encodeUtf8 $ Text.toUpper txt <> paddingChars) of
  Left (_, _rem) -> Nothing
  Right h -> pure $ Hash h
  where
  -- The decoder we're using is a base32 uppercase decoder that expects padding,
  -- so we provide it with the appropriate number of padding characters for the
  -- expected hash length.
  --
  -- The decoder requires 40 bit (8 5-bit characters) chunks, so if the number
  -- of characters of the input is not a multiple of 8, we add '=' padding chars
  -- until it is.
  --
  -- See https://tools.ietf.org/html/rfc4648#page-8
  paddingChars :: Text
  paddingChars = case Text.length txt `mod` 8 of
    0 -> ""
    n -> Text.replicate (8 - n) "="

  hashLength :: Int
  hashLength = 512

  _paddingChars :: Text
  _paddingChars = case hashLength `mod` 40 of
    0  -> ""
    8  -> "======"
    16 -> "===="
    24 -> "==="
    32 -> "="
    i  -> error $ "impossible hash length `mod` 40 not in {0,8,16,24,32}: " <> show i
fromBase32Hex txt = case Base32Hex.decode (encodeUtf8 $ Text.toUpper txt <> paddingChars) of
  Left (_, _rem) -> Nothing
  Right h -> pure $ Hash h
  where
  -- The decoder we're using is a base32 uppercase decoder that expects padding,
  -- so we provide it with the appropriate number of padding characters for the
  -- expected hash length.
  --
  -- The decoder requires 40 bit (8 5-bit characters) chunks, so if the number
  -- of characters of the input is not a multiple of 8, we add '=' padding chars
  -- until it is.
  --
  -- See https://tools.ietf.org/html/rfc4648#page-8
  paddingChars :: Text
  paddingChars = case Text.length txt `mod` 8 of
    0 -> ""
    n -> Text.replicate (8 - n) "="

  hashLength :: Int
  hashLength = 512

  _paddingChars :: Text
  _paddingChars = case hashLength `mod` 40 of
    0  -> ""
    8  -> "======"
    16 -> "===="
    24 -> "==="
    32 -> "="
    i  -> error $ "impossible hash length `mod` 40 not in {0,8,16,24,32}: " <> show i