{-# OPTIONS_HADDOCK prune #-}
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE BinaryLiterals #-}
{-# LANGUAGE OverloadedStrings #-}
module Data.ByteString.Base16 (
encode
, decode
) where
import qualified Data.Bits as B
import Data.Bits ((.&.), (.|.))
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, Word16)
to_strict :: BSB.Builder -> BS.ByteString
to_strict :: Builder -> ByteString
to_strict = ByteString -> ByteString
BS.toStrict (ByteString -> ByteString)
-> (Builder -> ByteString) -> Builder -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> ByteString
BSB.toLazyByteString
{-# INLINE to_strict #-}
to_strict_small :: BSB.Builder -> BS.ByteString
to_strict_small :: Builder -> ByteString
to_strict_small = 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 to_strict_small #-}
fi :: (Num a, Integral b) => b -> a
fi :: forall a b. (Num a, Integral b) => b -> a
fi = b -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral
{-# INLINE fi #-}
hex_charset :: BS.ByteString
hex_charset :: ByteString
hex_charset = ByteString
"0123456789abcdef"
expand_w8 :: Word8 -> Word16
expand_w8 :: Word8 -> Word16
expand_w8 Word8
b =
let !hi :: Word8
hi = ByteString -> Int -> Word8
BU.unsafeIndex ByteString
hex_charset (Word8 -> Int
forall a b. (Num a, Integral b) => b -> a
fi Word8
b Int -> Int -> Int
forall a. Bits a => a -> Int -> a
`B.shiftR` Int
4)
!lo :: Word8
lo = ByteString -> Int -> Word8
BU.unsafeIndex ByteString
hex_charset (Word8 -> Int
forall a b. (Num a, Integral b) => b -> a
fi Word8
b Int -> Int -> Int
forall a. Bits a => a -> a -> a
.&. Int
0b00001111)
in Word8 -> Word16
forall a b. (Num a, Integral b) => b -> a
fi Word8
hi Word16 -> Int -> Word16
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
8
Word16 -> Word16 -> Word16
forall a. Bits a => a -> a -> a
.|. Word8 -> Word16
forall a b. (Num a, Integral b) => b -> a
fi Word8
lo
{-# INLINE expand_w8 #-}
encode :: BS.ByteString -> BS.ByteString
encode :: ByteString -> ByteString
encode bs :: ByteString
bs@(BI.PS ForeignPtr Word8
_ Int
_ Int
l)
| Int
l Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
64 = Builder -> ByteString
to_strict_small Builder
loop
| Bool
otherwise = Builder -> ByteString
to_strict Builder
loop
where
loop :: Builder
loop
| Int
l 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 =
ByteString -> Builder
go64 ByteString
bs
| (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
3) 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 = case Int -> ByteString -> (ByteString, ByteString)
BS.splitAt (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
3) ByteString
bs of
(ByteString
chunk, ByteString
etc) ->
ByteString -> Builder
go64 ByteString
chunk
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> ByteString -> Builder
go32 (Int -> ByteString -> ByteString
BU.unsafeTake Int
2 ByteString
etc)
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> ByteString -> Builder
go16 (Int -> ByteString -> ByteString
BU.unsafeDrop Int
2 ByteString
etc)
| (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2) 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 = case Int -> ByteString -> (ByteString, ByteString)
BS.splitAt (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2) ByteString
bs of
(ByteString
chunk, ByteString
etc) ->
ByteString -> Builder
go64 ByteString
chunk
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> ByteString -> Builder
go32 ByteString
etc
| (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) 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 = case Int -> ByteString -> (ByteString, ByteString)
BS.splitAt (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) ByteString
bs of
(ByteString
chunk, ByteString
etc) ->
ByteString -> Builder
go64 ByteString
chunk
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> ByteString -> Builder
go16 ByteString
etc
| Int
l Int -> Int -> Int
forall a. Integral a => a -> a -> a
`rem` Int
2 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 =
ByteString -> Builder
go32 ByteString
bs
| (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`rem` Int
2 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = case Int -> ByteString -> (ByteString, ByteString)
BS.splitAt (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) ByteString
bs of
(ByteString
chunk, ByteString
etc) ->
ByteString -> Builder
go32 ByteString
chunk
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> ByteString -> Builder
go16 ByteString
etc
| Bool
otherwise =
ByteString -> Builder
go16 ByteString
bs
go64 :: ByteString -> Builder
go64 ByteString
b = case Int -> ByteString -> (ByteString, ByteString)
BS.splitAt Int
4 ByteString
b of
(ByteString
chunk, ByteString
etc)
| ByteString -> Bool
BS.null ByteString
chunk -> Builder
forall a. Monoid a => a
mempty
| Bool
otherwise ->
let !w16_0 :: Word16
w16_0 = Word8 -> Word16
expand_w8 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
0)
!w16_1 :: Word16
w16_1 = Word8 -> Word16
expand_w8 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
1)
!w16_2 :: Word16
w16_2 = Word8 -> Word16
expand_w8 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
2)
!w16_3 :: Word16
w16_3 = Word8 -> Word16
expand_w8 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
3)
!w64 :: Word64
w64 = Word16 -> Word64
forall a b. (Num a, Integral b) => b -> a
fi Word16
w16_0 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
48
Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word16 -> Word64
forall a b. (Num a, Integral b) => b -> a
fi Word16
w16_1 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
32
Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word16 -> Word64
forall a b. (Num a, Integral b) => b -> a
fi Word16
w16_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
.|. Word16 -> Word64
forall a b. (Num a, Integral b) => b -> a
fi Word16
w16_3
in Word64 -> Builder
BSB.word64BE Word64
w64 Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> ByteString -> Builder
go64 ByteString
etc
go32 :: ByteString -> Builder
go32 ByteString
b = case Int -> ByteString -> (ByteString, ByteString)
BS.splitAt Int
2 ByteString
b of
(ByteString
chunk, ByteString
etc)
| ByteString -> Bool
BS.null ByteString
chunk -> Builder
forall a. Monoid a => a
mempty
| Bool
otherwise ->
let !w16_0 :: Word16
w16_0 = Word8 -> Word16
expand_w8 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
0)
!w16_1 :: Word16
w16_1 = Word8 -> Word16
expand_w8 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
1)
!w32 :: Word32
w32 = Word16 -> Word32
forall a b. (Num a, Integral b) => b -> a
fi Word16
w16_0 Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
16
Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. Word16 -> Word32
forall a b. (Num a, Integral b) => b -> a
fi Word16
w16_1
in Word32 -> Builder
BSB.word32BE Word32
w32 Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> ByteString -> Builder
go32 ByteString
etc
go16 :: ByteString -> Builder
go16 ByteString
b = case ByteString -> Maybe (Word8, ByteString)
BS.uncons ByteString
b of
Maybe (Word8, ByteString)
Nothing -> Builder
forall a. Monoid a => a
mempty
Just (Word8
h, ByteString
t) ->
let !w16 :: Word16
w16 = Word8 -> Word16
expand_w8 Word8
h
in Word16 -> Builder
BSB.word16BE Word16
w16 Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> ByteString -> Builder
go16 ByteString
t
word4 :: Word8 -> Maybe Word8
word4 :: Word8 -> Maybe Word8
word4 Word8
c
| Word8
c Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
> Word8
47 Bool -> Bool -> Bool
&& Word8
c Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
< Word8
58 = 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
c Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Word8
48
| Word8
c Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
> Word8
64 Bool -> Bool -> Bool
&& Word8
c Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
< Word8
71 = 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
c Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Word8
55
| Word8
c Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
> Word8
96 Bool -> Bool -> Bool
&& Word8
c Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
< 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
c Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
- Word8
87
| Bool
otherwise = Maybe Word8
forall a. Maybe a
Nothing
{-# INLINE word4 #-}
decode :: BS.ByteString -> Maybe BS.ByteString
decode :: ByteString -> Maybe ByteString
decode bs :: ByteString
bs@(BI.PS ForeignPtr Word8
_ Int
_ Int
l)
| Int -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
B.testBit Int
l Int
0 = Maybe ByteString
forall a. Maybe a
Nothing
| Int
l Int -> Int -> Int
forall a. Integral a => a -> a -> a
`quot` Int
2 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
128 = (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
to_strict_small Maybe Builder
loop
| Bool
otherwise = (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
to_strict Maybe Builder
loop
where
loop :: Maybe Builder
loop
| Int
l Int -> Int -> Int
forall a. Integral a => a -> a -> a
`rem` Int
16 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 =
Builder -> ByteString -> Maybe Builder
go64 Builder
forall a. Monoid a => a
mempty ByteString
bs
| (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`rem` Int
16 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = case Int -> ByteString -> (ByteString, ByteString)
BS.splitAt (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2) ByteString
bs of
(ByteString
chunk, ByteString
etc) -> do
Builder
b0 <- Builder -> ByteString -> Maybe Builder
go64 Builder
forall a. Monoid a => a
mempty ByteString
chunk
Builder -> ByteString -> Maybe Builder
go8 Builder
b0 ByteString
etc
| (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
4) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`rem` Int
16 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = case Int -> ByteString -> (ByteString, ByteString)
BS.splitAt (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
4) ByteString
bs of
(ByteString
chunk, ByteString
etc) -> do
Builder
b0 <- Builder -> ByteString -> Maybe Builder
go64 Builder
forall a. Monoid a => a
mempty ByteString
chunk
Builder -> ByteString -> Maybe Builder
go16 Builder
b0 ByteString
etc
| (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
6) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`rem` Int
16 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = case Int -> ByteString -> (ByteString, ByteString)
BS.splitAt (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
6) ByteString
bs of
(ByteString
chunk, ByteString
etc) -> do
Builder
b0 <- Builder -> ByteString -> Maybe Builder
go64 Builder
forall a. Monoid a => a
mempty ByteString
chunk
Builder
b1 <- Builder -> ByteString -> Maybe Builder
go16 Builder
b0 (Int -> ByteString -> ByteString
BU.unsafeTake Int
4 ByteString
etc)
Builder -> ByteString -> Maybe Builder
go8 Builder
b1 (Int -> ByteString -> ByteString
BU.unsafeDrop Int
4 ByteString
etc)
| (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
8) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`rem` Int
16 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = case Int -> ByteString -> (ByteString, ByteString)
BS.splitAt (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
8) ByteString
bs of
(ByteString
chunk, ByteString
etc) -> do
Builder
b0 <- Builder -> ByteString -> Maybe Builder
go64 Builder
forall a. Monoid a => a
mempty ByteString
chunk
Builder -> ByteString -> Maybe Builder
go32 Builder
b0 ByteString
etc
| (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
10) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`rem` Int
16 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = case Int -> ByteString -> (ByteString, ByteString)
BS.splitAt (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
10) ByteString
bs of
(ByteString
chunk, ByteString
etc) -> do
Builder
b0 <- Builder -> ByteString -> Maybe Builder
go64 Builder
forall a. Monoid a => a
mempty ByteString
chunk
Builder
b1 <- Builder -> ByteString -> Maybe Builder
go32 Builder
b0 (Int -> ByteString -> ByteString
BU.unsafeTake Int
8 ByteString
etc)
Builder -> ByteString -> Maybe Builder
go8 Builder
b1 (Int -> ByteString -> ByteString
BU.unsafeDrop Int
8 ByteString
etc)
| (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
12) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`rem` Int
16 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = case Int -> ByteString -> (ByteString, ByteString)
BS.splitAt (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
12) ByteString
bs of
(ByteString
chunk, ByteString
etc) -> do
Builder
b0 <- Builder -> ByteString -> Maybe Builder
go64 Builder
forall a. Monoid a => a
mempty ByteString
chunk
Builder
b1 <- Builder -> ByteString -> Maybe Builder
go32 Builder
b0 (Int -> ByteString -> ByteString
BU.unsafeTake Int
8 ByteString
etc)
Builder -> ByteString -> Maybe Builder
go16 Builder
b1 (Int -> ByteString -> ByteString
BU.unsafeDrop Int
8 ByteString
etc)
| (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
14) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`rem` Int
16 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = case Int -> ByteString -> (ByteString, ByteString)
BS.splitAt (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
14) ByteString
bs of
(ByteString
chunk, ByteString
etc) -> do
Builder
b0 <- Builder -> ByteString -> Maybe Builder
go64 Builder
forall a. Monoid a => a
mempty ByteString
chunk
Builder
b1 <- Builder -> ByteString -> Maybe Builder
go32 Builder
b0 (Int -> ByteString -> ByteString
BU.unsafeTake Int
8 ByteString
etc)
Builder
b2 <- Builder -> ByteString -> Maybe Builder
go16 Builder
b1 (Int -> ByteString -> ByteString
BU.unsafeTake Int
4 (Int -> ByteString -> ByteString
BU.unsafeDrop Int
8 ByteString
etc))
Builder -> ByteString -> Maybe Builder
go8 Builder
b2 (Int -> ByteString -> ByteString
BU.unsafeDrop Int
12 ByteString
etc)
| Int
l Int -> Int -> Int
forall a. Integral a => a -> a -> a
`rem` Int
8 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 =
Builder -> ByteString -> Maybe Builder
go32 Builder
forall a. Monoid a => a
mempty ByteString
bs
| (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`rem` Int
8 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = case Int -> ByteString -> (ByteString, ByteString)
BS.splitAt (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2) ByteString
bs of
(ByteString
chunk, ByteString
etc) -> do
Builder
b0 <- Builder -> ByteString -> Maybe Builder
go32 Builder
forall a. Monoid a => a
mempty ByteString
chunk
Builder -> ByteString -> Maybe Builder
go8 Builder
b0 ByteString
etc
| (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
4) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`rem` Int
8 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = case Int -> ByteString -> (ByteString, ByteString)
BS.splitAt (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
4) ByteString
bs of
(ByteString
chunk, ByteString
etc) -> do
Builder
b0 <- Builder -> ByteString -> Maybe Builder
go32 Builder
forall a. Monoid a => a
mempty ByteString
chunk
Builder -> ByteString -> Maybe Builder
go16 Builder
b0 ByteString
etc
| (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
6) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`rem` Int
8 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = case Int -> ByteString -> (ByteString, ByteString)
BS.splitAt (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
6) ByteString
bs of
(ByteString
chunk, ByteString
etc) -> do
Builder
b0 <- Builder -> ByteString -> Maybe Builder
go32 Builder
forall a. Monoid a => a
mempty ByteString
chunk
Builder
b1 <- Builder -> ByteString -> Maybe Builder
go16 Builder
b0 (Int -> ByteString -> ByteString
BU.unsafeTake Int
4 ByteString
etc)
Builder -> ByteString -> Maybe Builder
go8 Builder
b1 (Int -> ByteString -> ByteString
BU.unsafeDrop Int
4 ByteString
etc)
| Int
l 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 =
Builder -> ByteString -> Maybe Builder
go16 Builder
forall a. Monoid a => a
mempty ByteString
bs
| (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2) 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 = case Int -> ByteString -> (ByteString, ByteString)
BS.splitAt (Int
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
2) ByteString
bs of
(ByteString
chunk, ByteString
etc) -> do
Builder
b0 <- Builder -> ByteString -> Maybe Builder
go16 Builder
forall a. Monoid a => a
mempty ByteString
chunk
Builder -> ByteString -> Maybe Builder
go8 Builder
b0 ByteString
etc
| Bool
otherwise =
Builder -> ByteString -> Maybe Builder
go8 Builder
forall a. Monoid a => a
mempty ByteString
bs
go64 :: Builder -> ByteString -> Maybe Builder
go64 Builder
acc ByteString
b = case Int -> ByteString -> (ByteString, ByteString)
BS.splitAt Int
16 ByteString
b of
(ByteString
chunk, ByteString
etc)
| ByteString -> Bool
BS.null ByteString
chunk -> Builder -> Maybe Builder
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Builder
acc
| Bool
otherwise -> do
!Word8
w4_00 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
00)
!Word8
w4_01 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
01)
!Word8
w4_02 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
02)
!Word8
w4_03 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
03)
!Word8
w4_04 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
04)
!Word8
w4_05 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
05)
!Word8
w4_06 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
06)
!Word8
w4_07 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
07)
!Word8
w4_08 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
08)
!Word8
w4_09 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
09)
!Word8
w4_10 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
10)
!Word8
w4_11 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
11)
!Word8
w4_12 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
12)
!Word8
w4_13 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
13)
!Word8
w4_14 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
14)
!Word8
w4_15 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
15)
let !w64 :: Word64
w64 = Word8 -> Word64
forall a b. (Num a, Integral b) => b -> a
fi Word8
w4_00 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
60
Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Num a, Integral b) => b -> a
fi Word8
w4_01 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
56
Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Num a, Integral b) => b -> a
fi Word8
w4_02 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
52
Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Num a, Integral b) => b -> a
fi Word8
w4_03 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
48
Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Num a, Integral b) => b -> a
fi Word8
w4_04 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
44
Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Num a, Integral b) => b -> a
fi Word8
w4_05 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
40
Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Num a, Integral b) => b -> a
fi Word8
w4_06 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
36
Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Num a, Integral b) => b -> a
fi Word8
w4_07 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
32
Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Num a, Integral b) => b -> a
fi Word8
w4_08 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
28
Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Num a, Integral b) => b -> a
fi Word8
w4_09 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
24
Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Num a, Integral b) => b -> a
fi Word8
w4_10 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. (Num a, Integral b) => b -> a
fi Word8
w4_11 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
16
Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Num a, Integral b) => b -> a
fi Word8
w4_12 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
12
Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Num a, Integral b) => b -> a
fi Word8
w4_13 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
08
Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Num a, Integral b) => b -> a
fi Word8
w4_14 Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
04
Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Num a, Integral b) => b -> a
fi Word8
w4_15
Builder -> ByteString -> Maybe Builder
go64 (Builder
acc Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Word64 -> Builder
BSB.word64BE Word64
w64) ByteString
etc
go32 :: Builder -> ByteString -> Maybe Builder
go32 Builder
acc ByteString
b = case Int -> ByteString -> (ByteString, ByteString)
BS.splitAt Int
8 ByteString
b of
(ByteString
chunk, ByteString
etc)
| ByteString -> Bool
BS.null ByteString
chunk -> Builder -> Maybe Builder
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Builder
acc
| Bool
otherwise -> do
!Word8
w4_00 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
00)
!Word8
w4_01 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
01)
!Word8
w4_02 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
02)
!Word8
w4_03 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
03)
!Word8
w4_04 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
04)
!Word8
w4_05 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
05)
!Word8
w4_06 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
06)
!Word8
w4_07 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
07)
let !w32 :: Word32
w32 = Word8 -> Word32
forall a b. (Num a, Integral b) => b -> a
fi Word8
w4_00 Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
28
Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. Word8 -> Word32
forall a b. (Num a, Integral b) => b -> a
fi Word8
w4_01 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. (Num a, Integral b) => b -> a
fi Word8
w4_02 Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
20
Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. Word8 -> Word32
forall a b. (Num a, Integral b) => b -> a
fi Word8
w4_03 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. (Num a, Integral b) => b -> a
fi Word8
w4_04 Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
12
Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. Word8 -> Word32
forall a b. (Num a, Integral b) => b -> a
fi Word8
w4_05 Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
08
Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. Word8 -> Word32
forall a b. (Num a, Integral b) => b -> a
fi Word8
w4_06 Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
04
Word32 -> Word32 -> Word32
forall a. Bits a => a -> a -> a
.|. Word8 -> Word32
forall a b. (Num a, Integral b) => b -> a
fi Word8
w4_07
Builder -> ByteString -> Maybe Builder
go32 (Builder
acc Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Word32 -> Builder
BSB.word32BE Word32
w32) ByteString
etc
go16 :: Builder -> ByteString -> Maybe Builder
go16 Builder
acc ByteString
b = case Int -> ByteString -> (ByteString, ByteString)
BS.splitAt Int
4 ByteString
b of
(ByteString
chunk, ByteString
etc)
| ByteString -> Bool
BS.null ByteString
chunk -> Builder -> Maybe Builder
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Builder
acc
| Bool
otherwise -> do
!Word8
w4_00 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
00)
!Word8
w4_01 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
01)
!Word8
w4_02 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
02)
!Word8
w4_03 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
03)
let !w16 :: Word16
w16 = Word8 -> Word16
forall a b. (Num a, Integral b) => b -> a
fi Word8
w4_00 Word16 -> Int -> Word16
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
12
Word16 -> Word16 -> Word16
forall a. Bits a => a -> a -> a
.|. Word8 -> Word16
forall a b. (Num a, Integral b) => b -> a
fi Word8
w4_01 Word16 -> Int -> Word16
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
08
Word16 -> Word16 -> Word16
forall a. Bits a => a -> a -> a
.|. Word8 -> Word16
forall a b. (Num a, Integral b) => b -> a
fi Word8
w4_02 Word16 -> Int -> Word16
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
04
Word16 -> Word16 -> Word16
forall a. Bits a => a -> a -> a
.|. Word8 -> Word16
forall a b. (Num a, Integral b) => b -> a
fi Word8
w4_03
Builder -> ByteString -> Maybe Builder
go16 (Builder
acc Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Word16 -> Builder
BSB.word16BE Word16
w16) ByteString
etc
go8 :: Builder -> ByteString -> Maybe Builder
go8 Builder
acc ByteString
b = case Int -> ByteString -> (ByteString, ByteString)
BS.splitAt Int
2 ByteString
b of
(ByteString
chunk, ByteString
etc)
| ByteString -> Bool
BS.null ByteString
chunk -> Builder -> Maybe Builder
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Builder
acc
| Bool
otherwise -> do
!Word8
w4_00 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
00)
!Word8
w4_01 <- Word8 -> Maybe Word8
word4 (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
chunk Int
01)
let !w8 :: Word8
w8 = Word8 -> Word8
forall a b. (Num a, Integral b) => b -> a
fi Word8
w4_00 Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
`B.shiftL` Int
04
Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. Word8 -> Word8
forall a b. (Num a, Integral b) => b -> a
fi Word8
w4_01
Builder -> ByteString -> Maybe Builder
go8 (Builder
acc Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Word8 -> Builder
BSB.word8 Word8
w8) ByteString
etc