module Text.ShellEscape.EscapeVector where import Data.ByteString.Char8 (ByteString) import qualified Data.ByteString.Char8 as ByteString import Data.Vector (Vector) import qualified Data.Vector as Vector import qualified Data.Vector.Mutable as Vector (new, write) import qualified Text.ShellEscape.Put as Put type EscapeVector escapingMode = Vector (Char, escapingMode) escWith :: (Char -> escapingMode) -> ByteString -> EscapeVector escapingMode escWith cf b = Vector.create $ do v <- Vector.new (ByteString.length b) sequence_ . snd $ ByteString.foldl' (f v) (0, []) b return v where f v (i, ops) c = (i + 1, Vector.write v i (c, cf c) : ops) stripEsc :: Vector (Char, escapingMode) -> ByteString stripEsc v = ByteString.unfoldr f . fst $ Vector.unzip v where f v | Vector.null v = Nothing | otherwise = Just (Vector.unsafeHead v, Vector.unsafeTail v) interpretEsc v f finish init = (eval . (finish lastMode :)) instructions where eval = Put.runPut' . sequence_ . reverse (instructions, lastMode) = Vector.foldl' f' init v where f' (list, mode) (c, e) = (put:list, mode') where (put, mode') = f mode (c, e)