-- | 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 bs :: 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` 4 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= 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 '=' Bool -> Bool -> Bool
|| ByteString
padPart ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== String -> ByteString
C8.pack "=="
          isB64Char :: Char -> Bool
isB64Char c :: 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
== '+' Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== '/'


  unsafeFromByteString :: ByteString -> Base64
unsafeFromByteString bs :: 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 w :: Word8
w = Word8
w Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`shiftR` 2; bot2 :: Word8 -> Word8
bot2 w :: Word8
w = Word8
w Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. 0x03
top4 :: Word8 -> Word8
top4 w :: Word8
w = Word8
w Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`shiftR` 4; bot4 :: Word8 -> Word8
bot4 w :: Word8
w = Word8
w Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. 0x0F
top2 :: Word8 -> Word8
top2 w :: Word8
w = Word8
w Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`shiftR` 6; bot6 :: Word8 -> Word8
bot6 w :: Word8
w = Word8
w Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. 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 t :: Word8
t p :: 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) 4 Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. Word8 -> Word8
top4 Word8
t
byte2 :: Word8 -> Word8 -> Word8
byte2 t :: Word8
t p :: 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) 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 '='

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


unB64 :: Word8 -> Word8
unB64 :: Word8 -> Word8
unB64 w :: Word8
w | Char -> Word8
c2w '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 'Z' = Word8
w Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Char -> Word8
c2w 'A'
        | Char -> Word8
c2w '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 'z' = Word8
w Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Char -> Word8
c2w 'a' Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ 26
        | Char -> Word8
c2w '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 '9' = Word8
w Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Char -> Word8
c2w '0' Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ 52
        | Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Char -> Word8
c2w '+'                 = 62
        | Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Char -> Word8
c2w '/'                 = 63
        | Bool
otherwise                    = String -> Word8
forall a. HasCallStack => String -> a
error (String -> Word8) -> String -> Word8
forall a b. (a -> b) -> a -> b
$ "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 bs :: 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 (4Int -> Int -> Int
forall a. Num a => a -> a -> a
*Int
n) Int -> Maybe (Word8, Int)
gen 0) ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
padding
    where gen :: Int -> Maybe (Word8, Int)
gen i :: 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
+ 1)
          at :: Int -> Int -> Word8
at blk :: Int
blk i :: Int
i = ByteString -> Int -> Word8
unsafeIndex ByteString
bs (Int -> Word8) -> Int -> Word8
forall a b. (a -> b) -> a -> b
$ 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 i :: Int
i = case Int
r of
            0 -> Word8 -> Word8
byte0          (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Word8
at Int
q 0
            1 -> Word8 -> Word8 -> Word8
byte1 (Int -> Int -> Word8
at Int
q 1) (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Word8
at Int
q 0
            2 -> Word8 -> Word8 -> Word8
byte2 (Int -> Int -> Word8
at Int
q 2) (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Word8
at Int
q 1
            3 -> Word8 -> Word8
byte3          (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Word8
at Int
q 2
            _ -> String -> Word8
forall a. HasCallStack => String -> a
error "base64 bad index"
            where (q :: Int
q, r :: Int
r) = Int -> Int -> (Int, Int)
forall a. Integral a => a -> a -> (a, a)
quotRem Int
i 4

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

          padding :: ByteString
padding = case Int
p of
            0 -> ByteString
forall a. Monoid a => a
mempty
            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 0
                        , Word8 -> Word8 -> Word8
byte1 0 (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Word8
at Int
n 0
                        , Word8
pad, Word8
pad
                        ]
            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 0
                        , Word8 -> Word8 -> Word8
byte1 (Int -> Int -> Word8
at Int
n 1) (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Word8
at Int
n 0
                        , Word8 -> Word8 -> Word8
byte2 0        (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Word8
at Int
n 1
                        , Word8
pad
                        ]
            _ -> String -> ByteString
forall a. HasCallStack => String -> a
error "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 a :: Word8
a b :: Word8
b = (Word8 -> Word8
unB64 Word8
a Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`shiftL` 2) Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. Word8 -> Word8
top4 (Word8 -> Word8
unB64 Word8
b)
merg1 :: Word8 -> Word8 -> Word8
merg1 a :: Word8
a b :: Word8
b = (Word8 -> Word8
unB64 Word8
a Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`shiftL` 4) Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. Word8 -> Word8
top6 (Word8 -> Word8
unB64 Word8
b)
merg2 :: Word8 -> Word8 -> Word8
merg2 a :: Word8
a b :: Word8
b = (Word8 -> Word8
unB64 Word8
a Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`shiftL` 6) Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. Word8 -> Word8
unB64 Word8
b


unsafeFromB64 :: ByteString -> ByteString
unsafeFromB64 :: ByteString -> ByteString
unsafeFromB64 bs :: 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 (3Int -> Int -> Int
forall a. Num a => a -> a -> a
*Int
n) Int -> Maybe (Word8, Int)
gen 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` 4 Int -> Int -> Int
forall a. Num a => a -> a -> a
- 1
        gen :: Int -> Maybe (Word8, Int)
gen i :: 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
+ 1)
        at :: Int -> Int -> Word8
at blk :: Int
blk i :: Int
i  = ByteString -> Int -> Word8
unsafeIndex ByteString
bs (Int -> Word8) -> Int -> Word8
forall a b. (a -> b) -> a -> b
$ 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 i :: Int
i    = case Int
r of
          0 -> Word8 -> Word8 -> Word8
merg0 (Int -> Int -> Word8
at Int
q 0) (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Word8
at Int
q 1
          1 -> Word8 -> Word8 -> Word8
merg1 (Int -> Int -> Word8
at Int
q 1) (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Word8
at Int
q 2
          2 -> Word8 -> Word8 -> Word8
merg2 (Int -> Int -> Word8
at Int
q 2) (Word8 -> Word8) -> Word8 -> Word8
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Word8
at Int
q 3
          _ -> String -> Word8
forall a. HasCallStack => String -> a
error "base64 bad index"
          where (q :: Int
q, r :: Int
r) = Int -> Int -> (Int, Int)
forall a. Integral a => a -> a -> (a, a)
quotRem Int
i 3

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