{-# OPTIONS_HADDOCK hide #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Raaz.Core.Encode.Base64( Base64 ) where
import Data.Char
import Data.ByteString as B
import Data.ByteString.Char8 as C8
import Data.ByteString.Internal (c2w, w2c)
import Data.ByteString.Unsafe (unsafeIndex)
import Raaz.Core.Prelude
import Raaz.Core.Encode.Internal
newtype Base64 = Base64 {Base64 -> ByteString
unBase64 :: ByteString} deriving (Base64 -> Base64 -> Bool
(Base64 -> Base64 -> Bool)
-> (Base64 -> Base64 -> Bool) -> Eq Base64
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Base64 -> Base64 -> Bool
== :: Base64 -> Base64 -> Bool
$c/= :: Base64 -> Base64 -> Bool
/= :: Base64 -> Base64 -> Bool
Eq, 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
$c<> :: Base64 -> Base64 -> Base64
<> :: Base64 -> Base64 -> Base64
$csconcat :: NonEmpty Base64 -> Base64
sconcat :: NonEmpty Base64 -> Base64
$cstimes :: forall b. Integral b => b -> Base64 -> Base64
stimes :: forall b. Integral b => b -> 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
$cmempty :: Base64
mempty :: Base64
$cmappend :: Base64 -> Base64 -> Base64
mappend :: Base64 -> Base64 -> Base64
$cmconcat :: [Base64] -> Base64
mconcat :: [Base64] -> Base64
Monoid)
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
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 #-}
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
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
'='
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]
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"
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
]