-- | Base 64 encoding of objects.
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE CPP                        #-}
module Raaz.Core.Encode.Base64( Base64 ) where

import Data.Char
import Data.Bits
import Data.String

import Data.ByteString as B
import Data.ByteString.Char8 as C8
import Data.ByteString.Internal (c2w, w2c)

import Data.ByteString.Unsafe(unsafeIndex)
import Data.Monoid
import Data.Word
import Raaz.Core.Encode.Internal


-- | The type corresponding to the standard padded base-64 binary
-- encoding.
newtype Base64 = Base64 {Base64 -> ByteString
unBase64 :: ByteString}
#if MIN_VERSION_base(4,11,0)
                 deriving (Base64 -> Base64 -> Bool
(Base64 -> Base64 -> Bool)
-> (Base64 -> Base64 -> Bool) -> Eq Base64
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Base64 -> Base64 -> Bool
$c/= :: Base64 -> Base64 -> Bool
== :: Base64 -> Base64 -> Bool
$c== :: Base64 -> Base64 -> Bool
Eq, b -> Base64 -> Base64
NonEmpty Base64 -> Base64
Base64 -> Base64 -> Base64
(Base64 -> Base64 -> Base64)
-> (NonEmpty Base64 -> Base64)
-> (forall b. Integral b => b -> Base64 -> Base64)
-> Semigroup Base64
forall b. Integral b => b -> Base64 -> Base64
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
stimes :: b -> Base64 -> Base64
$cstimes :: forall b. Integral b => b -> Base64 -> Base64
sconcat :: NonEmpty Base64 -> Base64
$csconcat :: NonEmpty Base64 -> Base64
<> :: Base64 -> Base64 -> Base64
$c<> :: Base64 -> Base64 -> Base64
Semigroup, Semigroup Base64
Base64
Semigroup Base64
-> Base64
-> (Base64 -> Base64 -> Base64)
-> ([Base64] -> Base64)
-> Monoid Base64
[Base64] -> Base64
Base64 -> Base64 -> Base64
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
mconcat :: [Base64] -> Base64
$cmconcat :: [Base64] -> Base64
mappend :: Base64 -> Base64 -> Base64
$cmappend :: Base64 -> Base64 -> Base64
mempty :: Base64
$cmempty :: Base64
$cp1Monoid :: Semigroup Base64
Monoid)
#else
                 deriving (Eq, Monoid)
#endif


-- Developers note: Internally base16 just stores the bytestring as
-- is. The conversion happens when we do an encode and decode of
-- actual base16.

instance Encodable Base64 where
  toByteString :: Base64 -> ByteString
toByteString          = ByteString -> ByteString
toB64 (ByteString -> ByteString)
-> (Base64 -> ByteString) -> Base64 -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Base64 -> ByteString
unBase64

  fromByteString :: ByteString -> Maybe Base64
fromByteString ByteString
bs
    | ByteString -> Bool
B.null ByteString
bs                = Base64 -> Maybe Base64
forall a. a -> Maybe a
Just (Base64 -> Maybe Base64) -> Base64 -> Maybe Base64
forall a b. (a -> b) -> a -> b
$ ByteString -> Base64
Base64 ByteString
B.empty
    | ByteString -> Int
B.length ByteString
bs Int -> Int -> Int
forall a. Integral a => a -> a -> a
`rem` Int
4 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0 = Maybe Base64
forall a. Maybe a
Nothing
    | Bool
okeyPad                  = Base64 -> Maybe Base64
forall a. a -> Maybe a
Just (Base64 -> Maybe Base64) -> Base64 -> Maybe Base64
forall a b. (a -> b) -> a -> b
$ ByteString -> Base64
Base64 (ByteString -> Base64) -> ByteString -> Base64
forall a b. (a -> b) -> a -> b
$ ByteString -> ByteString
unsafeFromB64 ByteString
bs
    | Bool
otherwise                = Maybe Base64
forall a. Maybe a
Nothing
    where padPart :: ByteString
padPart     = (Char -> Bool) -> ByteString -> ByteString
C8.dropWhile Char -> Bool
isB64Char ByteString
bs
          okeyPad :: Bool
okeyPad     = ByteString
padPart ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
C8.empty Bool -> Bool -> Bool
|| ByteString
padPart ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== Char -> ByteString
C8.singleton Char
'=' Bool -> Bool -> Bool
|| ByteString
padPart ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== String -> ByteString
C8.pack String
"=="
          isB64Char :: Char -> Bool
isB64Char Char
c = Char -> Bool
isAlpha Char
c Bool -> Bool -> Bool
|| Char -> Bool
isDigit Char
c Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'+' Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'/'


  unsafeFromByteString :: ByteString -> Base64
unsafeFromByteString ByteString
bs | ByteString -> Bool
B.null ByteString
bs = ByteString -> Base64
Base64 ByteString
B.empty
                          | Bool
otherwise = ByteString -> Base64
Base64 (ByteString -> Base64) -> ByteString -> Base64
forall a b. (a -> b) -> a -> b
$ ByteString -> ByteString
unsafeFromB64 ByteString
bs


instance Show Base64 where
  show :: Base64 -> String
show = ByteString -> String
C8.unpack (ByteString -> String)
-> (Base64 -> ByteString) -> Base64 -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Base64 -> ByteString
forall a. Encodable a => a -> ByteString
toByteString

-- | Ignores spaces and newlines.
instance IsString Base64 where
  fromString :: String -> Base64
fromString = ByteString -> Base64
forall a. Encodable a => ByteString -> a
unsafeFromByteString (ByteString -> Base64)
-> (String -> ByteString) -> String -> Base64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> ByteString -> ByteString
C8.filter (Bool -> Bool
not (Bool -> Bool) -> (Char -> Bool) -> Char -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Bool
isSpace) (ByteString -> ByteString)
-> (String -> ByteString) -> String -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ByteString
forall a. IsString a => String -> a
fromString

instance Format Base64 where
  encodeByteString :: ByteString -> Base64
encodeByteString = ByteString -> Base64
Base64
  {-# INLINE encodeByteString #-}

  decodeFormat :: Base64 -> ByteString
decodeFormat     = Base64 -> ByteString
unBase64
  {-# INLINE decodeFormat #-}



------------- Base 64 encoding -------------------------

-- NOTE: The topN functions ensure that the top N bits of a word are present
-- in the least N significant bits. The botN ensures that there

top6 :: Word8 -> Word8; bot2 :: Word8 -> Word8
top4 :: Word8 -> Word8; bot4 :: Word8 -> Word8
top2 :: Word8 -> Word8; bot6 :: Word8 -> Word8

top6 :: Word8 -> Word8
top6 Word8
w = Word8
w Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`shiftR` Int
2; bot2 :: Word8 -> Word8
bot2 Word8
w = Word8
w Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0x03
top4 :: Word8 -> Word8
top4 Word8
w = Word8
w Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`shiftR` Int
4; bot4 :: Word8 -> Word8
bot4 Word8
w = Word8
w Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0x0F
top2 :: Word8 -> Word8
top2 Word8
w = Word8
w Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`shiftR` Int
6; bot6 :: Word8 -> Word8
bot6 Word8
w = Word8
w Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0x3F

--------------- Combining bytes -----------------------------------

byte0 :: Word8 -> Word8
byte1 :: Word8 -> Word8 -> Word8
byte2 :: Word8 -> Word8 -> Word8
byte3 :: Word8 -> Word8
pad   :: Word8


byte0 :: Word8 -> Word8
byte0     = Word8 -> Word8
b64 (Word8 -> Word8) -> (Word8 -> Word8) -> Word8 -> Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Word8
top6
byte1 :: Word8 -> Word8 -> Word8
byte1 Word8
t Word8
p = Word8 -> Word8
b64 (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
shiftL (Word8 -> Word8
bot2 Word8
p) Int
4 Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. Word8 -> Word8
top4 Word8
t
byte2 :: Word8 -> Word8 -> Word8
byte2 Word8
t Word8
p = Word8 -> Word8
b64 (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
shiftL (Word8 -> Word8
bot4 Word8
p) Int
2 Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. Word8 -> Word8
top2 Word8
t
byte3 :: Word8 -> Word8
byte3     = Word8 -> Word8
b64 (Word8 -> Word8) -> (Word8 -> Word8) -> Word8 -> Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Word8
bot6
pad :: Word8
pad       = Char -> Word8
c2w Char
'='

-- | Encoding word.
b64 :: Word8 -> Word8
b64 :: Word8 -> Word8
b64 Word8
w | Word8
0  Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
w  Bool -> Bool -> Bool
&& Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
25 = Char -> Word8
c2w Char
'A' Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
w
      | Word8
26 Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
w  Bool -> Bool -> Bool
&& Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
51 = Char -> Word8
c2w Char
'a' Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
w Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Word8
26
      | Word8
52 Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
w  Bool -> Bool -> Bool
&& Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
61 = Char -> Word8
c2w Char
'0' Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
w Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Word8
52
      | Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
62             = Char -> Word8
c2w Char
'+'
      | Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
63             = Char -> Word8
c2w Char
'/'
      | Bool
otherwise           = String -> Word8
forall a. HasCallStack => String -> a
error String
"oops: b64"


unB64 :: Word8 -> Word8
unB64 :: Word8 -> Word8
unB64 Word8
w | Char -> Word8
c2w Char
'A' Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
w Bool -> Bool -> Bool
&& Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Char -> Word8
c2w Char
'Z' = Word8
w Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Char -> Word8
c2w Char
'A'
        | Char -> Word8
c2w Char
'a' Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
w Bool -> Bool -> Bool
&& Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Char -> Word8
c2w Char
'z' = Word8
w Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Char -> Word8
c2w Char
'a' Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
26
        | Char -> Word8
c2w Char
'0' Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
w Bool -> Bool -> Bool
&& Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Char -> Word8
c2w Char
'9' = Word8
w Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Char -> Word8
c2w Char
'0' Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
52
        | Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Char -> Word8
c2w Char
'+'                 = Word8
62
        | Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Char -> Word8
c2w Char
'/'                 = Word8
63
        | Bool
otherwise                    = String -> Word8
forall a. HasCallStack => String -> a
error (String -> Word8) -> String -> Word8
forall a b. (a -> b) -> a -> b
$ String
"oops unB64:" String -> ShowS
forall a. [a] -> [a] -> [a]
++ [Word8 -> Char
w2c Word8
w]




-- Since the encoding to base16 is usually used for user interaction
-- we can afford to be slower here.

-- TODO (Liquid Haskell)
--
{--@ toB64 :: ByteString -> { bs : ByteString | (bslen bs) mod 4 == 0 @-}
--
toB64 :: ByteString -> ByteString
toB64 :: ByteString -> ByteString
toB64 ByteString
bs = (ByteString, Maybe Int) -> ByteString
forall a b. (a, b) -> a
fst (Int
-> (Int -> Maybe (Word8, Int)) -> Int -> (ByteString, Maybe Int)
forall a.
Int -> (a -> Maybe (Word8, a)) -> a -> (ByteString, Maybe a)
B.unfoldrN (Int
4Int -> Int -> Int
forall a. Num a => a -> a -> a
*Int
n) Int -> Maybe (Word8, Int)
gen Int
0) ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
padding
    where gen :: Int -> Maybe (Word8, Int)
gen Int
i    = (Word8, Int) -> Maybe (Word8, Int)
forall a. a -> Maybe a
Just (Int -> Word8
byte Int
i, Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
          at :: Int -> Int -> Word8
at Int
blk Int
i = ByteString -> Int -> Word8
unsafeIndex ByteString
bs (Int -> Word8) -> Int -> Word8
forall a b. (a -> b) -> a -> b
$ Int
3 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
blk Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
i

          byte :: Int -> Word8
byte Int
i = case Int
r of
            Int
0 -> Word8 -> Word8
byte0          (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Word8
at Int
q Int
0
            Int
1 -> Word8 -> Word8 -> Word8
byte1 (Int -> Int -> Word8
at Int
q Int
1) (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Word8
at Int
q Int
0
            Int
2 -> Word8 -> Word8 -> Word8
byte2 (Int -> Int -> Word8
at Int
q Int
2) (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Word8
at Int
q Int
1
            Int
3 -> Word8 -> Word8
byte3          (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Word8
at Int
q Int
2
            Int
_ -> String -> Word8
forall a. HasCallStack => String -> a
error String
"base64 bad index"
            where (Int
q, Int
r) = Int -> Int -> (Int, Int)
forall a. Integral a => a -> a -> (a, a)
quotRem Int
i Int
4

          (Int
n,Int
p) = ByteString -> Int
B.length ByteString
bs Int -> Int -> (Int, Int)
forall a. Integral a => a -> a -> (a, a)
`quotRem` Int
3

          padding :: ByteString
padding = case Int
p of
            Int
0 -> ByteString
forall a. Monoid a => a
mempty
            Int
1 -> [Word8] -> ByteString
B.pack [ Word8 -> Word8
byte0   (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Word8
at Int
n Int
0
                        , Word8 -> Word8 -> Word8
byte1 Word8
0 (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Word8
at Int
n Int
0
                        , Word8
pad, Word8
pad
                        ]
            Int
2 -> [Word8] -> ByteString
B.pack [ Word8 -> Word8
byte0          (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Word8
at Int
n Int
0
                        , Word8 -> Word8 -> Word8
byte1 (Int -> Int -> Word8
at Int
n Int
1) (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Word8
at Int
n Int
0
                        , Word8 -> Word8 -> Word8
byte2 Word8
0        (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Word8
at Int
n Int
1
                        , Word8
pad
                        ]
            Int
_ -> String -> ByteString
forall a. HasCallStack => String -> a
error String
"base64 pad bad index"

-- Notes: Merge is used to convert from base64 digits, which are
-- words of 6-bits.
merg0 :: Word8 -> Word8 -> Word8
merg1 :: Word8 -> Word8 -> Word8
merg2 :: Word8 -> Word8 -> Word8
merg0 :: Word8 -> Word8 -> Word8
merg0 Word8
a Word8
b = (Word8 -> Word8
unB64 Word8
a Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`shiftL` Int
2) Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. Word8 -> Word8
top4 (Word8 -> Word8
unB64 Word8
b)
merg1 :: Word8 -> Word8 -> Word8
merg1 Word8
a Word8
b = (Word8 -> Word8
unB64 Word8
a Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`shiftL` Int
4) Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. Word8 -> Word8
top6 (Word8 -> Word8
unB64 Word8
b)
merg2 :: Word8 -> Word8 -> Word8
merg2 Word8
a Word8
b = (Word8 -> Word8
unB64 Word8
a Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`shiftL` Int
6) Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. Word8 -> Word8
unB64 Word8
b


unsafeFromB64 :: ByteString -> ByteString
unsafeFromB64 :: ByteString -> ByteString
unsafeFromB64 ByteString
bs = (ByteString, Maybe Int) -> ByteString
forall a b. (a, b) -> a
fst (Int
-> (Int -> Maybe (Word8, Int)) -> Int -> (ByteString, Maybe Int)
forall a.
Int -> (a -> Maybe (Word8, a)) -> a -> (ByteString, Maybe a)
B.unfoldrN (Int
3Int -> Int -> Int
forall a. Num a => a -> a -> a
*Int
n) Int -> Maybe (Word8, Int)
gen Int
0) ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
unPad
  where n :: Int
n         = ByteString -> Int
B.length ByteString
bs Int -> Int -> Int
forall a. Integral a => a -> a -> a
`quot` Int
4 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
        gen :: Int -> Maybe (Word8, Int)
gen Int
i     = (Word8, Int) -> Maybe (Word8, Int)
forall a. a -> Maybe a
Just (Int -> Word8
byte Int
i, Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
        at :: Int -> Int -> Word8
at Int
blk Int
i  = ByteString -> Int -> Word8
unsafeIndex ByteString
bs (Int -> Word8) -> Int -> Word8
forall a b. (a -> b) -> a -> b
$ Int
4 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
blk Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
i

        byte :: Int -> Word8
byte Int
i    = case Int
r of
          Int
0 -> Word8 -> Word8 -> Word8
merg0 (Int -> Int -> Word8
at Int
q Int
0) (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Word8
at Int
q Int
1
          Int
1 -> Word8 -> Word8 -> Word8
merg1 (Int -> Int -> Word8
at Int
q Int
1) (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Word8
at Int
q Int
2
          Int
2 -> Word8 -> Word8 -> Word8
merg2 (Int -> Int -> Word8
at Int
q Int
2) (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Word8
at Int
q Int
3
          Int
_ -> String -> Word8
forall a. HasCallStack => String -> a
error String
"base64 bad index"
          where (Int
q, Int
r) = Int -> Int -> (Int, Int)
forall a. Integral a => a -> a -> (a, a)
quotRem Int
i Int
3

        unPad :: ByteString
unPad
          | Int -> Int -> Word8
at Int
n Int
2 Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Char -> Word8
c2w Char
'=' = Word8 -> ByteString
B.singleton (Word8 -> ByteString) -> Word8 -> ByteString
forall a b. (a -> b) -> a -> b
$ Word8 -> Word8 -> Word8
merg0 (Int -> Int -> Word8
at Int
n Int
0) (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Word8
at Int
n Int
1
          | Int -> Int -> Word8
at Int
n Int
3 Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Char -> Word8
c2w Char
'=' = [Word8] -> ByteString
B.pack [ Word8 -> Word8 -> Word8
merg0 (Int -> Int -> Word8
at Int
n Int
0) (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Word8
at Int
n Int
1
                                       , Word8 -> Word8 -> Word8
merg1 (Int -> Int -> Word8
at Int
n Int
1) (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Word8
at Int
n Int
2
                                       ]
          | Bool
otherwise         = [Word8] -> ByteString
B.pack [ Word8 -> Word8 -> Word8
merg0 (Int -> Int -> Word8
at Int
n Int
0) (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Word8
at Int
n Int
1
                                       , Word8 -> Word8 -> Word8
merg1 (Int -> Int -> Word8
at Int
n Int
1) (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Word8
at Int
n Int
2
                                       , Word8 -> Word8 -> Word8
merg2 (Int -> Int -> Word8
at Int
n Int
2) (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Word8
at Int
n Int
3
                                       ]