{-# LANGUAGE BinaryLiterals #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
module RON.Base64 (
alphabet,
decode,
decode60,
decode60base32,
decode64,
decode64base32,
decodeLetter,
decodeLetter4,
encode,
encode60,
encode60short,
encode64,
encode64base32short,
encodeLetter,
encodeLetter4,
isLetter,
) where
import RON.Prelude
import Data.Bits (complement, shiftL, shiftR, (.&.), (.|.))
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as BSL
import RON.Util.Word (Word4, Word6 (W6), Word60, leastSignificant4,
leastSignificant6, leastSignificant60, safeCast)
alphabet :: ByteString
alphabet :: ByteString
alphabet = ByteString
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"
isLetter :: Word8 -> Bool
isLetter :: Word8 -> Bool
isLetter Word8
c
= Word8
c Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Word8
ord0 Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
9
Bool -> Bool -> Bool
|| Word8
c Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Word8
ordA Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
25
Bool -> Bool -> Bool
|| Word8
c Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Word8
orda Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
25
Bool -> Bool -> Bool
|| Word8
c Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
ord_
Bool -> Bool -> Bool
|| Word8
c Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
ordõ
decodeLetter :: Word8 -> Maybe Word6
decodeLetter :: Word8 -> Maybe Word6
decodeLetter Word8
x
| Word8
x Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
< Word8
ord0 = Maybe Word6
forall a. Maybe a
Nothing
| Word8
x Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
ord9 = Word6 -> Maybe Word6
forall a. a -> Maybe a
Just (Word6 -> Maybe Word6) -> (Word8 -> Word6) -> Word8 -> Maybe Word6
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Word6
forall integral. Integral integral => integral -> Word6
leastSignificant6 (Word8 -> Maybe Word6) -> Word8 -> Maybe Word6
forall a b. (a -> b) -> a -> b
$ Word8
x Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Word8
ord0
| Word8
x Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
< Word8
ordA = Maybe Word6
forall a. Maybe a
Nothing
| Word8
x Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
ordZ = Word6 -> Maybe Word6
forall a. a -> Maybe a
Just (Word6 -> Maybe Word6) -> (Word8 -> Word6) -> Word8 -> Maybe Word6
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Word6
forall integral. Integral integral => integral -> Word6
leastSignificant6 (Word8 -> Maybe Word6) -> Word8 -> Maybe Word6
forall a b. (a -> b) -> a -> b
$ Word8
x Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Word8
ordA Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
posA
| Word8
x Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
ord_ = Word6 -> Maybe Word6
forall a. a -> Maybe a
Just (Word6 -> Maybe Word6) -> Word6 -> Maybe Word6
forall a b. (a -> b) -> a -> b
$ Word8 -> Word6
forall integral. Integral integral => integral -> Word6
leastSignificant6 Word8
pos_
| Word8
x Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
< Word8
orda = Maybe Word6
forall a. Maybe a
Nothing
| Word8
x Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
ordz = Word6 -> Maybe Word6
forall a. a -> Maybe a
Just (Word6 -> Maybe Word6) -> (Word8 -> Word6) -> Word8 -> Maybe Word6
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Word6
forall integral. Integral integral => integral -> Word6
leastSignificant6 (Word8 -> Maybe Word6) -> Word8 -> Maybe Word6
forall a b. (a -> b) -> a -> b
$ Word8
x Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Word8
orda Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
posa
| Word8
x Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
ordõ = Word6 -> Maybe Word6
forall a. a -> Maybe a
Just (Word6 -> Maybe Word6) -> Word6 -> Maybe Word6
forall a b. (a -> b) -> a -> b
$ Word8 -> Word6
forall integral. Integral integral => integral -> Word6
leastSignificant6 Word8
posõ
| Bool
otherwise = Maybe Word6
forall a. Maybe a
Nothing
ord0, ord9, ordA, ordZ, ord_, orda, ordz, ordõ :: Word8
ord0 :: Word8
ord0 = Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word8) -> Int -> Word8
forall a b. (a -> b) -> a -> b
$ Char -> Int
ord Char
'0'
ord9 :: Word8
ord9 = Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word8) -> Int -> Word8
forall a b. (a -> b) -> a -> b
$ Char -> Int
ord Char
'9'
ordA :: Word8
ordA = Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word8) -> Int -> Word8
forall a b. (a -> b) -> a -> b
$ Char -> Int
ord Char
'A'
ordZ :: Word8
ordZ = Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word8) -> Int -> Word8
forall a b. (a -> b) -> a -> b
$ Char -> Int
ord Char
'Z'
ord_ :: Word8
ord_ = Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word8) -> Int -> Word8
forall a b. (a -> b) -> a -> b
$ Char -> Int
ord Char
'_'
orda :: Word8
orda = Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word8) -> Int -> Word8
forall a b. (a -> b) -> a -> b
$ Char -> Int
ord Char
'a'
ordz :: Word8
ordz = Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word8) -> Int -> Word8
forall a b. (a -> b) -> a -> b
$ Char -> Int
ord Char
'z'
ordõ :: Word8
ordõ = Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word8) -> Int -> Word8
forall a b. (a -> b) -> a -> b
$ Char -> Int
ord Char
'~'
posA, pos_, posa, posõ :: Word8
posA :: Word8
posA = Word8
10
pos_ :: Word8
pos_ = Word8
36
posa :: Word8
posa = Word8
37
posõ :: Word8
posõ = Word8
63
decodeLetter4 :: Word8 -> Maybe Word4
decodeLetter4 :: Word8 -> Maybe Word4
decodeLetter4 Word8
x
| Word8
x Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
< Word8
ord0 = Maybe Word4
forall a. Maybe a
Nothing
| Word8
x Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
ord9 = Word4 -> Maybe Word4
forall a. a -> Maybe a
Just (Word4 -> Maybe Word4) -> (Word8 -> Word4) -> Word8 -> Maybe Word4
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Word4
forall integral. Integral integral => integral -> Word4
leastSignificant4 (Word8 -> Maybe Word4) -> Word8 -> Maybe Word4
forall a b. (a -> b) -> a -> b
$ Word8
x Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Word8
ord0
| Word8
x Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
< Word8
ordA = Maybe Word4
forall a. Maybe a
Nothing
| Word8
x Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
ordZ = Word4 -> Maybe Word4
forall a. a -> Maybe a
Just (Word4 -> Maybe Word4) -> (Word8 -> Word4) -> Word8 -> Maybe Word4
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Word4
forall integral. Integral integral => integral -> Word4
leastSignificant4 (Word8 -> Maybe Word4) -> Word8 -> Maybe Word4
forall a b. (a -> b) -> a -> b
$ Word8
x Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Word8
ordA Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
posA
| Bool
otherwise = Maybe Word4
forall a. Maybe a
Nothing
decode :: ByteStringL -> Maybe ByteStringL
decode :: ByteStringL -> Maybe ByteStringL
decode =
([Word6] -> ByteStringL) -> Maybe [Word6] -> Maybe ByteStringL
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ([Word8] -> ByteStringL
BSL.pack ([Word8] -> ByteStringL)
-> ([Word6] -> [Word8]) -> [Word6] -> ByteStringL
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Word8] -> [Word8]
go ([Word8] -> [Word8]) -> ([Word6] -> [Word8]) -> [Word6] -> [Word8]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word6 -> Word8) -> [Word6] -> [Word8]
forall a b. (a -> b) -> [a] -> [b]
map Word6 -> Word8
forall v w. SafeCast v w => v -> w
safeCast) (Maybe [Word6] -> Maybe ByteStringL)
-> (ByteStringL -> Maybe [Word6])
-> ByteStringL
-> Maybe ByteStringL
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word8 -> Maybe Word6) -> [Word8] -> Maybe [Word6]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse Word8 -> Maybe Word6
decodeLetter ([Word8] -> Maybe [Word6])
-> (ByteStringL -> [Word8]) -> ByteStringL -> Maybe [Word6]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteStringL -> [Word8]
BSL.unpack
where
go :: [Word8] -> [Word8]
go = \case
[Word8
a, Word8
b] -> Word8 -> Word8 -> [Word8]
forall a. Bits a => a -> a -> [a]
decode2 Word8
a Word8
b
[Word8
a, Word8
b, Word8
c] -> Word8 -> Word8 -> Word8 -> [Word8]
forall a. (Bits a, Num a) => a -> a -> a -> [a]
decode3 Word8
a Word8
b Word8
c
Word8
a:Word8
b:Word8
c:Word8
d:[Word8]
rest -> Word8 -> Word8 -> Word8 -> Word8 -> [Word8]
forall a. (Bits a, Num a) => a -> a -> a -> a -> [a]
decode4 Word8
a Word8
b Word8
c Word8
d [Word8] -> [Word8] -> [Word8]
forall a. [a] -> [a] -> [a]
++ [Word8] -> [Word8]
go [Word8]
rest
[Word8]
_ -> []
decode2 :: a -> a -> [a]
decode2 a
a a
b = [(a
a a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftL` Int
2) a -> a -> a
forall a. Bits a => a -> a -> a
.|. (a
b a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftR` Int
4)]
decode3 :: a -> a -> a -> [a]
decode3 a
a a
b a
c =
[ ( a
a a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftL` Int
2) a -> a -> a
forall a. Bits a => a -> a -> a
.|. (a
b a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftR` Int
4)
, ((a
b a -> a -> a
forall a. Bits a => a -> a -> a
.&. a
0b1111) a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftL` Int
4) a -> a -> a
forall a. Bits a => a -> a -> a
.|. (a
c a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftR` Int
2)
]
decode4 :: a -> a -> a -> a -> [a]
decode4 a
a a
b a
c a
d =
[ ( a
a a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftL` Int
2) a -> a -> a
forall a. Bits a => a -> a -> a
.|. (a
b a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftR` Int
4)
, ((a
b a -> a -> a
forall a. Bits a => a -> a -> a
.&. a
0b1111) a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftL` Int
4) a -> a -> a
forall a. Bits a => a -> a -> a
.|. (a
c a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftR` Int
2)
, ((a
c a -> a -> a
forall a. Bits a => a -> a -> a
.&. a
0b11) a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftL` Int
6) a -> a -> a
forall a. Bits a => a -> a -> a
.|. a
d
]
decode60 :: ByteString -> Maybe Word60
decode60 :: ByteString -> Maybe Word60
decode60 =
(Word64 -> Word60) -> Maybe Word64 -> Maybe Word60
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Word64 -> Word60
forall integral. Integral integral => integral -> Word60
leastSignificant60 (Maybe Word64 -> Maybe Word60)
-> ([Word8] -> Maybe Word64) -> [Word8] -> Maybe Word60
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [Word8] -> Maybe Word64
go Int
10
([Word8] -> Maybe Word60)
-> (ByteString -> Maybe [Word8]) -> ByteString -> Maybe Word60
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< (Word8 -> Maybe Word8) -> [Word8] -> Maybe [Word8]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse ((Word6 -> Word8) -> Maybe Word6 -> Maybe Word8
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Word6 -> Word8
forall v w. SafeCast v w => v -> w
safeCast (Maybe Word6 -> Maybe Word8)
-> (Word8 -> Maybe Word6) -> Word8 -> Maybe Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Maybe Word6
decodeLetter) ([Word8] -> Maybe [Word8])
-> (ByteString -> [Word8]) -> ByteString -> Maybe [Word8]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [Word8]
BS.unpack
where
go :: Int -> [Word8] -> Maybe Word64
go :: Int -> [Word8] -> Maybe Word64
go Int
n = \case
[] | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 -> Word64 -> Maybe Word64
forall a. a -> Maybe a
Just Word64
0
[Word8
a] | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
1 -> Word64 -> Maybe Word64
forall a. a -> Maybe a
Just (Word64 -> Maybe Word64) -> Word64 -> Maybe Word64
forall a b. (a -> b) -> a -> b
$ Word8 -> Word8 -> Word8 -> Word8 -> Word64
decode4 Word8
a Word8
0 Word8
0 Word8
0
[Word8
a, Word8
b]
| Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
2 -> Word64 -> Maybe Word64
forall a. a -> Maybe a
Just (Word64 -> Maybe Word64) -> Word64 -> Maybe Word64
forall a b. (a -> b) -> a -> b
$ Word8 -> Word8 -> Word8 -> Word8 -> Word64
decode4 Word8
a Word8
b Word8
0 Word8
0
[Word8
a, Word8
b, Word8
c]
| Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
3 -> Word64 -> Maybe Word64
forall a. a -> Maybe a
Just (Word64 -> Maybe Word64) -> Word64 -> Maybe Word64
forall a b. (a -> b) -> a -> b
$ Word8 -> Word8 -> Word8 -> Word8 -> Word64
decode4 Word8
a Word8
b Word8
c Word8
0
(Word8
a:Word8
b:Word8
c:Word8
d:[Word8]
rest)
| Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
4 -> do
Word64
lowerPart <- Int -> [Word8] -> Maybe Word64
go (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
4) [Word8]
rest
Word64 -> Maybe Word64
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word64 -> Maybe Word64) -> Word64 -> Maybe Word64
forall a b. (a -> b) -> a -> b
$ Word8 -> Word8 -> Word8 -> Word8 -> Word64
decode4 Word8
a Word8
b Word8
c Word8
d Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. (Word64
lowerPart Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`shiftR` Int
24)
[Word8]
_ -> Maybe Word64
forall a. Maybe a
Nothing
decode4 :: Word8 -> Word8 -> Word8 -> Word8 -> Word64
decode4 :: Word8 -> Word8 -> Word8 -> Word8 -> Word64
decode4 Word8
a Word8
b Word8
c Word8
d =
(Word8 -> Word64
forall v w. SafeCast v w => v -> w
safeCast Word8
a Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`shiftL` Int
54) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|.
(Word8 -> Word64
forall v w. SafeCast v w => v -> w
safeCast Word8
b Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`shiftL` Int
48) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|.
(Word8 -> Word64
forall v w. SafeCast v w => v -> w
safeCast Word8
c Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`shiftL` Int
42) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|.
(Word8 -> Word64
forall v w. SafeCast v w => v -> w
safeCast Word8
d Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`shiftL` Int
36)
decode60base32 :: ByteString -> Maybe Word60
decode60base32 :: ByteString -> Maybe Word60
decode60base32 =
(Word64 -> Word60) -> Maybe Word64 -> Maybe Word60
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Word64 -> Word60
forall integral. Integral integral => integral -> Word60
leastSignificant60 (Maybe Word64 -> Maybe Word60)
-> ([Word8] -> Maybe Word64) -> [Word8] -> Maybe Word60
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Word8] -> Maybe Word64
go12
([Word8] -> Maybe Word60)
-> (ByteString -> Maybe [Word8]) -> ByteString -> Maybe Word60
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< (Word8 -> Maybe Word8) -> [Word8] -> Maybe [Word8]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse ((Word6 -> Word8) -> Maybe Word6 -> Maybe Word8
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Word6 -> Word8
forall v w. SafeCast v w => v -> w
safeCast (Maybe Word6 -> Maybe Word8)
-> (Word8 -> Maybe Word6) -> Word8 -> Maybe Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Maybe Word6
decodeLetter) ([Word8] -> Maybe [Word8])
-> (ByteString -> [Word8]) -> ByteString -> Maybe [Word8]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [Word8]
BS.unpack
where
go12 :: [Word8] -> Maybe Word64
go12 :: [Word8] -> Maybe Word64
go12 [Word8]
letters = do
let ([Word8]
letters8, [Word8]
letters4) = Int -> [Word8] -> ([Word8], [Word8])
forall a. Int -> [a] -> ([a], [a])
splitAt Int
8 [Word8]
letters
w8 :: Word64
w8 = Int -> [Word8] -> Word64
decodeBase32 Int
8 [Word8]
letters8
Word64
w4 <- [Word8] -> Maybe Word64
go4 [Word8]
letters4
Word64 -> Maybe Word64
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word64 -> Maybe Word64) -> Word64 -> Maybe Word64
forall a b. (a -> b) -> a -> b
$ (Word64
w8 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`shiftL` Int
20) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word64
w4
go4 :: [Word8] -> Maybe Word64
go4 :: [Word8] -> Maybe Word64
go4 [Word8]
letters = case Int -> [Word8] -> ([Word8], [Word8])
forall a. Int -> [a] -> ([a], [a])
splitAt Int
4 [Word8]
letters of
([Word8]
letters4, []) -> Word64 -> Maybe Word64
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word64 -> Maybe Word64) -> Word64 -> Maybe Word64
forall a b. (a -> b) -> a -> b
$ Int -> [Word8] -> Word64
decodeBase32 Int
4 [Word8]
letters4
([Word8], [Word8])
_ -> Maybe Word64
forall a. Maybe a
Nothing
decodeBase32 :: Int -> [Word8] -> Word64
decodeBase32 :: Int -> [Word8] -> Word64
decodeBase32 Int
len
= (Word64 -> Word8 -> Word64) -> Word64 -> [Word8] -> Word64
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\Word64
acc Word8
b -> (Word64
acc Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`shiftL` Int
5) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall v w. SafeCast v w => v -> w
safeCast Word8
b) Word64
0
([Word8] -> Word64) -> ([Word8] -> [Word8]) -> [Word8] -> Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [Word8] -> [Word8]
forall a. Int -> [a] -> [a]
take Int
len
([Word8] -> [Word8]) -> ([Word8] -> [Word8]) -> [Word8] -> [Word8]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Word8] -> [Word8] -> [Word8]
forall a. [a] -> [a] -> [a]
++ Word8 -> [Word8]
forall a. a -> [a]
repeat Word8
0)
decode64 :: ByteString -> Maybe Word64
decode64 :: ByteString -> Maybe Word64
decode64 ByteString
s = do
(Word8
s0, ByteString
s1) <- ByteString -> Maybe (Word8, ByteString)
BS.uncons ByteString
s
Word4 -> Word60 -> Word64
cons64 (Word4 -> Word60 -> Word64)
-> Maybe Word4 -> Maybe (Word60 -> Word64)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Word8 -> Maybe Word4
decodeLetter4 Word8
s0 Maybe (Word60 -> Word64) -> Maybe Word60 -> Maybe Word64
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ByteString -> Maybe Word60
decode60 ByteString
s1
decode64base32 :: ByteString -> Maybe Word64
decode64base32 :: ByteString -> Maybe Word64
decode64base32 ByteString
s = do
(Word8
s0, ByteString
s1) <- ByteString -> Maybe (Word8, ByteString)
BS.uncons ByteString
s
Word4 -> Word60 -> Word64
cons64 (Word4 -> Word60 -> Word64)
-> Maybe Word4 -> Maybe (Word60 -> Word64)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Word8 -> Maybe Word4
decodeLetter4 Word8
s0 Maybe (Word60 -> Word64) -> Maybe Word60 -> Maybe Word64
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ByteString -> Maybe Word60
decode60base32 ByteString
s1
cons64 :: Word4 -> Word60 -> Word64
cons64 :: Word4 -> Word60 -> Word64
cons64 Word4
v Word60
w = (Word4 -> Word64
forall v w. SafeCast v w => v -> w
safeCast Word4
v Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`shiftL` Int
60) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word60 -> Word64
forall v w. SafeCast v w => v -> w
safeCast Word60
w
encode :: ByteStringL -> ByteStringL
encode :: ByteStringL -> ByteStringL
encode = [Word8] -> ByteStringL
BSL.pack ([Word8] -> ByteStringL)
-> (ByteStringL -> [Word8]) -> ByteStringL -> ByteStringL
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Word8] -> [Word8]
go ([Word8] -> [Word8])
-> (ByteStringL -> [Word8]) -> ByteStringL -> [Word8]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteStringL -> [Word8]
BSL.unpack
where
go :: [Word8] -> [Word8]
go = \case
[] -> []
[Word8
a] -> Word8 -> [Word8]
forall a. (Integral a, Bits a) => a -> [Word8]
encode1 Word8
a
[Word8
a, Word8
b] -> Word8 -> Word8 -> [Word8]
forall a. (Integral a, Bits a) => a -> a -> [Word8]
encode2 Word8
a Word8
b
Word8
a:Word8
b:Word8
c:[Word8]
rest -> Word8 -> Word8 -> Word8 -> [Word8]
forall a. (Integral a, Bits a) => a -> a -> a -> [Word8]
encode3 Word8
a Word8
b Word8
c [Word8] -> [Word8] -> [Word8]
forall a. [a] -> [a] -> [a]
++ [Word8] -> [Word8]
go [Word8]
rest
encode1 :: a -> [Word8]
encode1 a
a =
(a -> Word8) -> [a] -> [Word8]
forall a b. (a -> b) -> [a] -> [b]
map (Word6 -> Word8
encodeLetter (Word6 -> Word8) -> (a -> Word6) -> a -> Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Word6
forall integral. Integral integral => integral -> Word6
leastSignificant6)
[a
a a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftR` Int
2, (a
a a -> a -> a
forall a. Bits a => a -> a -> a
.&. a
0b11) a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftL` Int
4]
encode2 :: a -> a -> [Word8]
encode2 a
a a
b = (a -> Word8) -> [a] -> [Word8]
forall a b. (a -> b) -> [a] -> [b]
map (Word6 -> Word8
encodeLetter (Word6 -> Word8) -> (a -> Word6) -> a -> Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Word6
forall integral. Integral integral => integral -> Word6
leastSignificant6)
[ a
a a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftR` Int
2
, ((a
a a -> a -> a
forall a. Bits a => a -> a -> a
.&. a
0b11) a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftL` Int
4) a -> a -> a
forall a. Bits a => a -> a -> a
.|. (a
b a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftR` Int
4)
, (a
b a -> a -> a
forall a. Bits a => a -> a -> a
.&. a
0b1111) a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftL` Int
2
]
encode3 :: a -> a -> a -> [Word8]
encode3 a
a a
b a
c = (a -> Word8) -> [a] -> [Word8]
forall a b. (a -> b) -> [a] -> [b]
map (Word6 -> Word8
encodeLetter (Word6 -> Word8) -> (a -> Word6) -> a -> Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Word6
forall integral. Integral integral => integral -> Word6
leastSignificant6)
[ a
a a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftR` Int
2
, ((a
a a -> a -> a
forall a. Bits a => a -> a -> a
.&. a
0b11) a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftL` Int
4) a -> a -> a
forall a. Bits a => a -> a -> a
.|. (a
b a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftR` Int
4)
, ((a
b a -> a -> a
forall a. Bits a => a -> a -> a
.&. a
0b1111) a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftL` Int
2) a -> a -> a
forall a. Bits a => a -> a -> a
.|. (a
c a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftR` Int
6)
, a
c a -> a -> a
forall a. Bits a => a -> a -> a
.&. a
0b111111
]
encodeLetter :: Word6 -> Word8
encodeLetter :: Word6 -> Word8
encodeLetter Word6
i = ByteString
alphabet ByteString -> Int -> Word8
`BS.index` Word6 -> Int
forall v w. SafeCast v w => v -> w
safeCast Word6
i
encodeLetter4 :: Word4 -> Word8
encodeLetter4 :: Word4 -> Word8
encodeLetter4 Word4
i = ByteString
alphabet ByteString -> Int -> Word8
`BS.index` Word4 -> Int
forall v w. SafeCast v w => v -> w
safeCast Word4
i
encode60 :: Word60 -> ByteString
encode60 :: Word60 -> ByteString
encode60 Word60
w = [Word8] -> ByteString
BS.pack
[ Word6 -> Word8
encodeLetter (Word6 -> Word8) -> Word6 -> Word8
forall a b. (a -> b) -> a -> b
$ Word64 -> Word6
forall integral. Integral integral => integral -> Word6
leastSignificant6 (Word60 -> Word64
forall v w. SafeCast v w => v -> w
safeCast Word60
w Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`shiftR` (Int
6 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
i) :: Word64)
| Int
i <- [Int
9, Int
8 .. Int
0]
]
encode60short :: Word60 -> ByteString
encode60short :: Word60 -> ByteString
encode60short Word60
v = case Word60 -> Word64
forall v w. SafeCast v w => v -> w
safeCast Word60
v :: Word64 of
Word64
0 -> ByteString
"0"
Word64
x -> [Word8] -> ByteString
BS.pack ([Word8] -> ByteString)
-> ([Word64] -> [Word8]) -> [Word64] -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word64 -> Word8) -> [Word64] -> [Word8]
forall a b. (a -> b) -> [a] -> [b]
map (Word6 -> Word8
encodeLetter (Word6 -> Word8) -> (Word64 -> Word6) -> Word64 -> Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word64 -> Word6
forall integral. Integral integral => integral -> Word6
leastSignificant6) ([Word64] -> ByteString) -> [Word64] -> ByteString
forall a b. (a -> b) -> a -> b
$ Int -> Word64 -> [Word64]
forall a. (Num a, Bits a) => Int -> a -> [a]
go Int
9 Word64
x
where
go :: Int -> a -> [a]
go Int
_ a
0 = []
go Int
i a
w =
(a
w a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftR` (Int
6 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
i)) a -> a -> a
forall a. Bits a => a -> a -> a
.&. a
0b111111 a -> [a] -> [a]
forall a. a -> [a] -> [a]
:
Int -> a -> [a]
go (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) (a
w a -> a -> a
forall a. Bits a => a -> a -> a
.&. a -> a
forall a. Bits a => a -> a
complement (a
0b111111 a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftL` (Int
6 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
i)))
encode64base32short :: Word64 -> ByteString
encode64base32short :: Word64 -> ByteString
encode64base32short = \case
Word64
0 -> ByteString
"0"
Word64
x -> [Word8] -> ByteString
BS.pack ([Word8] -> ByteString)
-> ([Word64] -> [Word8]) -> [Word64] -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word64 -> Word8) -> [Word64] -> [Word8]
forall a b. (a -> b) -> [a] -> [b]
map (Word6 -> Word8
encodeLetter (Word6 -> Word8) -> (Word64 -> Word6) -> Word64 -> Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word64 -> Word6
forall integral. Integral integral => integral -> Word6
leastSignificant5) ([Word64] -> ByteString) -> [Word64] -> ByteString
forall a b. (a -> b) -> a -> b
$ Int -> Word64 -> [Word64]
forall a. (Num a, Bits a) => Int -> a -> [a]
go Int
12 Word64
x
where
go :: Int -> a -> [a]
go Int
_ a
0 = []
go Int
i a
w =
(a
w a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftR` (Int
5 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
i)) a -> a -> a
forall a. Bits a => a -> a -> a
.&. a
0b11111 a -> [a] -> [a]
forall a. a -> [a] -> [a]
:
Int -> a -> [a]
go (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) (a
w a -> a -> a
forall a. Bits a => a -> a -> a
.&. a -> a
forall a. Bits a => a -> a
complement (a
0b11111 a -> Int -> a
forall a. Bits a => a -> Int -> a
`shiftL` (Int
5 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
i)))
leastSignificant5 :: a -> Word6
leastSignificant5 a
w = Word8 -> Word6
W6 (Word8 -> Word6) -> Word8 -> Word6
forall a b. (a -> b) -> a -> b
$ a -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
w Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b11111
encode64 :: Word64 -> ByteString
encode64 :: Word64 -> ByteString
encode64 Word64
w =
Word6 -> Word8
encodeLetter (Word64 -> Word6
forall integral. Integral integral => integral -> Word6
leastSignificant6 (Word64 -> Word6) -> Word64 -> Word6
forall a b. (a -> b) -> a -> b
$ Word64
w Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`shiftR` Int
60)
Word8 -> ByteString -> ByteString
`BS.cons` Word60 -> ByteString
encode60 (Word64 -> Word60
forall integral. Integral integral => integral -> Word60
leastSignificant60 Word64
w)