{-# OPTIONS_GHC -fno-warn-orphans #-}
{-# OPTIONS_GHC -fno-warn-unused-top-binds #-}

module Unison.Util.Bytes
  ( Bytes (..),
    Chunk,
    fromByteString,
    toByteString,
    fromWord8s,
    toWord8s,
    fromBase16,
    toBase16,
    fromBase32,
    toBase32,
    fromBase64,
    toBase64,
    fromBase64UrlUnpadded,
    toBase64UrlUnpadded,
    chunkFromByteString,
    byteStringToChunk,
    chunkToByteString,
    fromChunks,
    chunks,
    byteStringChunks,
    toArray,
    fromArray,
    toLazyByteString,
    flatten,
    at,
    take,
    drop,
    indexOf,
    size,
    empty,
    encodeNat16be,
    decodeNat16be,
    encodeNat32be,
    decodeNat32be,
    encodeNat64be,
    decodeNat64be,
    encodeNat16le,
    decodeNat16le,
    encodeNat32le,
    decodeNat32le,
    encodeNat64le,
    decodeNat64le,
    decodeUtf8,
    encodeUtf8,
    zlibCompress,
    zlibDecompress,
    gzipCompress,
    gzipDecompress,
  )
where

import Basement.Block.Mutable (Block (Block))
import Codec.Compression.GZip qualified as GZip
import Codec.Compression.Zlib qualified as Zlib
import Control.DeepSeq (NFData (..))
import Control.Monad.Primitive (unsafeIOToPrim)
import Data.Bits (shiftL, shiftR, (.|.))
import Data.ByteArray qualified as BA
import Data.ByteArray.Encoding qualified as BE
import Data.ByteString qualified as B
import Data.ByteString.Lazy qualified as LB
import Data.ByteString.Lazy.Search qualified as SS
import Data.Char
import Data.Primitive.ByteArray
  ( ByteArray (ByteArray),
    copyByteArrayToPtr,
  )
import Data.Primitive.Ptr (copyPtrToMutableByteArray)
import Data.Text qualified as Text
import Data.Vector.Primitive qualified as V
import Data.Vector.Primitive.Mutable qualified as MV
import Data.Vector.Storable qualified as SV
import Data.Vector.Storable.ByteString qualified as BSV
import Data.Vector.Storable.Mutable qualified as MSV
import Foreign.ForeignPtr (withForeignPtr)
import Foreign.Storable (pokeByteOff)
import Unison.Prelude hiding (ByteString, empty)
import Unison.Util.Rope qualified as R
import Unsafe.Coerce (unsafeCoerce)
import Prelude hiding (drop, take)

type Chunk = V.Vector Word8

-- Bytes type represented as a rope of ByteStrings
newtype Bytes = Bytes {Bytes -> Rope Chunk
underlying :: R.Rope Chunk}
  deriving stock (Bytes -> Bytes -> Bool
(Bytes -> Bytes -> Bool) -> (Bytes -> Bytes -> Bool) -> Eq Bytes
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Bytes -> Bytes -> Bool
== :: Bytes -> Bytes -> Bool
$c/= :: Bytes -> Bytes -> Bool
/= :: Bytes -> Bytes -> Bool
Eq, Eq Bytes
Eq Bytes =>
(Bytes -> Bytes -> Ordering)
-> (Bytes -> Bytes -> Bool)
-> (Bytes -> Bytes -> Bool)
-> (Bytes -> Bytes -> Bool)
-> (Bytes -> Bytes -> Bool)
-> (Bytes -> Bytes -> Bytes)
-> (Bytes -> Bytes -> Bytes)
-> Ord Bytes
Bytes -> Bytes -> Bool
Bytes -> Bytes -> Ordering
Bytes -> Bytes -> Bytes
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Bytes -> Bytes -> Ordering
compare :: Bytes -> Bytes -> Ordering
$c< :: Bytes -> Bytes -> Bool
< :: Bytes -> Bytes -> Bool
$c<= :: Bytes -> Bytes -> Bool
<= :: Bytes -> Bytes -> Bool
$c> :: Bytes -> Bytes -> Bool
> :: Bytes -> Bytes -> Bool
$c>= :: Bytes -> Bytes -> Bool
>= :: Bytes -> Bytes -> Bool
$cmax :: Bytes -> Bytes -> Bytes
max :: Bytes -> Bytes -> Bytes
$cmin :: Bytes -> Bytes -> Bytes
min :: Bytes -> Bytes -> Bytes
Ord)
  deriving newtype (NonEmpty Bytes -> Bytes
Bytes -> Bytes -> Bytes
(Bytes -> Bytes -> Bytes)
-> (NonEmpty Bytes -> Bytes)
-> (forall b. Integral b => b -> Bytes -> Bytes)
-> Semigroup Bytes
forall b. Integral b => b -> Bytes -> Bytes
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
$c<> :: Bytes -> Bytes -> Bytes
<> :: Bytes -> Bytes -> Bytes
$csconcat :: NonEmpty Bytes -> Bytes
sconcat :: NonEmpty Bytes -> Bytes
$cstimes :: forall b. Integral b => b -> Bytes -> Bytes
stimes :: forall b. Integral b => b -> Bytes -> Bytes
Semigroup, Semigroup Bytes
Bytes
Semigroup Bytes =>
Bytes
-> (Bytes -> Bytes -> Bytes) -> ([Bytes] -> Bytes) -> Monoid Bytes
[Bytes] -> Bytes
Bytes -> Bytes -> Bytes
forall a.
Semigroup a =>
a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
$cmempty :: Bytes
mempty :: Bytes
$cmappend :: Bytes -> Bytes -> Bytes
mappend :: Bytes -> Bytes -> Bytes
$cmconcat :: [Bytes] -> Bytes
mconcat :: [Bytes] -> Bytes
Monoid)

instance R.Sized Chunk where size :: Chunk -> Int
size = Chunk -> Int
forall a. Prim a => Vector a -> Int
V.length

instance R.Drop Chunk where drop :: Int -> Chunk -> Chunk
drop = Int -> Chunk -> Chunk
forall a. Prim a => Int -> Vector a -> Vector a
V.drop

instance R.Take Chunk where take :: Int -> Chunk -> Chunk
take = Int -> Chunk -> Chunk
forall a. Prim a => Int -> Vector a -> Vector a
V.take

instance R.Index Chunk Word8 where unsafeIndex :: Int -> Chunk -> Word8
unsafeIndex Int
n Chunk
bs = Chunk
bs Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
`V.unsafeIndex` Int
n

instance R.Reverse Chunk where reverse :: Chunk -> Chunk
reverse = Chunk -> Chunk
forall a. Prim a => Vector a -> Vector a
V.reverse

instance NFData Bytes where rnf :: Bytes -> ()
rnf Bytes
_ = ()

null :: Bytes -> Bool
null :: Bytes -> Bool
null = Rope Chunk -> Bool
forall a. Sized a => Rope a -> Bool
R.null (Rope Chunk -> Bool) -> (Bytes -> Rope Chunk) -> Bytes -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bytes -> Rope Chunk
underlying

empty :: Bytes
empty :: Bytes
empty = Bytes
forall a. Monoid a => a
mempty

isAscii :: Bytes -> Bool
isAscii :: Bytes -> Bool
isAscii Bytes
b = (Chunk -> Bool) -> [Chunk] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all ((Word8 -> Bool) -> Chunk -> Bool
forall a. Prim a => (a -> Bool) -> Vector a -> Bool
V.all (Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
0x7F)) (Bytes -> [Chunk]
chunks Bytes
b)

fromByteString :: B.ByteString -> Bytes
fromByteString :: ByteString -> Bytes
fromByteString ByteString
b = Bytes -> Chunk -> Bytes
snoc Bytes
empty (ByteString -> Chunk
byteStringToChunk ByteString
b)

toByteString :: Bytes -> B.ByteString
toByteString :: Bytes -> ByteString
toByteString Bytes
b = [ByteString] -> ByteString
B.concat ((Chunk -> ByteString) -> [Chunk] -> [ByteString]
forall a b. (a -> b) -> [a] -> [b]
map Chunk -> ByteString
chunkToByteString (Bytes -> [Chunk]
chunks Bytes
b))

toArray :: (BA.ByteArray b) => Bytes -> b
toArray :: forall b. ByteArray b => Bytes -> b
toArray Bytes
b = Chunk -> b
forall b. ByteArray b => Chunk -> b
chunkToArray (Chunk -> b) -> Chunk -> b
forall a b. (a -> b) -> a -> b
$ [Chunk] -> Chunk
forall a. Prim a => [Vector a] -> Vector a
V.concat (Bytes -> [Chunk]
chunks Bytes
b)

fromArray :: (BA.ByteArrayAccess b) => b -> Bytes
fromArray :: forall b. ByteArrayAccess b => b -> Bytes
fromArray b
b = Bytes -> Chunk -> Bytes
snoc Bytes
empty (b -> Chunk
forall b. ByteArrayAccess b => b -> Chunk
arrayToChunk b
b)

byteStringToChunk, chunkFromByteString :: B.ByteString -> Chunk
byteStringToChunk :: ByteString -> Chunk
byteStringToChunk = Vector Word8 -> Chunk
fromStorable (Vector Word8 -> Chunk)
-> (ByteString -> Vector Word8) -> ByteString -> Chunk
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Vector Word8
forall a. Storable a => ByteString -> Vector a
BSV.byteStringToVector
chunkFromByteString :: ByteString -> Chunk
chunkFromByteString = ByteString -> Chunk
byteStringToChunk

chunkToByteString :: Chunk -> B.ByteString
chunkToByteString :: Chunk -> ByteString
chunkToByteString = Vector Word8 -> ByteString
forall a. Storable a => Vector a -> ByteString
BSV.vectorToByteString (Vector Word8 -> ByteString)
-> (Chunk -> Vector Word8) -> Chunk -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Chunk -> Vector Word8
toStorable

fromStorable :: SV.Vector Word8 -> V.Vector Word8
fromStorable :: Vector Word8 -> Chunk
fromStorable Vector Word8
sv =
  (forall s. ST s (MVector s Word8)) -> Chunk
forall a. Prim a => (forall s. ST s (MVector s a)) -> Vector a
V.create ((forall s. ST s (MVector s Word8)) -> Chunk)
-> (forall s. ST s (MVector s Word8)) -> Chunk
forall a b. (a -> b) -> a -> b
$ do
    MSV.MVector Int
l ForeignPtr Word8
fp <- Vector Word8 -> ST s (MVector (PrimState (ST s)) Word8)
forall a (m :: * -> *).
(Storable a, PrimMonad m) =>
Vector a -> m (MVector (PrimState m) a)
SV.unsafeThaw Vector Word8
sv
    v :: MVector s Word8
v@(MV.MVector Int
_ Int
_ MutableByteArray s
ba) <- Int -> ST s (MVector (PrimState (ST s)) Word8)
forall (m :: * -> *) a.
(PrimMonad m, Prim a) =>
Int -> m (MVector (PrimState m) a)
MV.unsafeNew Int
l
    IO () -> ST s ()
forall (m :: * -> *) a. PrimMonad m => IO a -> m a
unsafeIOToPrim (IO () -> ST s ())
-> ((Ptr Word8 -> IO ()) -> IO ())
-> (Ptr Word8 -> IO ())
-> ST s ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ForeignPtr Word8 -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
fp ((Ptr Word8 -> IO ()) -> ST s ())
-> (Ptr Word8 -> IO ()) -> ST s ()
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
p ->
      -- Note: unsafeCoerce is for s -> RealWorld in byte array type
      MutableByteArray (PrimState IO) -> Int -> Ptr Word8 -> Int -> IO ()
forall (m :: * -> *) a.
(PrimMonad m, Prim a) =>
MutableByteArray (PrimState m) -> Int -> Ptr a -> Int -> m ()
copyPtrToMutableByteArray (MutableByteArray s -> MutableByteArray RealWorld
forall a b. a -> b
unsafeCoerce MutableByteArray s
ba) Int
0 Ptr Word8
p Int
l
    pure MVector s Word8
v

toStorable :: V.Vector Word8 -> SV.Vector Word8
toStorable :: Chunk -> Vector Word8
toStorable (V.Vector Int
o Int
l ByteArray
ba) = (forall s. ST s (MVector s Word8)) -> Vector Word8
forall a. Storable a => (forall s. ST s (MVector s a)) -> Vector a
SV.create ((forall s. ST s (MVector s Word8)) -> Vector Word8)
-> (forall s. ST s (MVector s Word8)) -> Vector Word8
forall a b. (a -> b) -> a -> b
$ do
  v :: MVector s Word8
v@(MSV.MVector Int
_ ForeignPtr Word8
fp) <- Int -> ST s (MVector (PrimState (ST s)) Word8)
forall (m :: * -> *) a.
(PrimMonad m, Storable a) =>
Int -> m (MVector (PrimState m) a)
MSV.unsafeNew Int
l
  IO () -> ST s ()
forall (m :: * -> *) a. PrimMonad m => IO a -> m a
unsafeIOToPrim (IO () -> ST s ())
-> ((Ptr Word8 -> IO ()) -> IO ())
-> (Ptr Word8 -> IO ())
-> ST s ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ForeignPtr Word8 -> (Ptr Word8 -> IO ()) -> IO ()
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
fp ((Ptr Word8 -> IO ()) -> ST s ())
-> (Ptr Word8 -> IO ()) -> ST s ()
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
p ->
    Ptr Word8 -> ByteArray -> Int -> Int -> IO ()
forall (m :: * -> *) a.
(PrimMonad m, Prim a) =>
Ptr a -> ByteArray -> Int -> Int -> m ()
copyByteArrayToPtr Ptr Word8
p ByteArray
ba Int
o Int
l
  pure MVector s Word8
v

zlibCompress :: Bytes -> Bytes
zlibCompress :: Bytes -> Bytes
zlibCompress = ByteString -> Bytes
fromLazyByteString (ByteString -> Bytes) -> (Bytes -> ByteString) -> Bytes -> Bytes
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
Zlib.compress (ByteString -> ByteString)
-> (Bytes -> ByteString) -> Bytes -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bytes -> ByteString
toLazyByteString

gzipCompress :: Bytes -> Bytes
gzipCompress :: Bytes -> Bytes
gzipCompress = ByteString -> Bytes
fromLazyByteString (ByteString -> Bytes) -> (Bytes -> ByteString) -> Bytes -> Bytes
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
GZip.compress (ByteString -> ByteString)
-> (Bytes -> ByteString) -> Bytes -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bytes -> ByteString
toLazyByteString

gzipDecompress :: Bytes -> Bytes
gzipDecompress :: Bytes -> Bytes
gzipDecompress = ByteString -> Bytes
fromLazyByteString (ByteString -> Bytes) -> (Bytes -> ByteString) -> Bytes -> Bytes
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
GZip.decompress (ByteString -> ByteString)
-> (Bytes -> ByteString) -> Bytes -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bytes -> ByteString
toLazyByteString

zlibDecompress :: Bytes -> Bytes
zlibDecompress :: Bytes -> Bytes
zlibDecompress = ByteString -> Bytes
fromLazyByteString (ByteString -> Bytes) -> (Bytes -> ByteString) -> Bytes -> Bytes
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
Zlib.decompress (ByteString -> ByteString)
-> (Bytes -> ByteString) -> Bytes -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bytes -> ByteString
toLazyByteString

toLazyByteString :: Bytes -> LB.ByteString
toLazyByteString :: Bytes -> ByteString
toLazyByteString Bytes
b = [ByteString] -> ByteString
LB.fromChunks ([ByteString] -> ByteString) -> [ByteString] -> ByteString
forall a b. (a -> b) -> a -> b
$ (Chunk -> ByteString) -> [Chunk] -> [ByteString]
forall a b. (a -> b) -> [a] -> [b]
map Chunk -> ByteString
chunkToByteString ([Chunk] -> [ByteString]) -> [Chunk] -> [ByteString]
forall a b. (a -> b) -> a -> b
$ Bytes -> [Chunk]
chunks Bytes
b

fromLazyByteString :: LB.ByteString -> Bytes
fromLazyByteString :: ByteString -> Bytes
fromLazyByteString ByteString
b = [Chunk] -> Bytes
fromChunks (ByteString -> Chunk
byteStringToChunk (ByteString -> Chunk) -> [ByteString] -> [Chunk]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ByteString -> [ByteString]
LB.toChunks ByteString
b)

size :: Bytes -> Int
size :: Bytes -> Int
size = Rope Chunk -> Int
forall a. Sized a => a -> Int
R.size (Rope Chunk -> Int) -> (Bytes -> Rope Chunk) -> Bytes -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bytes -> Rope Chunk
underlying

chunkSize :: Chunk -> Int
chunkSize :: Chunk -> Int
chunkSize = Chunk -> Int
forall a. Prim a => Vector a -> Int
V.length

chunks :: Bytes -> [Chunk]
chunks :: Bytes -> [Chunk]
chunks (Bytes Rope Chunk
bs) = Rope Chunk -> [Chunk]
forall a. Rope a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList Rope Chunk
bs

byteStringChunks :: Bytes -> [B.ByteString]
byteStringChunks :: Bytes -> [ByteString]
byteStringChunks Bytes
bs = Chunk -> ByteString
chunkToByteString (Chunk -> ByteString) -> [Chunk] -> [ByteString]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Bytes -> [Chunk]
chunks Bytes
bs

fromChunks :: [Chunk] -> Bytes
fromChunks :: [Chunk] -> Bytes
fromChunks = (Bytes -> Chunk -> Bytes) -> Bytes -> [Chunk] -> Bytes
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Bytes -> Chunk -> Bytes
snoc Bytes
empty

cons :: Chunk -> Bytes -> Bytes
cons :: Chunk -> Bytes -> Bytes
cons Chunk
b (Bytes Rope Chunk
bs) = Rope Chunk -> Bytes
Bytes (Chunk -> Rope Chunk -> Rope Chunk
forall a. (Sized a, Semigroup a) => a -> Rope a -> Rope a
R.cons Chunk
b Rope Chunk
bs)

snoc :: Bytes -> Chunk -> Bytes
snoc :: Bytes -> Chunk -> Bytes
snoc (Bytes Rope Chunk
bs) Chunk
b = Rope Chunk -> Bytes
Bytes (Rope Chunk -> Chunk -> Rope Chunk
forall a. (Sized a, Semigroup a) => Rope a -> a -> Rope a
R.snoc Rope Chunk
bs Chunk
b)

flatten :: Bytes -> Bytes
flatten :: Bytes -> Bytes
flatten Bytes
b = Bytes -> Chunk -> Bytes
snoc Bytes
forall a. Monoid a => a
mempty ([Chunk] -> Chunk
forall a. Prim a => [Vector a] -> Vector a
V.concat (Bytes -> [Chunk]
chunks Bytes
b))

take :: Int -> Bytes -> Bytes
take :: Int -> Bytes -> Bytes
take Int
n (Bytes Rope Chunk
bs) = Rope Chunk -> Bytes
Bytes (Int -> Rope Chunk -> Rope Chunk
forall a. Take a => Int -> a -> a
R.take Int
n Rope Chunk
bs)

drop :: Int -> Bytes -> Bytes
drop :: Int -> Bytes -> Bytes
drop Int
n (Bytes Rope Chunk
bs) = Rope Chunk -> Bytes
Bytes (Int -> Rope Chunk -> Rope Chunk
forall a. Drop a => Int -> a -> a
R.drop Int
n Rope Chunk
bs)

indexOf :: Bytes -> Bytes -> Maybe Word64
indexOf :: Bytes -> Bytes -> Maybe Word64
indexOf Bytes
needle Bytes
haystack =
  case ByteString -> ByteString -> [Int64]
SS.indices ByteString
needle' ByteString
haystack' of
    [] -> Maybe Word64
forall a. Maybe a
Nothing
    (Int64
i : [Int64]
_) -> Word64 -> Maybe Word64
forall a. a -> Maybe a
Just (Int64 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
i)
  where
    needle' :: ByteString
needle' = Bytes -> ByteString
toByteString Bytes
needle
    haystack' :: ByteString
haystack' = Bytes -> ByteString
toLazyByteString Bytes
haystack

at, index :: Int -> Bytes -> Maybe Word8
at :: Int -> Bytes -> Maybe Word8
at Int
n (Bytes Rope Chunk
bs) = Int -> Rope Chunk -> Maybe Word8
forall a ch. (Sized a, Index a ch) => Int -> Rope a -> Maybe ch
R.index Int
n Rope Chunk
bs
index :: Int -> Bytes -> Maybe Word8
index = Int -> Bytes -> Maybe Word8
at

dropBlock :: Int -> Bytes -> Maybe (Chunk, Bytes)
dropBlock :: Int -> Bytes -> Maybe (Chunk, Bytes)
dropBlock Int
nBytes (Bytes Rope Chunk
chunks) = Chunk -> Rope Chunk -> Maybe (Chunk, Bytes)
go Chunk
forall a. Monoid a => a
mempty Rope Chunk
chunks
  where
    go :: Chunk -> Rope Chunk -> Maybe (Chunk, Bytes)
go Chunk
acc Rope Chunk
chunks
      | Chunk -> Int
forall a. Prim a => Vector a -> Int
V.length Chunk
acc Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
nBytes = (Chunk, Bytes) -> Maybe (Chunk, Bytes)
forall a. a -> Maybe a
Just (Chunk
acc, Rope Chunk -> Bytes
Bytes Rope Chunk
chunks)
      | Chunk -> Int
forall a. Prim a => Vector a -> Int
V.length Chunk
acc Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
nBytes, (Chunk
hd, Chunk
hd2) <- Int -> Chunk -> (Chunk, Chunk)
forall a. Prim a => Int -> Vector a -> (Vector a, Vector a)
V.splitAt Int
nBytes Chunk
acc = (Chunk, Bytes) -> Maybe (Chunk, Bytes)
forall a. a -> Maybe a
Just (Chunk
hd, Rope Chunk -> Bytes
Bytes (Chunk
hd2 Chunk -> Rope Chunk -> Rope Chunk
forall a. (Sized a, Semigroup a) => a -> Rope a -> Rope a
`R.cons` Rope Chunk
chunks))
      | Just (Chunk
head, Rope Chunk
tail) <- Rope Chunk -> Maybe (Chunk, Rope Chunk)
forall a. Sized a => Rope a -> Maybe (a, Rope a)
R.uncons Rope Chunk
chunks = Chunk -> Rope Chunk -> Maybe (Chunk, Bytes)
go (Chunk
acc Chunk -> Chunk -> Chunk
forall a. Semigroup a => a -> a -> a
<> Chunk
head) Rope Chunk
tail
      | Bool
otherwise = Maybe (Chunk, Bytes)
forall a. Maybe a
Nothing

decodeNat64be :: Bytes -> Maybe (Word64, Bytes)
decodeNat64be :: Bytes -> Maybe (Word64, Bytes)
decodeNat64be Bytes
bs = case Int -> Bytes -> Maybe (Chunk, Bytes)
dropBlock Int
8 Bytes
bs of
  Just (Chunk
head, Bytes
rest) ->
    let b8 :: Word8
b8 = Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
V.unsafeIndex Chunk
head Int
0
        b7 :: Word8
b7 = Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
V.unsafeIndex Chunk
head Int
1
        b6 :: Word8
b6 = Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
V.unsafeIndex Chunk
head Int
2
        b5 :: Word8
b5 = Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
V.unsafeIndex Chunk
head Int
3
        b4 :: Word8
b4 = Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
V.unsafeIndex Chunk
head Int
4
        b3 :: Word8
b3 = Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
V.unsafeIndex Chunk
head Int
5
        b2 :: Word8
b2 = Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
V.unsafeIndex Chunk
head Int
6
        b1 :: Word8
b1 = Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
V.unsafeIndex Chunk
head Int
7
        b :: Word64
b =
          Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
shiftL (Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b8) Int
56
            Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
shiftL (Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b7) Int
48
            Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
shiftL (Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b6) Int
40
            Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
shiftL (Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b5) Int
32
            Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
shiftL (Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b4) Int
24
            Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
shiftL (Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b3) Int
16
            Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
shiftL (Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b2) Int
8
            Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b1
     in (Word64, Bytes) -> Maybe (Word64, Bytes)
forall a. a -> Maybe a
Just (Word64
b, Bytes
rest)
  Maybe (Chunk, Bytes)
Nothing -> Maybe (Word64, Bytes)
forall a. Maybe a
Nothing

decodeNat64le :: Bytes -> Maybe (Word64, Bytes)
decodeNat64le :: Bytes -> Maybe (Word64, Bytes)
decodeNat64le Bytes
bs = case Int -> Bytes -> Maybe (Chunk, Bytes)
dropBlock Int
8 Bytes
bs of
  Just (Chunk
head, Bytes
rest) ->
    let b1 :: Word8
b1 = Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
V.unsafeIndex Chunk
head Int
0
        b2 :: Word8
b2 = Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
V.unsafeIndex Chunk
head Int
1
        b3 :: Word8
b3 = Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
V.unsafeIndex Chunk
head Int
2
        b4 :: Word8
b4 = Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
V.unsafeIndex Chunk
head Int
3
        b5 :: Word8
b5 = Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
V.unsafeIndex Chunk
head Int
4
        b6 :: Word8
b6 = Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
V.unsafeIndex Chunk
head Int
5
        b7 :: Word8
b7 = Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
V.unsafeIndex Chunk
head Int
6
        b8 :: Word8
b8 = Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
V.unsafeIndex Chunk
head Int
7
        b :: Word64
b =
          Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
shiftL (Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b8) Int
56
            Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
shiftL (Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b7) Int
48
            Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
shiftL (Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b6) Int
40
            Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
shiftL (Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b5) Int
32
            Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
shiftL (Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b4) Int
24
            Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
shiftL (Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b3) Int
16
            Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
shiftL (Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b2) Int
8
            Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b1
     in (Word64, Bytes) -> Maybe (Word64, Bytes)
forall a. a -> Maybe a
Just (Word64
b, Bytes
rest)
  Maybe (Chunk, Bytes)
Nothing -> Maybe (Word64, Bytes)
forall a. Maybe a
Nothing

decodeNat32be :: Bytes -> Maybe (Word64, Bytes)
decodeNat32be :: Bytes -> Maybe (Word64, Bytes)
decodeNat32be Bytes
bs = case Int -> Bytes -> Maybe (Chunk, Bytes)
dropBlock Int
4 Bytes
bs of
  Just (Chunk
head, Bytes
rest) ->
    let b4 :: Word8
b4 = Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
V.unsafeIndex Chunk
head Int
0
        b3 :: Word8
b3 = Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
V.unsafeIndex Chunk
head Int
1
        b2 :: Word8
b2 = Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
V.unsafeIndex Chunk
head Int
2
        b1 :: Word8
b1 = Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
V.unsafeIndex Chunk
head Int
3
        b :: Word64
b =
          Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
shiftL (Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b4) Int
24
            Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
shiftL (Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b3) Int
16
            Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
shiftL (Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b2) Int
8
            Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b1
     in (Word64, Bytes) -> Maybe (Word64, Bytes)
forall a. a -> Maybe a
Just (Word64
b, Bytes
rest)
  Maybe (Chunk, Bytes)
Nothing -> Maybe (Word64, Bytes)
forall a. Maybe a
Nothing

decodeNat32le :: Bytes -> Maybe (Word64, Bytes)
decodeNat32le :: Bytes -> Maybe (Word64, Bytes)
decodeNat32le Bytes
bs = case Int -> Bytes -> Maybe (Chunk, Bytes)
dropBlock Int
4 Bytes
bs of
  Just (Chunk
head, Bytes
rest) ->
    let b1 :: Word8
b1 = Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
V.unsafeIndex Chunk
head Int
0
        b2 :: Word8
b2 = Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
V.unsafeIndex Chunk
head Int
1
        b3 :: Word8
b3 = Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
V.unsafeIndex Chunk
head Int
2
        b4 :: Word8
b4 = Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
V.unsafeIndex Chunk
head Int
3
        b :: Word64
b =
          Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
shiftL (Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b4) Int
24
            Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
shiftL (Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b3) Int
16
            Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
shiftL (Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b2) Int
8
            Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b1
     in (Word64, Bytes) -> Maybe (Word64, Bytes)
forall a. a -> Maybe a
Just (Word64
b, Bytes
rest)
  Maybe (Chunk, Bytes)
Nothing -> Maybe (Word64, Bytes)
forall a. Maybe a
Nothing

decodeNat16be :: Bytes -> Maybe (Word64, Bytes)
decodeNat16be :: Bytes -> Maybe (Word64, Bytes)
decodeNat16be Bytes
bs = case Int -> Bytes -> Maybe (Chunk, Bytes)
dropBlock Int
2 Bytes
bs of
  Just (Chunk
head, Bytes
rest) ->
    let b2 :: Word8
b2 = Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
V.unsafeIndex Chunk
head Int
0
        b1 :: Word8
b1 = Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
V.unsafeIndex Chunk
head Int
1
        b :: Word64
b =
          Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
shiftL (Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b2) Int
8
            Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b1
     in (Word64, Bytes) -> Maybe (Word64, Bytes)
forall a. a -> Maybe a
Just (Word64
b, Bytes
rest)
  Maybe (Chunk, Bytes)
Nothing -> Maybe (Word64, Bytes)
forall a. Maybe a
Nothing

decodeNat16le :: Bytes -> Maybe (Word64, Bytes)
decodeNat16le :: Bytes -> Maybe (Word64, Bytes)
decodeNat16le Bytes
bs = case Int -> Bytes -> Maybe (Chunk, Bytes)
dropBlock Int
2 Bytes
bs of
  Just (Chunk
head, Bytes
rest) ->
    let b1 :: Word8
b1 = Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
V.unsafeIndex Chunk
head Int
0
        b2 :: Word8
b2 = Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
V.unsafeIndex Chunk
head Int
1
        b :: Word64
b =
          Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
shiftL (Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b2) Int
8
            Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word8 -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b1
     in (Word64, Bytes) -> Maybe (Word64, Bytes)
forall a. a -> Maybe a
Just (Word64
b, Bytes
rest)
  Maybe (Chunk, Bytes)
Nothing -> Maybe (Word64, Bytes)
forall a. Maybe a
Nothing

fillBE :: Word64 -> Int -> Int -> Word8
fillBE :: Word64 -> Int -> Int -> Word8
fillBE Word64
n Int
k Int
0 = Word64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
shiftR Word64
n (Int
k Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
8))
fillBE Word64
n Int
k Int
i = Word64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
shiftR Word64
n ((Int
k Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
i) Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
8))
{-# INLINE fillBE #-}

encodeNat64be :: Word64 -> Bytes
encodeNat64be :: Word64 -> Bytes
encodeNat64be Word64
n = Rope Chunk -> Bytes
Bytes (Chunk -> Rope Chunk
forall a. Sized a => a -> Rope a
R.one (Int -> (Int -> Word8) -> Chunk
forall a. Prim a => Int -> (Int -> a) -> Vector a
V.generate Int
8 (Word64 -> Int -> Int -> Word8
fillBE Word64
n Int
7)))

encodeNat32be :: Word64 -> Bytes
encodeNat32be :: Word64 -> Bytes
encodeNat32be Word64
n = Rope Chunk -> Bytes
Bytes (Chunk -> Rope Chunk
forall a. Sized a => a -> Rope a
R.one (Int -> (Int -> Word8) -> Chunk
forall a. Prim a => Int -> (Int -> a) -> Vector a
V.generate Int
4 (Word64 -> Int -> Int -> Word8
fillBE Word64
n Int
3)))

encodeNat16be :: Word64 -> Bytes
encodeNat16be :: Word64 -> Bytes
encodeNat16be Word64
n = Rope Chunk -> Bytes
Bytes (Chunk -> Rope Chunk
forall a. Sized a => a -> Rope a
R.one (Int -> (Int -> Word8) -> Chunk
forall a. Prim a => Int -> (Int -> a) -> Vector a
V.generate Int
2 (Word64 -> Int -> Int -> Word8
fillBE Word64
n Int
1)))

fillLE :: Word64 -> Int -> Word8
fillLE :: Word64 -> Int -> Word8
fillLE Word64
n Int
i = Word64 -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
shiftR Word64
n (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
8))
{-# INLINE fillLE #-}

encodeNat64le :: Word64 -> Bytes
encodeNat64le :: Word64 -> Bytes
encodeNat64le Word64
n = Rope Chunk -> Bytes
Bytes (Chunk -> Rope Chunk
forall a. Sized a => a -> Rope a
R.one (Int -> (Int -> Word8) -> Chunk
forall a. Prim a => Int -> (Int -> a) -> Vector a
V.generate Int
8 (Word64 -> Int -> Word8
fillLE Word64
n)))

encodeNat32le :: Word64 -> Bytes
encodeNat32le :: Word64 -> Bytes
encodeNat32le Word64
n = Rope Chunk -> Bytes
Bytes (Chunk -> Rope Chunk
forall a. Sized a => a -> Rope a
R.one (Int -> (Int -> Word8) -> Chunk
forall a. Prim a => Int -> (Int -> a) -> Vector a
V.generate Int
4 (Word64 -> Int -> Word8
fillLE Word64
n)))

encodeNat16le :: Word64 -> Bytes
encodeNat16le :: Word64 -> Bytes
encodeNat16le Word64
n = Rope Chunk -> Bytes
Bytes (Chunk -> Rope Chunk
forall a. Sized a => a -> Rope a
R.one (Int -> (Int -> Word8) -> Chunk
forall a. Prim a => Int -> (Int -> a) -> Vector a
V.generate Int
2 (Word64 -> Int -> Word8
fillLE Word64
n)))

toBase16 :: Bytes -> Bytes
toBase16 :: Bytes -> Bytes
toBase16 Bytes
bs = (Bytes -> Chunk -> Bytes) -> Bytes -> [Chunk] -> Bytes
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Bytes -> Chunk -> Bytes
step Bytes
empty (Bytes -> [Chunk]
chunks Bytes
bs)
  where
    step :: Bytes -> Chunk -> Bytes
step Bytes
bs Chunk
b =
      Bytes -> Chunk -> Bytes
snoc
        Bytes
bs
        ( forall b. ByteArrayAccess b => b -> Chunk
arrayToChunk @BA.Bytes (Bytes -> Chunk) -> Bytes -> Chunk
forall a b. (a -> b) -> a -> b
$
            Base -> Bytes -> Bytes
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
Base -> bin -> bout
BE.convertToBase Base
BE.Base16 (forall b. ByteArray b => Chunk -> b
chunkToArray @BA.Bytes Chunk
b)
        )

chunkToArray, arrayFromChunk :: (BA.ByteArray b) => Chunk -> b
chunkToArray :: forall b. ByteArray b => Chunk -> b
chunkToArray Chunk
bs = Int -> (Ptr Any -> IO ()) -> b
forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
BA.allocAndFreeze (Chunk -> Int
forall a. Prim a => Vector a -> Int
V.length Chunk
bs) ((Ptr Any -> IO ()) -> b) -> (Ptr Any -> IO ()) -> b
forall a b. (a -> b) -> a -> b
$ \Ptr Any
ptr ->
  let go :: Int -> IO ()
go !Int
ind =
        if Int
ind Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Chunk -> Int
forall a. Prim a => Vector a -> Int
V.length Chunk
bs
          then Ptr Any -> Int -> Word8 -> IO ()
forall b. Ptr b -> Int -> Word8 -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
pokeByteOff Ptr Any
ptr Int
ind (Chunk -> Int -> Word8
forall a. Prim a => Vector a -> Int -> a
V.unsafeIndex Chunk
bs Int
ind) IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Int -> IO ()
go (Int
ind Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
          else () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
   in Int -> IO ()
go Int
0
arrayFromChunk :: forall b. ByteArray b => Chunk -> b
arrayFromChunk = Chunk -> b
forall b. ByteArray b => Chunk -> b
chunkToArray

arrayToChunk, chunkFromArray :: (BA.ByteArrayAccess b) => b -> Chunk
arrayToChunk :: forall b. ByteArrayAccess b => b -> Chunk
arrayToChunk b
bs = case b -> Block Word8
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
BA.convert b
bs :: Block Word8 of
  Block ByteArray#
bs -> Int -> Int -> ByteArray -> Chunk
forall a. Int -> Int -> ByteArray -> Vector a
V.Vector Int
0 Int
n (ByteArray# -> ByteArray
ByteArray ByteArray#
bs)
  where
    n :: Int
n = b -> Int
forall ba. ByteArrayAccess ba => ba -> Int
BA.length b
bs
{-# INLINE arrayToChunk #-}
chunkFromArray :: forall b. ByteArrayAccess b => b -> Chunk
chunkFromArray = b -> Chunk
forall b. ByteArrayAccess b => b -> Chunk
arrayToChunk

fromBase16 :: Bytes -> Either Text.Text Bytes
fromBase16 :: Bytes -> Either Text Bytes
fromBase16 = Base -> Bytes -> Either Text Bytes
fromBase Base
BE.Base16

toBase32, toBase64, toBase64UrlUnpadded :: Bytes -> Bytes
toBase32 :: Bytes -> Bytes
toBase32 = Base -> Bytes -> Bytes
toBase Base
BE.Base32
toBase64 :: Bytes -> Bytes
toBase64 = Base -> Bytes -> Bytes
toBase Base
BE.Base64
toBase64UrlUnpadded :: Bytes -> Bytes
toBase64UrlUnpadded = Base -> Bytes -> Bytes
toBase Base
BE.Base64URLUnpadded

fromBase32, fromBase64, fromBase64UrlUnpadded :: Bytes -> Either Text.Text Bytes
fromBase32 :: Bytes -> Either Text Bytes
fromBase32 = Base -> Bytes -> Either Text Bytes
fromBase Base
BE.Base32
fromBase64 :: Bytes -> Either Text Bytes
fromBase64 = Base -> Bytes -> Either Text Bytes
fromBase Base
BE.Base64
fromBase64UrlUnpadded :: Bytes -> Either Text Bytes
fromBase64UrlUnpadded = Base -> Bytes -> Either Text Bytes
fromBase Base
BE.Base64URLUnpadded

fromBase :: BE.Base -> Bytes -> Either Text.Text Bytes
fromBase :: Base -> Bytes -> Either Text Bytes
fromBase Base
e (Bytes Rope Chunk
bs) = case Base -> Bytes -> Either String Bytes
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
Base -> bin -> Either String bout
BE.convertFromBase Base
e (forall b. ByteArray b => Chunk -> b
chunkToArray @BA.Bytes (Chunk -> Bytes) -> Chunk -> Bytes
forall a b. (a -> b) -> a -> b
$ Rope Chunk -> Chunk
forall a. Monoid a => Rope a -> a
R.flatten Rope Chunk
bs) of
  Left String
e -> Text -> Either Text Bytes
forall a b. a -> Either a b
Left (String -> Text
Text.pack String
e)
  Right Bytes
b -> Bytes -> Either Text Bytes
forall a b. b -> Either a b
Right (Bytes -> Either Text Bytes) -> Bytes -> Either Text Bytes
forall a b. (a -> b) -> a -> b
$ Bytes -> Chunk -> Bytes
snoc Bytes
empty (Bytes -> Chunk
forall b. ByteArrayAccess b => b -> Chunk
chunkFromArray (Bytes
b :: BA.Bytes))

toBase :: BE.Base -> Bytes -> Bytes
toBase :: Base -> Bytes -> Bytes
toBase Base
e (Bytes Rope Chunk
bs) = Bytes -> Chunk -> Bytes
snoc Bytes
empty (Bytes -> Chunk
forall b. ByteArrayAccess b => b -> Chunk
arrayToChunk Bytes
arr)
  where
    arr :: BA.Bytes
    arr :: Bytes
arr = Base -> Bytes -> Bytes
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
Base -> bin -> bout
BE.convertToBase Base
e (forall b. ByteArray b => Chunk -> b
chunkToArray @BA.Bytes (Chunk -> Bytes) -> Chunk -> Bytes
forall a b. (a -> b) -> a -> b
$ Rope Chunk -> Chunk
forall a. Monoid a => Rope a -> a
R.flatten Rope Chunk
bs)

toWord8s :: Bytes -> [Word8]
toWord8s :: Bytes -> [Word8]
toWord8s Bytes
bs = Bytes -> [Chunk]
chunks Bytes
bs [Chunk] -> (Chunk -> [Word8]) -> [Word8]
forall a b. [a] -> (a -> [b]) -> [b]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Chunk -> [Word8]
forall a. Prim a => Vector a -> [a]
V.toList

fromWord8s :: [Word8] -> Bytes
fromWord8s :: [Word8] -> Bytes
fromWord8s [Word8]
bs = Bytes -> Chunk -> Bytes
snoc Bytes
empty ([Word8] -> Chunk
forall a. Prim a => [a] -> Vector a
V.fromList [Word8]
bs)

instance Show Bytes where
  show :: Bytes -> String
show Bytes
bs = Bytes -> [Word8]
toWord8s (Bytes -> Bytes
toBase16 Bytes
bs) [Word8] -> (Word8 -> String) -> String
forall a b. [a] -> (a -> [b]) -> [b]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Word8
w -> [Int -> Char
chr (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
w)]