{-# OPTIONS_HADDOCK prune #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE BinaryLiterals #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ViewPatterns #-}

-- |
-- Module: Data.ByteString.Base32
-- Copyright: (c) 2024 Jared Tobin
-- License: MIT
-- Maintainer: Jared Tobin <jared@ppad.tech>
--
-- Unpadded base32 encoding & decoding using the bech32 character set.

-- this module is an adaptation of emilypi's 'base32' library

module Data.ByteString.Base32 (
    -- * base32 encoding and decoding
    encode
  , decode
  ) where

import Control.Monad (guard)
import Data.Bits ((.|.), (.&.))
import qualified Data.Bits as B
import qualified Data.ByteString as BS
import qualified Data.ByteString.Builder as BSB
import qualified Data.ByteString.Builder.Extra as BE
import qualified Data.ByteString.Internal as BI
import qualified Data.ByteString.Unsafe as BU
import Data.Word (Word8, Word32, Word64)

fi :: (Integral a, Num b) => a -> b
fi :: forall a b. (Integral a, Num b) => a -> b
fi = a -> b
forall a b. (Integral a, Num b) => a -> b
fromIntegral
{-# INLINE fi #-}

word32be :: BS.ByteString -> Word32
word32be :: ByteString -> Word32
word32be ByteString
s =
  (Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fi (ByteString
s ByteString -> Int -> Word8
`BU.unsafeIndex` Int
0) Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
24) Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|.
  (Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fi (ByteString
s ByteString -> Int -> Word8
`BU.unsafeIndex` Int
1) Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
16) Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|.
  (Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fi (ByteString
s ByteString -> Int -> Word8
`BU.unsafeIndex` Int
2) Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`B.shiftL`  Int
8) Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|.
  (Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fi (ByteString
s ByteString -> Int -> Word8
`BU.unsafeIndex` Int
3))
{-# INLINE word32be #-}

-- realization for small builders
toStrict :: BSB.Builder -> BS.ByteString
toStrict :: Builder -> ByteString
toStrict = ByteString -> ByteString
BS.toStrict
  (ByteString -> ByteString)
-> (Builder -> ByteString) -> Builder -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AllocationStrategy -> ByteString -> Builder -> ByteString
BE.toLazyByteStringWith (Int -> Int -> AllocationStrategy
BE.safeStrategy Int
128 Int
BE.smallChunkSize) ByteString
forall a. Monoid a => a
mempty
{-# INLINE toStrict #-}

bech32_charset :: BS.ByteString
bech32_charset :: ByteString
bech32_charset = ByteString
"qpzry9x8gf2tvdw0s3jn54khce6mua7l"

word5 :: Word8 -> Maybe Word8
word5 :: Word8 -> Maybe Word8
word5 = \case
  Word8
113 -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
0
  Word8
112 -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
1
  Word8
122 -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
2
  Word8
114 -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
3
  Word8
121 -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
4
  Word8
57  -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
5
  Word8
120 -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
6
  Word8
56  -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
7
  Word8
103 -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
8
  Word8
102 -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
9
  Word8
50  -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
10
  Word8
116 -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
11
  Word8
118 -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
12
  Word8
100 -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
13
  Word8
119 -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
14
  Word8
48  -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
15
  Word8
115 -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
16
  Word8
51  -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
17
  Word8
106 -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
18
  Word8
110 -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
19
  Word8
53  -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
20
  Word8
52  -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
21
  Word8
107 -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
22
  Word8
104 -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
23
  Word8
99  -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
24
  Word8
101 -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
25
  Word8
54  -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
26
  Word8
109 -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
27
  Word8
117 -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
28
  Word8
97  -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
29
  Word8
55  -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
30
  Word8
108 -> Word8 -> Maybe Word8
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Maybe Word8) -> Word8 -> Maybe Word8
forall a b. (a -> b) -> a -> b
$! Word8
31
  Word8
_   -> Maybe Word8
forall a. Maybe a
Nothing
{-# INLINE word5 #-}

arrange :: Word32 -> Word8 -> BSB.Builder
arrange :: Word32 -> Word8 -> Builder
arrange Word32
w32 Word8
w8 =
  let mask :: Word32
mask = Word32
0b00011111                                 -- low 5-bit mask
      bech32_char :: Word32 -> Word64
bech32_char = Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fi (Word8 -> Word64) -> (Word32 -> Word8) -> Word32 -> Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HasCallStack => ByteString -> Int -> Word8
ByteString -> Int -> Word8
BS.index ByteString
bech32_charset (Int -> Word8) -> (Word32 -> Int) -> Word32 -> Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word32 -> Int
forall a b. (Integral a, Num b) => a -> b
fi   -- word5 -> bech32

      -- split 40 bits into 8 w5's
      w5_0 :: Word32
w5_0 = Word32
mask Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. (Word32
w32 Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
27) -- highest 5 bits
      w5_1 :: Word32
w5_1 = Word32
mask Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. (Word32
w32 Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
22)
      w5_2 :: Word32
w5_2 = Word32
mask Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. (Word32
w32 Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
17)
      w5_3 :: Word32
w5_3 = Word32
mask Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. (Word32
w32 Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
12)
      w5_4 :: Word32
w5_4 = Word32
mask Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. (Word32
w32 Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
07)
      w5_5 :: Word32
w5_5 = Word32
mask Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. (Word32
w32 Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
02)
      -- combine lowest 2 bits of w32 with highest 3 bits of w8
      w5_6 :: Word32
w5_6 = Word32
mask Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. (Word32
w32 Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
03 Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fi Word8
w8 Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
05)
      -- lowest 5 bits of w8
      w5_7 :: Word32
w5_7 = Word32
mask Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.&. Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fi Word8
w8

      -- get (w8) bech32 char for each w5, pack all into little-endian w64
      !w64 :: Word64
w64 = Word32 -> Word64
bech32_char Word32
w5_0
         Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word32 -> Word64
bech32_char Word32
w5_1 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
8
         Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word32 -> Word64
bech32_char Word32
w5_2 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
16
         Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word32 -> Word64
bech32_char Word32
w5_3 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
24
         Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word32 -> Word64
bech32_char Word32
w5_4 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
32
         Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word32 -> Word64
bech32_char Word32
w5_5 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
40
         Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word32 -> Word64
bech32_char Word32
w5_6 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
48
         Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word32 -> Word64
bech32_char Word32
w5_7 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
56

  in  Word64 -> Builder
BSB.word64LE Word64
w64
{-# INLINE arrange #-}

-- | Encode a base256-encoded 'ByteString' as a base32-encoded
--   'ByteString', using the bech32 character set.
--
--   >>> encode "jtobin was here!"
--   "df6x7cnfdcs8wctnyp5x2un9yy"
encode
  :: BS.ByteString -- ^ base256-encoded bytestring
  -> BS.ByteString -- ^ base32-encoded bytestring
encode :: ByteString -> ByteString
encode ByteString
dat = Builder -> ByteString
toStrict (ByteString -> Builder
go ByteString
dat) where
  bech32_char :: Word8 -> Word8
bech32_char = Word8 -> Word8
forall a b. (Integral a, Num b) => a -> b
fi (Word8 -> Word8) -> (Word8 -> Word8) -> Word8 -> Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HasCallStack => ByteString -> Int -> Word8
ByteString -> Int -> Word8
BS.index ByteString
bech32_charset (Int -> Word8) -> (Word8 -> Int) -> Word8 -> Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fi

  go :: ByteString -> Builder
go bs :: ByteString
bs@(BI.PS ForeignPtr Word8
_ Int
_ Int
l)
    | Int
l Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
5 = case Int -> ByteString -> (ByteString, ByteString)
BS.splitAt Int
5 ByteString
bs of
        (ByteString
chunk, ByteString
etc) -> case ByteString -> Maybe (ByteString, Word8)
BS.unsnoc ByteString
chunk of
          Maybe (ByteString, Word8)
Nothing -> [Char] -> Builder
forall a. HasCallStack => [Char] -> a
error [Char]
"impossible, chunk length is 5"
          Just (ByteString -> Word32
word32be -> Word32
w32, Word8
w8) -> Word32 -> Word8 -> Builder
arrange Word32
w32 Word8
w8 Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> ByteString -> Builder
go ByteString
etc
    | Int
l Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = Builder
forall a. Monoid a => a
mempty
    | Int
l Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 =
        let a :: Word8
a = ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
0
            t :: Word8
t = Word8 -> Word8
bech32_char ((Word8
a Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b11111000) Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
3)
            u :: Word8
u = Word8 -> Word8
bech32_char ((Word8
a Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b00000111) Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
2)

            !w16 :: Word16
w16 = Word8 -> Word16
forall a b. (Integral a, Num b) => a -> b
fi Word8
t
               Word16 -> Word16 -> Word16
forall a. Bits a => a -> a -> a
.|. Word8 -> Word16
forall a b. (Integral a, Num b) => a -> b
fi Word8
u Word16 -> Int -> Word16
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
8

        in  Word16 -> Builder
BSB.word16LE Word16
w16
    | Int
l Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
2 =
        let a :: Word8
a = ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
0
            b :: Word8
b = ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
1
            t :: Word8
t = Word8 -> Word8
bech32_char ((Word8
a Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b11111000) Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
3)
            u :: Word8
u = Word8 -> Word8
bech32_char (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$
                      ((Word8
a Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b00000111) Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
2)
                  Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. ((Word8
b Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b11000000) Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
6)
            v :: Word8
v = Word8 -> Word8
bech32_char ((Word8
b Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b00111110) Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
1)
            w :: Word8
w = Word8 -> Word8
bech32_char ((Word8
b Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b00000001) Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
4)

            !w32 :: Word32
w32 = Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fi Word8
t
               Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fi Word8
u Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
8
               Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fi Word8
v Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
16
               Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fi Word8
w Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
24

        in  Word32 -> Builder
BSB.word32LE Word32
w32
    | Int
l Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
3 =
        let a :: Word8
a = ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
0
            b :: Word8
b = ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
1
            c :: Word8
c = ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
2
            t :: Word8
t = Word8 -> Word8
bech32_char ((Word8
a Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b11111000) Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
3)
            u :: Word8
u = Word8 -> Word8
bech32_char (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$
                      ((Word8
a Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b00000111) Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
2)
                  Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. ((Word8
b Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b11000000) Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
6)
            v :: Word8
v = Word8 -> Word8
bech32_char ((Word8
b Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b00111110) Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
1)
            w :: Word8
w = Word8 -> Word8
bech32_char (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$
                      ((Word8
b Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b00000001) Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
4)
                  Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. ((Word8
c Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b11110000) Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
4)
            x :: Word8
x = Word8 -> Word8
bech32_char ((Word8
c Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b00001111) Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
1)

            !w32 :: Word32
w32 = Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fi Word8
t
               Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fi Word8
u Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
8
               Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fi Word8
v Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
16
               Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fi Word8
w Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
24

        in  Word32 -> Builder
BSB.word32LE Word32
w32 Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Word8 -> Builder
BSB.word8 Word8
x
    | Int
l Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
4 =
        let a :: Word8
a = ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
0
            b :: Word8
b = ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
1
            c :: Word8
c = ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
2
            d :: Word8
d = ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
3
            t :: Word8
t = Word8 -> Word8
bech32_char ((Word8
a Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b11111000) Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
3)
            u :: Word8
u = Word8 -> Word8
bech32_char (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$
                      ((Word8
a Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b00000111) Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
2)
                  Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. ((Word8
b Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b11000000) Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
6)
            v :: Word8
v = Word8 -> Word8
bech32_char ((Word8
b Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b00111110) Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
1)
            w :: Word8
w = Word8 -> Word8
bech32_char (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$
                      ((Word8
b Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b00000001) Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
4)
                  Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. ((Word8
c Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b11110000) Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
4)
            x :: Word8
x = Word8 -> Word8
bech32_char (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$
                      ((Word8
c Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b00001111) Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
1)
                  Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. ((Word8
d Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b10000000) Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
7)
            y :: Word8
y = Word8 -> Word8
bech32_char ((Word8
d Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b01111100) Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
2)
            z :: Word8
z = Word8 -> Word8
bech32_char ((Word8
d Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b00000011) Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
3)

            !w32 :: Word32
w32 = Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fi Word8
t
               Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fi Word8
u Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
8
               Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fi Word8
v Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
16
               Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fi Word8
w Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
24

            !w16 :: Word16
w16 = Word8 -> Word16
forall a b. (Integral a, Num b) => a -> b
fi Word8
x
               Word16 -> Word16 -> Word16
forall a. Bits a => a -> a -> a
.|. Word8 -> Word16
forall a b. (Integral a, Num b) => a -> b
fi Word8
y Word16 -> Int -> Word16
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
8

        in  Word32 -> Builder
BSB.word32LE Word32
w32 Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Word16 -> Builder
BSB.word16LE Word16
w16 Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Word8 -> Builder
BSB.word8 Word8
z

    | Bool
otherwise =
        [Char] -> Builder
forall a. HasCallStack => [Char] -> a
error [Char]
"impossible"

-- | Decode a 'ByteString', encoded as base32 using the bech32 character
--   set, to a base256-encoded 'ByteString'.
--
--   >>> decode "df6x7cnfdcs8wctnyp5x2un9yy"
--   Just "jtobin was here!"
--   >>> decode "dfOx7cnfdcs8wctnyp5x2un9yy" -- s/6/O (non-bech32 character)
--   Nothing
decode
  :: BS.ByteString        -- ^ base32-encoded bytestring
  -> Maybe BS.ByteString  -- ^ base256-encoded bytestring
decode :: ByteString -> Maybe ByteString
decode = (Builder -> ByteString) -> Maybe Builder -> Maybe ByteString
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Builder -> ByteString
toStrict (Maybe Builder -> Maybe ByteString)
-> (ByteString -> Maybe Builder) -> ByteString -> Maybe ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> ByteString -> Maybe Builder
go Builder
forall a. Monoid a => a
mempty where
  go :: Builder -> ByteString -> Maybe Builder
go Builder
acc bs :: ByteString
bs@(BI.PS ForeignPtr Word8
_ Int
_ Int
l)
    | Int
l Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
8 = do
        Builder
fin <- ByteString -> Maybe Builder
finalize ByteString
bs
        Builder -> Maybe Builder
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Builder
acc Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
fin)
    | Bool
otherwise = case Int -> ByteString -> (ByteString, ByteString)
BS.splitAt Int
8 ByteString
bs of
        (ByteString
chunk, ByteString
etc) -> do
           Builder
res <- ByteString -> Maybe Builder
decode_chunk ByteString
chunk
           Builder -> ByteString -> Maybe Builder
go (Builder
acc Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
res) ByteString
etc

finalize :: BS.ByteString -> Maybe BSB.Builder
finalize :: ByteString -> Maybe Builder
finalize bs :: ByteString
bs@(BI.PS ForeignPtr Word8
_ Int
_ Int
l)
  | Int
l Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = Builder -> Maybe Builder
forall a. a -> Maybe a
Just Builder
forall a. Monoid a => a
mempty
  | Bool
otherwise = do
      Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Int
l Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
2)
      Word8
w5_0 <- Word8 -> Maybe Word8
word5 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
0)
      Word8
w5_1 <- Word8 -> Maybe Word8
word5 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
1)
      let w8_0 :: Word8
w8_0 = Word8
w5_0 Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
3
             Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. Word8
w5_1 Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
2

      -- https://datatracker.ietf.org/doc/html/rfc4648#section-6
      if | Int
l Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
2 -> do -- 2 w5's, need 1 w8; 2 bits remain
             Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Word8
w5_1 Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
6 Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0)
             Builder -> Maybe Builder
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Builder
BSB.word8 Word8
w8_0)

         | Int
l Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
4 -> do -- 4 w5's, need 2 w8's; 4 bits remain
             Word8
w5_2 <- Word8 -> Maybe Word8
word5 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
2)
             Word8
w5_3 <- Word8 -> Maybe Word8
word5 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
3)
             let w8_1 :: Word8
w8_1 = Word8
w5_1 Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
6
                    Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. Word8
w5_2 Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
1
                    Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. Word8
w5_3 Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
4

                 !w16 :: Word16
w16 = Word8 -> Word16
forall a b. (Integral a, Num b) => a -> b
fi Word8
w8_1
                    Word16 -> Word16 -> Word16
forall a. Bits a => a -> a -> a
.|. Word8 -> Word16
forall a b. (Integral a, Num b) => a -> b
fi Word8
w8_0 Word16 -> Int -> Word16
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
8

             Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Word8
w5_3 Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
4 Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0)
             Builder -> Maybe Builder
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word16 -> Builder
BSB.word16BE Word16
w16)

         | Int
l Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
5 -> do -- 5 w5's, need 3 w8's; 1 bit remains
             Word8
w5_2 <- Word8 -> Maybe Word8
word5 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
2)
             Word8
w5_3 <- Word8 -> Maybe Word8
word5 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
3)
             Word8
w5_4 <- Word8 -> Maybe Word8
word5 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
4)
             let w8_1 :: Word8
w8_1 = Word8
w5_1 Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
6
                    Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. Word8
w5_2 Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
1
                    Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. Word8
w5_3 Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
4
                 w8_2 :: Word8
w8_2 = Word8
w5_3 Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
4
                    Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. Word8
w5_4 Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
1

                 w16 :: Word16
w16  = Word8 -> Word16
forall a b. (Integral a, Num b) => a -> b
fi Word8
w8_1
                    Word16 -> Word16 -> Word16
forall a. Bits a => a -> a -> a
.|. Word8 -> Word16
forall a b. (Integral a, Num b) => a -> b
fi Word8
w8_0 Word16 -> Int -> Word16
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
8

             Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Word8
w5_4 Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
7 Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0)
             Builder -> Maybe Builder
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word16 -> Builder
BSB.word16BE Word16
w16 Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Word8 -> Builder
BSB.word8 Word8
w8_2)

         | Int
l Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
7 -> do -- 7 w5's, need 4 w8's; 3 bits remain
             Word8
w5_2 <- Word8 -> Maybe Word8
word5 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
2)
             Word8
w5_3 <- Word8 -> Maybe Word8
word5 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
3)
             Word8
w5_4 <- Word8 -> Maybe Word8
word5 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
4)
             Word8
w5_5 <- Word8 -> Maybe Word8
word5 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
5)
             Word8
w5_6 <- Word8 -> Maybe Word8
word5 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
6)
             let w8_1 :: Word8
w8_1 = Word8
w5_1 Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
6
                    Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. Word8
w5_2 Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
1
                    Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. Word8
w5_3 Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
4
                 w8_2 :: Word8
w8_2 = Word8
w5_3 Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
4
                    Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. Word8
w5_4 Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
1
                 w8_3 :: Word8
w8_3 = Word8
w5_4 Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
7
                    Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. Word8
w5_5 Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
2
                    Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. Word8
w5_6 Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
3

                 w32 :: Word32
w32  = Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fi Word8
w8_3
                    Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fi Word8
w8_2 Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
8
                    Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fi Word8
w8_1 Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
16
                    Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. Word8 -> Word32
forall a b. (Integral a, Num b) => a -> b
fi Word8
w8_0 Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
24

             Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Word8
w5_6 Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
5 Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0)
             Builder -> Maybe Builder
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word32 -> Builder
BSB.word32BE Word32
w32)

         | Bool
otherwise -> Maybe Builder
forall a. Maybe a
Nothing

-- assumes length 8 input
decode_chunk :: BS.ByteString -> Maybe BSB.Builder
decode_chunk :: ByteString -> Maybe Builder
decode_chunk ByteString
bs = do
  Word8
w5_0 <- Word8 -> Maybe Word8
word5 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
0)
  Word8
w5_1 <- Word8 -> Maybe Word8
word5 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
1)
  Word8
w5_2 <- Word8 -> Maybe Word8
word5 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
2)
  Word8
w5_3 <- Word8 -> Maybe Word8
word5 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
3)
  Word8
w5_4 <- Word8 -> Maybe Word8
word5 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
4)
  Word8
w5_5 <- Word8 -> Maybe Word8
word5 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
5)
  Word8
w5_6 <- Word8 -> Maybe Word8
word5 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
6)
  Word8
w5_7 <- Word8 -> Maybe Word8
word5 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
7)

  let w40 :: Word64
      !w40 :: Word64
w40 = Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fi Word8
w5_0 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
35
         Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fi Word8
w5_1 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
30
         Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fi Word8
w5_2 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
25
         Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fi Word8
w5_3 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
20
         Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fi Word8
w5_4 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
15
         Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fi Word8
w5_5 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
10
         Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fi Word8
w5_6 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
05
         Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fi Word8
w5_7
      !w32 :: Word32
w32 = Word64 -> Word32
forall a b. (Integral a, Num b) => a -> b
fi (Word64
w40 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
8)   :: Word32
      !w8 :: Word8
w8  = Word64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fi (Word64
0b11111111 Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.&. Word64
w40) :: Word8

  Builder -> Maybe Builder
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Builder -> Maybe Builder) -> Builder -> Maybe Builder
forall a b. (a -> b) -> a -> b
$ Word32 -> Builder
BSB.word32BE Word32
w32 Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Word8 -> Builder
BSB.word8 Word8
w8