module Data.Text.Builder.Linear.Internal (
Buffer,
runBuffer,
runBufferBS,
dupBuffer,
consumeBuffer,
eraseBuffer,
byteSizeOfBuffer,
lengthOfBuffer,
dropBuffer,
takeBuffer,
newEmptyBuffer,
appendBounded,
appendExact,
prependBounded,
prependBounded',
appendBounded',
prependExact,
(><),
) where
import Data.ByteString.Internal (ByteString (..))
import Data.Text qualified as T
import Data.Text.Array qualified as A
import Data.Text.Internal (Text (..))
import GHC.Exts (Int (..), Levity (..), RuntimeRep (..), TYPE, byteArrayContents#, plusAddr#, unsafeCoerce#)
import GHC.ForeignPtr (ForeignPtr (..), ForeignPtrContents (..))
import GHC.ST (ST (..), runST)
import Data.Text.Builder.Linear.Array
data Buffer ∷ TYPE ('BoxedRep 'Unlifted) where
Buffer ∷ {-# UNPACK #-} !Text → Buffer
unBuffer ∷ Buffer ⊸ Text
unBuffer :: Buffer %1 -> Text
unBuffer (Buffer Text
x) = Text
x
runBuffer ∷ (Buffer ⊸ Buffer) ⊸ Text
runBuffer :: (Buffer %1 -> Buffer) %1 -> Text
runBuffer Buffer %1 -> Buffer
f = Buffer %1 -> Text
unBuffer (Buffer %1 -> Buffer
shrinkBuffer (Buffer %1 -> Buffer
f (Text -> Buffer
Buffer Text
forall a. Monoid a => a
mempty)))
{-# NOINLINE runBuffer #-}
runBufferBS ∷ (Buffer ⊸ Buffer) ⊸ ByteString
runBufferBS :: (Buffer %1 -> Buffer) %1 -> ByteString
runBufferBS Buffer %1 -> Buffer
f = case Buffer %1 -> Buffer
shrinkBuffer (Buffer %1 -> Buffer
f (Text -> Buffer
Buffer Text
memptyPinned)) of
Buffer (Text (A.ByteArray ByteArray#
arr) (I# Int#
from) Int
len) → ForeignPtr Word8 -> Int -> ByteString
BS ForeignPtr Word8
forall {a}. ForeignPtr a
fp Int
len
where
addr# :: Addr#
addr# = ByteArray# -> Addr#
byteArrayContents# ByteArray#
arr Addr# -> Int# -> Addr#
`plusAddr#` Int#
from
fp :: ForeignPtr a
fp = Addr# -> ForeignPtrContents -> ForeignPtr a
forall a. Addr# -> ForeignPtrContents -> ForeignPtr a
ForeignPtr Addr#
addr# (MutableByteArray# RealWorld -> ForeignPtrContents
PlainPtr (ByteArray# -> MutableByteArray# RealWorld
forall a b. a -> b
unsafeCoerce# ByteArray#
arr))
{-# NOINLINE runBufferBS #-}
shrinkBuffer ∷ Buffer ⊸ Buffer
shrinkBuffer :: Buffer %1 -> Buffer
shrinkBuffer (Buffer (Text Array
arr Int
from Int
len)) = Text -> Buffer
Buffer (Text -> Buffer) -> Text -> Buffer
forall a b. (a -> b) -> a -> b
$ (forall s. ST s Text) -> Text
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s Text) -> Text) -> (forall s. ST s Text) -> Text
forall a b. (a -> b) -> a -> b
$ do
MArray s
arrM ← Array -> ST s (MArray s)
forall s. Array -> ST s (MArray s)
unsafeThaw Array
arr
MArray s -> Int -> ST s ()
forall s. MArray s -> Int -> ST s ()
A.shrinkM MArray s
arrM (Int
from Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
len)
Array
arr' ← MArray s -> ST s Array
forall s. MArray s -> ST s Array
A.unsafeFreeze MArray s
arrM
Text -> ST s Text
forall a. a -> ST s a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> ST s Text) -> Text -> ST s Text
forall a b. (a -> b) -> a -> b
$ Array -> Int -> Int -> Text
Text Array
arr' Int
from Int
len
memptyPinned ∷ Text
memptyPinned :: Text
memptyPinned = (forall s. ST s Text) -> Text
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s Text) -> Text) -> (forall s. ST s Text) -> Text
forall a b. (a -> b) -> a -> b
$ do
MArray s
marr ← Int -> ST s (MArray s)
forall s. Int -> ST s (MArray s)
A.newPinned Int
0
Array
arr ← MArray s -> ST s Array
forall s. MArray s -> ST s Array
A.unsafeFreeze MArray s
marr
Text -> ST s Text
forall a. a -> ST s a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> ST s Text) -> Text -> ST s Text
forall a b. (a -> b) -> a -> b
$ Array -> Int -> Int -> Text
Text Array
arr Int
0 Int
0
newEmptyBuffer ∷ Buffer ⊸ (# Buffer, Buffer #)
newEmptyBuffer :: Buffer %1 -> (# Buffer, Buffer #)
newEmptyBuffer (Buffer t :: Text
t@(Text Array
arr Int
_ Int
_)) =
(# Text -> Buffer
Buffer Text
t, Text -> Buffer
Buffer (if Array -> Bool
isPinned Array
arr then Text
memptyPinned else Text
forall a. Monoid a => a
mempty) #)
dupBuffer ∷ Buffer ⊸ (# Buffer, Buffer #)
dupBuffer :: Buffer %1 -> (# Buffer, Buffer #)
dupBuffer (Buffer Text
x) = (# Text -> Buffer
Buffer Text
x, Text -> Buffer
Buffer (Text -> Text
T.copy Text
x) #)
consumeBuffer ∷ Buffer ⊸ ()
consumeBuffer :: Buffer %1 -> ()
consumeBuffer Buffer {} = ()
eraseBuffer ∷ Buffer ⊸ Buffer
eraseBuffer :: Buffer %1 -> Buffer
eraseBuffer (Buffer (Text Array
arr Int
_ Int
_)) =
Text -> Buffer
Buffer (if Array -> Bool
isPinned Array
arr then Text
memptyPinned else Text
forall a. Monoid a => a
mempty)
byteSizeOfBuffer ∷ Buffer ⊸ (# Buffer, Word #)
byteSizeOfBuffer :: Buffer %1 -> (# Buffer, Word #)
byteSizeOfBuffer (Buffer t :: Text
t@(Text Array
_ Int
_ Int
len)) = (# Text -> Buffer
Buffer Text
t, Int -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len #)
lengthOfBuffer ∷ Buffer ⊸ (# Buffer, Word #)
lengthOfBuffer :: Buffer %1 -> (# Buffer, Word #)
lengthOfBuffer (Buffer Text
t) = (# Text -> Buffer
Buffer Text
t, Int -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Text -> Int
T.length Text
t) #)
dropBuffer ∷ Word → Buffer ⊸ Buffer
dropBuffer :: Word -> Buffer %1 -> Buffer
dropBuffer Word
nChar (Buffer t :: Text
t@(Text Array
arr Int
off Int
len))
| Int
nByte Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 = Text -> Buffer
Buffer (Array -> Int -> Int -> Text
Text Array
arr (Int
off Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
len) Int
0)
| Bool
otherwise = Text -> Buffer
Buffer (Array -> Int -> Int -> Text
Text Array
arr (Int
off Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
nByte) (Int
len Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
nByte))
where
nByte :: Int
nByte = Int -> Text -> Int
T.measureOff (Word -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word
nChar) Text
t
takeBuffer ∷ Word → Buffer ⊸ Buffer
takeBuffer :: Word -> Buffer %1 -> Buffer
takeBuffer Word
nChar (Buffer t :: Text
t@(Text Array
arr Int
off Int
_))
| Int
nByte Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 = Text -> Buffer
Buffer Text
t
| Bool
otherwise = Text -> Buffer
Buffer (Array -> Int -> Int -> Text
Text Array
arr Int
off Int
nByte)
where
nByte :: Int
nByte = Int -> Text -> Int
T.measureOff (Word -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word
nChar) Text
t
appendBounded
∷ Int
→ (∀ s. A.MArray s → Int → ST s Int)
→ Buffer
⊸ Buffer
appendBounded :: Int
-> (forall s. MArray s -> Int -> ST s Int) -> Buffer %1 -> Buffer
appendBounded Int
maxSrcLen forall s. MArray s -> Int -> ST s Int
appender (Buffer (Text Array
dst Int
dstOff Int
dstLen)) = Text -> Buffer
Buffer (Text -> Buffer) -> Text -> Buffer
forall a b. (a -> b) -> a -> b
$ (forall s. ST s Text) -> Text
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s Text) -> Text) -> (forall s. ST s Text) -> Text
forall a b. (a -> b) -> a -> b
$ do
let dstFullLen :: Int
dstFullLen = Array -> Int
sizeofByteArray Array
dst
newFullLen :: Int
newFullLen = Int
dstOff Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* (Int
dstLen Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
maxSrcLen)
MArray s
newM ←
if Int
dstOff Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
dstLen Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
maxSrcLen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
dstFullLen
then Array -> ST s (MArray s)
forall s. Array -> ST s (MArray s)
unsafeThaw Array
dst
else do
MArray s
tmpM ← (if Array -> Bool
isPinned Array
dst then Int -> ST s (MArray s)
forall s. Int -> ST s (MArray s)
A.newPinned else Int -> ST s (MArray s)
forall s. Int -> ST s (MArray s)
A.new) Int
newFullLen
Int -> MArray s -> Int -> Array -> Int -> ST s ()
forall s. Int -> MArray s -> Int -> Array -> Int -> ST s ()
A.copyI Int
dstLen MArray s
tmpM Int
dstOff Array
dst Int
dstOff
MArray s -> ST s (MArray s)
forall a. a -> ST s a
forall (f :: * -> *) a. Applicative f => a -> f a
pure MArray s
tmpM
Int
srcLen ← MArray s -> Int -> ST s Int
forall s. MArray s -> Int -> ST s Int
appender MArray s
newM (Int
dstOff Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
dstLen)
Array
new ← MArray s -> ST s Array
forall s. MArray s -> ST s Array
A.unsafeFreeze MArray s
newM
Text -> ST s Text
forall a. a -> ST s a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> ST s Text) -> Text -> ST s Text
forall a b. (a -> b) -> a -> b
$ Array -> Int -> Int -> Text
Text Array
new Int
dstOff (Int
dstLen Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
srcLen)
{-# INLINE appendBounded #-}
appendBounded'
∷ Int
→ (∀ s x. ((A.MArray s → Int → ST s Int) → ST s x) → ((A.MArray s → Int → ST s Int) → ST s x) → ST s x)
→ Buffer
⊸ Buffer
appendBounded' :: Int
-> (forall s x.
((MArray s -> Int -> ST s Int) -> ST s x)
-> ((MArray s -> Int -> ST s Int) -> ST s x) -> ST s x)
-> Buffer
%1 -> Buffer
appendBounded' Int
maxSrcLen forall s x.
((MArray s -> Int -> ST s Int) -> ST s x)
-> ((MArray s -> Int -> ST s Int) -> ST s x) -> ST s x
writer (Buffer (Text Array
dst Int
dstOff Int
dstLen)) = Text -> Buffer
Buffer (Text -> Buffer) -> Text -> Buffer
forall a b. (a -> b) -> a -> b
$ (forall s. ST s Text) -> Text
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s Text) -> Text) -> (forall s. ST s Text) -> Text
forall a b. (a -> b) -> a -> b
$ do
let dstFullLen :: Int
dstFullLen = Array -> Int
sizeofByteArray Array
dst
newFullLen :: Int
newFullLen = Int
dstOff Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* (Int
dstLen Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
maxSrcLen)
MArray s
newM ←
if Int
dstOff Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
dstLen Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
maxSrcLen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
dstFullLen
then Array -> ST s (MArray s)
forall s. Array -> ST s (MArray s)
unsafeThaw Array
dst
else do
MArray s
tmpM ← (if Array -> Bool
isPinned Array
dst then Int -> ST s (MArray s)
forall s. Int -> ST s (MArray s)
A.newPinned else Int -> ST s (MArray s)
forall s. Int -> ST s (MArray s)
A.new) Int
newFullLen
Int -> MArray s -> Int -> Array -> Int -> ST s ()
forall s. Int -> MArray s -> Int -> Array -> Int -> ST s ()
A.copyI Int
dstLen MArray s
tmpM Int
dstOff Array
dst Int
dstOff
MArray s -> ST s (MArray s)
forall a. a -> ST s a
forall (f :: * -> *) a. Applicative f => a -> f a
pure MArray s
tmpM
let append :: (MArray s -> Int -> ST s b) -> ST s (Int, b)
append = \MArray s -> Int -> ST s b
appender → do
b
count ← MArray s -> Int -> ST s b
appender MArray s
newM (Int
dstOff Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
dstLen)
(Int, b) -> ST s (Int, b)
forall a. a -> ST s a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Int
dstOff, b
count)
let prepend :: (MArray s -> Int -> ST s Int) -> ST s (Int, Int)
prepend = \MArray s -> Int -> ST s Int
prepender → case Int
dstLen of
Int
0 → do
Int
count ← MArray s -> Int -> ST s Int
prepender MArray s
newM Int
maxSrcLen
(Int, Int) -> ST s (Int, Int)
forall a. a -> ST s a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Int
maxSrcLen Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
count, Int
count)
Int
_ → do
let off' :: Int
off'
| Int
dstOff Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
maxSrcLen = Int
dstOff
| Bool
otherwise = Int
dstOff Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
dstLen Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
maxSrcLen
Int
count ← MArray s -> Int -> ST s Int
prepender MArray s
newM Int
off'
MArray s -> Int -> MArray s -> Int -> Int -> ST s ()
forall s. MArray s -> Int -> MArray s -> Int -> Int -> ST s ()
A.copyM MArray s
newM (Int
dstOff Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
dstLen) MArray s
newM (Int
off' Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
count) Int
count
(Int, Int) -> ST s (Int, Int)
forall a. a -> ST s a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Int
dstOff, Int
count)
!(Int
dstOff', Int
srcLen) ← ((MArray s -> Int -> ST s Int) -> ST s (Int, Int))
-> ((MArray s -> Int -> ST s Int) -> ST s (Int, Int))
-> ST s (Int, Int)
forall s x.
((MArray s -> Int -> ST s Int) -> ST s x)
-> ((MArray s -> Int -> ST s Int) -> ST s x) -> ST s x
writer (MArray s -> Int -> ST s Int) -> ST s (Int, Int)
forall {b}. (MArray s -> Int -> ST s b) -> ST s (Int, b)
append (MArray s -> Int -> ST s Int) -> ST s (Int, Int)
prepend
Array
new ← MArray s -> ST s Array
forall s. MArray s -> ST s Array
A.unsafeFreeze MArray s
newM
Text -> ST s Text
forall a. a -> ST s a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> ST s Text) -> Text -> ST s Text
forall a b. (a -> b) -> a -> b
$ Array -> Int -> Int -> Text
Text Array
new Int
dstOff' (Int
dstLen Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
srcLen)
{-# INLINE appendBounded' #-}
appendExact
∷ Int
→ (∀ s. A.MArray s → Int → ST s ())
→ Buffer
⊸ Buffer
appendExact :: Int
-> (forall s. MArray s -> Int -> ST s ()) -> Buffer %1 -> Buffer
appendExact Int
srcLen forall s. MArray s -> Int -> ST s ()
appender =
Int
-> (forall s. MArray s -> Int -> ST s Int) -> Buffer %1 -> Buffer
appendBounded
Int
srcLen
(\MArray s
dst Int
dstOff → MArray s -> Int -> ST s ()
forall s. MArray s -> Int -> ST s ()
appender MArray s
dst Int
dstOff ST s () -> ST s Int -> ST s Int
forall a b. ST s a -> ST s b -> ST s b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Int -> ST s Int
forall a. a -> ST s a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Int
srcLen)
{-# INLINE appendExact #-}
prependBounded
∷ Int
→ (∀ s. A.MArray s → Int → ST s Int)
→ (∀ s. A.MArray s → Int → ST s Int)
→ Buffer
⊸ Buffer
prependBounded :: Int
-> (forall s. MArray s -> Int -> ST s Int)
-> (forall s. MArray s -> Int -> ST s Int)
-> Buffer
%1 -> Buffer
prependBounded Int
maxSrcLen forall s. MArray s -> Int -> ST s Int
prepender forall s. MArray s -> Int -> ST s Int
appender (Buffer (Text Array
dst Int
dstOff Int
dstLen))
| Int
maxSrcLen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
dstOff = Text -> Buffer
Buffer (Text -> Buffer) -> Text -> Buffer
forall a b. (a -> b) -> a -> b
$ (forall s. ST s Text) -> Text
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s Text) -> Text) -> (forall s. ST s Text) -> Text
forall a b. (a -> b) -> a -> b
$ do
MArray s
newM ← Array -> ST s (MArray s)
forall s. Array -> ST s (MArray s)
unsafeThaw Array
dst
Int
srcLen ← MArray s -> Int -> ST s Int
forall s. MArray s -> Int -> ST s Int
prepender MArray s
newM Int
dstOff
Array
new ← MArray s -> ST s Array
forall s. MArray s -> ST s Array
A.unsafeFreeze MArray s
newM
Text -> ST s Text
forall a. a -> ST s a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> ST s Text) -> Text -> ST s Text
forall a b. (a -> b) -> a -> b
$ Array -> Int -> Int -> Text
Text Array
new (Int
dstOff Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
srcLen) (Int
srcLen Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
dstLen)
| Bool
otherwise = Text -> Buffer
Buffer (Text -> Buffer) -> Text -> Buffer
forall a b. (a -> b) -> a -> b
$ (forall s. ST s Text) -> Text
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s Text) -> Text) -> (forall s. ST s Text) -> Text
forall a b. (a -> b) -> a -> b
$ do
let dstFullLen :: Int
dstFullLen = Array -> Int
sizeofByteArray Array
dst
newOff :: Int
newOff = Int
dstLen Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
maxSrcLen
newFullLen :: Int
newFullLen = Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
newOff Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Int
dstFullLen Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
dstOff Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
dstLen)
MArray s
newM ← (if Array -> Bool
isPinned Array
dst then Int -> ST s (MArray s)
forall s. Int -> ST s (MArray s)
A.newPinned else Int -> ST s (MArray s)
forall s. Int -> ST s (MArray s)
A.new) Int
newFullLen
Int
srcLen ← MArray s -> Int -> ST s Int
forall s. MArray s -> Int -> ST s Int
appender MArray s
newM Int
newOff
Int -> MArray s -> Int -> Array -> Int -> ST s ()
forall s. Int -> MArray s -> Int -> Array -> Int -> ST s ()
A.copyI Int
dstLen MArray s
newM (Int
newOff Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
srcLen) Array
dst Int
dstOff
Array
new ← MArray s -> ST s Array
forall s. MArray s -> ST s Array
A.unsafeFreeze MArray s
newM
Text -> ST s Text
forall a. a -> ST s a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> ST s Text) -> Text -> ST s Text
forall a b. (a -> b) -> a -> b
$ Array -> Int -> Int -> Text
Text Array
new Int
newOff (Int
dstLen Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
srcLen)
{-# INLINE prependBounded #-}
prependBounded'
∷ Int
→ (∀ s. A.MArray s → Int → ST s Int)
→ Buffer
⊸ Buffer
prependBounded' :: Int
-> (forall s. MArray s -> Int -> ST s Int) -> Buffer %1 -> Buffer
prependBounded' Int
maxSrcLen forall s. MArray s -> Int -> ST s Int
prepender (Buffer (Text Array
dst Int
dstOff Int
dstLen))
| Int
maxSrcLen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
dstOff = Text -> Buffer
Buffer (Text -> Buffer) -> Text -> Buffer
forall a b. (a -> b) -> a -> b
$ (forall s. ST s Text) -> Text
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s Text) -> Text) -> (forall s. ST s Text) -> Text
forall a b. (a -> b) -> a -> b
$ do
MArray s
newM ← Array -> ST s (MArray s)
forall s. Array -> ST s (MArray s)
unsafeThaw Array
dst
Int
srcLen ← MArray s -> Int -> ST s Int
forall s. MArray s -> Int -> ST s Int
prepender MArray s
newM Int
dstOff
Array
new ← MArray s -> ST s Array
forall s. MArray s -> ST s Array
A.unsafeFreeze MArray s
newM
Text -> ST s Text
forall a. a -> ST s a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> ST s Text) -> Text -> ST s Text
forall a b. (a -> b) -> a -> b
$ Array -> Int -> Int -> Text
Text Array
new (Int
dstOff Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
srcLen) (Int
srcLen Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
dstLen)
| Bool
otherwise = Text -> Buffer
Buffer (Text -> Buffer) -> Text -> Buffer
forall a b. (a -> b) -> a -> b
$ (forall s. ST s Text) -> Text
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s Text) -> Text) -> (forall s. ST s Text) -> Text
forall a b. (a -> b) -> a -> b
$ do
let dstFullLen :: Int
dstFullLen = Array -> Int
sizeofByteArray Array
dst
off :: Int
off = Int
dstLen Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
maxSrcLen
newFullLen :: Int
newFullLen = Int
off Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Int
dstFullLen Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
dstOff)
MArray s
newM ← (if Array -> Bool
isPinned Array
dst then Int -> ST s (MArray s)
forall s. Int -> ST s (MArray s)
A.newPinned else Int -> ST s (MArray s)
forall s. Int -> ST s (MArray s)
A.new) Int
newFullLen
Int
srcLen ← MArray s -> Int -> ST s Int
forall s. MArray s -> Int -> ST s Int
prepender MArray s
newM Int
off
Int -> MArray s -> Int -> Array -> Int -> ST s ()
forall s. Int -> MArray s -> Int -> Array -> Int -> ST s ()
A.copyI Int
dstLen MArray s
newM Int
off Array
dst Int
dstOff
Array
new ← MArray s -> ST s Array
forall s. MArray s -> ST s Array
A.unsafeFreeze MArray s
newM
Text -> ST s Text
forall a. a -> ST s a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> ST s Text) -> Text -> ST s Text
forall a b. (a -> b) -> a -> b
$ Array -> Int -> Int -> Text
Text Array
new (Int
off Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
srcLen) (Int
dstLen Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
srcLen)
{-# INLINE prependBounded' #-}
prependExact
∷ Int
→ (∀ s. A.MArray s → Int → ST s ())
→ Buffer
⊸ Buffer
prependExact :: Int
-> (forall s. MArray s -> Int -> ST s ()) -> Buffer %1 -> Buffer
prependExact Int
srcLen forall s. MArray s -> Int -> ST s ()
appender =
Int
-> (forall s. MArray s -> Int -> ST s Int)
-> (forall s. MArray s -> Int -> ST s Int)
-> Buffer
%1 -> Buffer
prependBounded
Int
srcLen
(\MArray s
dst Int
dstOff → MArray s -> Int -> ST s ()
forall s. MArray s -> Int -> ST s ()
appender MArray s
dst (Int
dstOff Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
srcLen) ST s () -> ST s Int -> ST s Int
forall a b. ST s a -> ST s b -> ST s b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Int -> ST s Int
forall a. a -> ST s a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Int
srcLen)
(\MArray s
dst Int
dstOff → MArray s -> Int -> ST s ()
forall s. MArray s -> Int -> ST s ()
appender MArray s
dst Int
dstOff ST s () -> ST s Int -> ST s Int
forall a b. ST s a -> ST s b -> ST s b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Int -> ST s Int
forall a. a -> ST s a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Int
srcLen)
{-# INLINE prependExact #-}
(><) ∷ Buffer ⊸ Buffer ⊸ Buffer
infix 6 ><
Buffer (Text Array
left Int
leftOff Int
leftLen) >< :: Buffer %1 -> Buffer %1 -> Buffer
>< Buffer (Text Array
right Int
rightOff Int
rightLen) = Text -> Buffer
Buffer (Text -> Buffer) -> Text -> Buffer
forall a b. (a -> b) -> a -> b
$ (forall s. ST s Text) -> Text
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s Text) -> Text) -> (forall s. ST s Text) -> Text
forall a b. (a -> b) -> a -> b
$ do
let leftFullLen :: Int
leftFullLen = Array -> Int
sizeofByteArray Array
left
rightFullLen :: Int
rightFullLen = Array -> Int
sizeofByteArray Array
right
canCopyToLeft :: Bool
canCopyToLeft = Int
leftOff Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
leftLen Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
rightLen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
leftFullLen
canCopyToRight :: Bool
canCopyToRight = Int
leftLen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
rightOff
shouldCopyToLeft :: Bool
shouldCopyToLeft = Bool
canCopyToLeft Bool -> Bool -> Bool
&& (Bool -> Bool
not Bool
canCopyToRight Bool -> Bool -> Bool
|| Int
leftLen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
rightLen)
if Bool
shouldCopyToLeft
then do
MArray s
newM ← Array -> ST s (MArray s)
forall s. Array -> ST s (MArray s)
unsafeThaw Array
left
Int -> MArray s -> Int -> Array -> Int -> ST s ()
forall s. Int -> MArray s -> Int -> Array -> Int -> ST s ()
A.copyI Int
rightLen MArray s
newM (Int
leftOff Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
leftLen) Array
right Int
rightOff
Array
new ← MArray s -> ST s Array
forall s. MArray s -> ST s Array
A.unsafeFreeze MArray s
newM
Text -> ST s Text
forall a. a -> ST s a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> ST s Text) -> Text -> ST s Text
forall a b. (a -> b) -> a -> b
$ Array -> Int -> Int -> Text
Text Array
new Int
leftOff (Int
leftLen Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
rightLen)
else
if Bool
canCopyToRight
then do
MArray s
newM ← Array -> ST s (MArray s)
forall s. Array -> ST s (MArray s)
unsafeThaw Array
right
Int -> MArray s -> Int -> Array -> Int -> ST s ()
forall s. Int -> MArray s -> Int -> Array -> Int -> ST s ()
A.copyI Int
leftLen MArray s
newM (Int
rightOff Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
leftLen) Array
left Int
leftOff
Array
new ← MArray s -> ST s Array
forall s. MArray s -> ST s Array
A.unsafeFreeze MArray s
newM
Text -> ST s Text
forall a. a -> ST s a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> ST s Text) -> Text -> ST s Text
forall a b. (a -> b) -> a -> b
$ Array -> Int -> Int -> Text
Text Array
new (Int
rightOff Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
leftLen) (Int
leftLen Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
rightLen)
else do
let fullLen :: Int
fullLen = Int
leftOff Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
leftLen Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
rightLen Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Int
rightFullLen Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
rightOff Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
rightLen)
MArray s
newM ← (if Array -> Bool
isPinned Array
left Bool -> Bool -> Bool
|| Array -> Bool
isPinned Array
right then Int -> ST s (MArray s)
forall s. Int -> ST s (MArray s)
A.newPinned else Int -> ST s (MArray s)
forall s. Int -> ST s (MArray s)
A.new) Int
fullLen
Int -> MArray s -> Int -> Array -> Int -> ST s ()
forall s. Int -> MArray s -> Int -> Array -> Int -> ST s ()
A.copyI Int
leftLen MArray s
newM Int
leftOff Array
left Int
leftOff
Int -> MArray s -> Int -> Array -> Int -> ST s ()
forall s. Int -> MArray s -> Int -> Array -> Int -> ST s ()
A.copyI Int
rightLen MArray s
newM (Int
leftOff Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
leftLen) Array
right Int
rightOff
Array
new ← MArray s -> ST s Array
forall s. MArray s -> ST s Array
A.unsafeFreeze MArray s
newM
Text -> ST s Text
forall a. a -> ST s a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> ST s Text) -> Text -> ST s Text
forall a b. (a -> b) -> a -> b
$ Array -> Int -> Int -> Text
Text Array
new Int
leftOff (Int
leftLen Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
rightLen)