module Text.Trifecta.Slice
( slice
, sliced
) where
import Control.Monad.Trans.Class
import Data.Semigroup
import Data.Interned
import Data.Foldable (toList)
import Data.FingerTree as FingerTree
import Data.ByteString as Strict
import Data.ByteString.Lazy as Lazy
import Text.Trifecta.Hunk
import Text.Trifecta.Bytes
import Text.Trifecta.Rope as Rope
import Text.Trifecta.Delta
import Text.Trifecta.Strand
import Text.Trifecta.It
import Text.Parsec.Prim hiding ((<|>))
slice :: Delta -> Delta -> P u Strict.ByteString
slice !i !j = lift (Cont loop)
where
bi = bytes i
bj = bytes j
loop t eof
| bj <= bytes t || eof = Done t eof $ go $ strands t
| otherwise = Cont $ \t' eof' -> loop (t <> t') eof'
go !t
| required <= Strict.length first = Strict.take required first
| otherwise = Strict.concat
$ Lazy.toChunks
$ Lazy.take (fromIntegral required)
$ Lazy.fromChunks
$ first : Prelude.foldr iter [] (toList r')
where
iter (HunkStrand h) b = unintern h : b
iter (PathStrand _) b = b
(l,r) = FingerTree.split (\m -> bytes m > bi) t
HunkStrand (Hunk _ _ a) :< r' = FingerTree.viewl r
first = Strict.drop (bi bytes l) a
required = bj bi
sliced :: (a -> Strict.ByteString -> r) -> P u a -> P u r
sliced f pa = do
mark <- getInput
a <- pa
release <- getInput
bs <- slice mark release
return $ f a bs