module SimpleParser.CharString
  ( CharString (..)
  , LazyCharString (..)
  , toLazyCharString
  , toStrictCharString
  ) where

import Data.Bifunctor (second)
import Data.ByteString (ByteString)
import qualified Data.ByteString.Char8 as BSC
import qualified Data.ByteString.Lazy as BSL
import qualified Data.ByteString.Lazy.Char8 as BSLC
import Data.Coerce (coerce)
import Data.String (IsString)
import qualified Data.Text.Encoding as TE
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.Encoding as TLE
import SimpleParser.Chunked (Chunked (..), TextualChunked (..))
import SimpleParser.Stream (Stream (..))
import qualified Text.Builder as TB

newtype CharString = CharString
  { CharString -> ByteString
unCharString :: ByteString
  } deriving newtype (CharString -> CharString -> Bool
(CharString -> CharString -> Bool)
-> (CharString -> CharString -> Bool) -> Eq CharString
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CharString -> CharString -> Bool
$c/= :: CharString -> CharString -> Bool
== :: CharString -> CharString -> Bool
$c== :: CharString -> CharString -> Bool
Eq, Eq CharString
Eq CharString
-> (CharString -> CharString -> Ordering)
-> (CharString -> CharString -> Bool)
-> (CharString -> CharString -> Bool)
-> (CharString -> CharString -> Bool)
-> (CharString -> CharString -> Bool)
-> (CharString -> CharString -> CharString)
-> (CharString -> CharString -> CharString)
-> Ord CharString
CharString -> CharString -> Bool
CharString -> CharString -> Ordering
CharString -> CharString -> CharString
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
min :: CharString -> CharString -> CharString
$cmin :: CharString -> CharString -> CharString
max :: CharString -> CharString -> CharString
$cmax :: CharString -> CharString -> CharString
>= :: CharString -> CharString -> Bool
$c>= :: CharString -> CharString -> Bool
> :: CharString -> CharString -> Bool
$c> :: CharString -> CharString -> Bool
<= :: CharString -> CharString -> Bool
$c<= :: CharString -> CharString -> Bool
< :: CharString -> CharString -> Bool
$c< :: CharString -> CharString -> Bool
compare :: CharString -> CharString -> Ordering
$ccompare :: CharString -> CharString -> Ordering
$cp1Ord :: Eq CharString
Ord, Int -> CharString -> ShowS
[CharString] -> ShowS
CharString -> String
(Int -> CharString -> ShowS)
-> (CharString -> String)
-> ([CharString] -> ShowS)
-> Show CharString
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CharString] -> ShowS
$cshowList :: [CharString] -> ShowS
show :: CharString -> String
$cshow :: CharString -> String
showsPrec :: Int -> CharString -> ShowS
$cshowsPrec :: Int -> CharString -> ShowS
Show, b -> CharString -> CharString
NonEmpty CharString -> CharString
CharString -> CharString -> CharString
(CharString -> CharString -> CharString)
-> (NonEmpty CharString -> CharString)
-> (forall b. Integral b => b -> CharString -> CharString)
-> Semigroup CharString
forall b. Integral b => b -> CharString -> CharString
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
stimes :: b -> CharString -> CharString
$cstimes :: forall b. Integral b => b -> CharString -> CharString
sconcat :: NonEmpty CharString -> CharString
$csconcat :: NonEmpty CharString -> CharString
<> :: CharString -> CharString -> CharString
$c<> :: CharString -> CharString -> CharString
Semigroup, Semigroup CharString
CharString
Semigroup CharString
-> CharString
-> (CharString -> CharString -> CharString)
-> ([CharString] -> CharString)
-> Monoid CharString
[CharString] -> CharString
CharString -> CharString -> CharString
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
mconcat :: [CharString] -> CharString
$cmconcat :: [CharString] -> CharString
mappend :: CharString -> CharString -> CharString
$cmappend :: CharString -> CharString -> CharString
mempty :: CharString
$cmempty :: CharString
$cp1Monoid :: Semigroup CharString
Monoid, String -> CharString
(String -> CharString) -> IsString CharString
forall a. (String -> a) -> IsString a
fromString :: String -> CharString
$cfromString :: String -> CharString
IsString)

newtype LazyCharString = LazyCharString
  { LazyCharString -> ByteString
unLazyCharString :: BSL.ByteString
  } deriving newtype (LazyCharString -> LazyCharString -> Bool
(LazyCharString -> LazyCharString -> Bool)
-> (LazyCharString -> LazyCharString -> Bool) -> Eq LazyCharString
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: LazyCharString -> LazyCharString -> Bool
$c/= :: LazyCharString -> LazyCharString -> Bool
== :: LazyCharString -> LazyCharString -> Bool
$c== :: LazyCharString -> LazyCharString -> Bool
Eq, Eq LazyCharString
Eq LazyCharString
-> (LazyCharString -> LazyCharString -> Ordering)
-> (LazyCharString -> LazyCharString -> Bool)
-> (LazyCharString -> LazyCharString -> Bool)
-> (LazyCharString -> LazyCharString -> Bool)
-> (LazyCharString -> LazyCharString -> Bool)
-> (LazyCharString -> LazyCharString -> LazyCharString)
-> (LazyCharString -> LazyCharString -> LazyCharString)
-> Ord LazyCharString
LazyCharString -> LazyCharString -> Bool
LazyCharString -> LazyCharString -> Ordering
LazyCharString -> LazyCharString -> LazyCharString
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
min :: LazyCharString -> LazyCharString -> LazyCharString
$cmin :: LazyCharString -> LazyCharString -> LazyCharString
max :: LazyCharString -> LazyCharString -> LazyCharString
$cmax :: LazyCharString -> LazyCharString -> LazyCharString
>= :: LazyCharString -> LazyCharString -> Bool
$c>= :: LazyCharString -> LazyCharString -> Bool
> :: LazyCharString -> LazyCharString -> Bool
$c> :: LazyCharString -> LazyCharString -> Bool
<= :: LazyCharString -> LazyCharString -> Bool
$c<= :: LazyCharString -> LazyCharString -> Bool
< :: LazyCharString -> LazyCharString -> Bool
$c< :: LazyCharString -> LazyCharString -> Bool
compare :: LazyCharString -> LazyCharString -> Ordering
$ccompare :: LazyCharString -> LazyCharString -> Ordering
$cp1Ord :: Eq LazyCharString
Ord, Int -> LazyCharString -> ShowS
[LazyCharString] -> ShowS
LazyCharString -> String
(Int -> LazyCharString -> ShowS)
-> (LazyCharString -> String)
-> ([LazyCharString] -> ShowS)
-> Show LazyCharString
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [LazyCharString] -> ShowS
$cshowList :: [LazyCharString] -> ShowS
show :: LazyCharString -> String
$cshow :: LazyCharString -> String
showsPrec :: Int -> LazyCharString -> ShowS
$cshowsPrec :: Int -> LazyCharString -> ShowS
Show, b -> LazyCharString -> LazyCharString
NonEmpty LazyCharString -> LazyCharString
LazyCharString -> LazyCharString -> LazyCharString
(LazyCharString -> LazyCharString -> LazyCharString)
-> (NonEmpty LazyCharString -> LazyCharString)
-> (forall b. Integral b => b -> LazyCharString -> LazyCharString)
-> Semigroup LazyCharString
forall b. Integral b => b -> LazyCharString -> LazyCharString
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
stimes :: b -> LazyCharString -> LazyCharString
$cstimes :: forall b. Integral b => b -> LazyCharString -> LazyCharString
sconcat :: NonEmpty LazyCharString -> LazyCharString
$csconcat :: NonEmpty LazyCharString -> LazyCharString
<> :: LazyCharString -> LazyCharString -> LazyCharString
$c<> :: LazyCharString -> LazyCharString -> LazyCharString
Semigroup, Semigroup LazyCharString
LazyCharString
Semigroup LazyCharString
-> LazyCharString
-> (LazyCharString -> LazyCharString -> LazyCharString)
-> ([LazyCharString] -> LazyCharString)
-> Monoid LazyCharString
[LazyCharString] -> LazyCharString
LazyCharString -> LazyCharString -> LazyCharString
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
mconcat :: [LazyCharString] -> LazyCharString
$cmconcat :: [LazyCharString] -> LazyCharString
mappend :: LazyCharString -> LazyCharString -> LazyCharString
$cmappend :: LazyCharString -> LazyCharString -> LazyCharString
mempty :: LazyCharString
$cmempty :: LazyCharString
$cp1Monoid :: Semigroup LazyCharString
Monoid, String -> LazyCharString
(String -> LazyCharString) -> IsString LazyCharString
forall a. (String -> a) -> IsString a
fromString :: String -> LazyCharString
$cfromString :: String -> LazyCharString
IsString)

toLazyCharString :: CharString -> LazyCharString
toLazyCharString :: CharString -> LazyCharString
toLazyCharString = CharString -> LazyCharString
forall a. HasCallStack => a
undefined

toStrictCharString :: LazyCharString -> CharString
toStrictCharString :: LazyCharString -> CharString
toStrictCharString = LazyCharString -> CharString
forall a. HasCallStack => a
undefined

instance Chunked CharString Char where
  consChunk :: Char -> CharString -> CharString
consChunk Char
a = ByteString -> CharString
CharString (ByteString -> CharString)
-> (CharString -> ByteString) -> CharString -> CharString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ByteString -> ByteString
BSC.cons Char
a (ByteString -> ByteString)
-> (CharString -> ByteString) -> CharString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CharString -> ByteString
unCharString
  unconsChunk :: CharString -> Maybe (Char, CharString)
unconsChunk = ((Char, ByteString) -> (Char, CharString))
-> Maybe (Char, ByteString) -> Maybe (Char, CharString)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((ByteString -> CharString)
-> (Char, ByteString) -> (Char, CharString)
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second ByteString -> CharString
CharString) (Maybe (Char, ByteString) -> Maybe (Char, CharString))
-> (CharString -> Maybe (Char, ByteString))
-> CharString
-> Maybe (Char, CharString)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Maybe (Char, ByteString)
BSC.uncons (ByteString -> Maybe (Char, ByteString))
-> (CharString -> ByteString)
-> CharString
-> Maybe (Char, ByteString)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CharString -> ByteString
unCharString
  tokenToChunk :: Char -> CharString
tokenToChunk = ByteString -> CharString
CharString (ByteString -> CharString)
-> (Char -> ByteString) -> Char -> CharString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ByteString
BSC.singleton
  tokensToChunk :: String -> CharString
tokensToChunk = ByteString -> CharString
CharString (ByteString -> CharString)
-> (String -> ByteString) -> String -> CharString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ByteString
BSC.pack
  chunkToTokens :: CharString -> String
chunkToTokens = ByteString -> String
BSC.unpack (ByteString -> String)
-> (CharString -> ByteString) -> CharString -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CharString -> ByteString
unCharString
  chunkLength :: CharString -> Int
chunkLength = ByteString -> Int
BSC.length (ByteString -> Int)
-> (CharString -> ByteString) -> CharString -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CharString -> ByteString
unCharString
  chunkEmpty :: CharString -> Bool
chunkEmpty = ByteString -> Bool
BSC.null (ByteString -> Bool)
-> (CharString -> ByteString) -> CharString -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CharString -> ByteString
unCharString

instance TextualChunked CharString where
  buildChunk :: CharString -> Builder
buildChunk = ByteString -> Builder
TB.asciiByteString (ByteString -> Builder)
-> (CharString -> ByteString) -> CharString -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CharString -> ByteString
unCharString
  packChunk :: CharString -> Text
packChunk = ByteString -> Text
TE.decodeLatin1 (ByteString -> Text)
-> (CharString -> ByteString) -> CharString -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CharString -> ByteString
unCharString
  unpackChunk :: Text -> CharString
unpackChunk = ByteString -> CharString
CharString (ByteString -> CharString)
-> (Text -> ByteString) -> Text -> CharString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
TE.encodeUtf8

instance Stream CharString where
  type Chunk CharString = CharString
  type Token CharString = Char

  streamTake1 :: CharString -> Maybe (Token CharString, CharString)
streamTake1 = Maybe (Char, ByteString) -> Maybe (Char, CharString)
coerce (Maybe (Char, ByteString) -> Maybe (Char, CharString))
-> (CharString -> Maybe (Char, ByteString))
-> CharString
-> Maybe (Char, CharString)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Maybe (Char, ByteString)
BSC.uncons (ByteString -> Maybe (Char, ByteString))
-> (CharString -> ByteString)
-> CharString
-> Maybe (Char, ByteString)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CharString -> ByteString
coerce
  streamTakeN :: Int -> CharString -> Maybe (Chunk CharString, CharString)
streamTakeN Int
n (CharString ByteString
s)
    | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 = (CharString, CharString) -> Maybe (CharString, CharString)
forall a. a -> Maybe a
Just ((ByteString, ByteString) -> (CharString, CharString)
coerce (ByteString
BSC.empty, ByteString
s))
    | ByteString -> Bool
BSC.null ByteString
s = Maybe (Chunk CharString, CharString)
forall a. Maybe a
Nothing
    | Bool
otherwise = (CharString, CharString) -> Maybe (CharString, CharString)
forall a. a -> Maybe a
Just ((ByteString, ByteString) -> (CharString, CharString)
coerce (Int -> ByteString -> (ByteString, ByteString)
BSC.splitAt Int
n ByteString
s))
  streamTakeWhile :: (Token CharString -> Bool)
-> CharString -> (Chunk CharString, CharString)
streamTakeWhile = (ByteString -> (ByteString, ByteString))
-> CharString -> (CharString, CharString)
coerce ((ByteString -> (ByteString, ByteString))
 -> CharString -> (CharString, CharString))
-> ((Char -> Bool) -> ByteString -> (ByteString, ByteString))
-> (Char -> Bool)
-> CharString
-> (CharString, CharString)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> ByteString -> (ByteString, ByteString)
BSC.span

instance Chunked LazyCharString Char where
  consChunk :: Char -> LazyCharString -> LazyCharString
consChunk Char
a = ByteString -> LazyCharString
LazyCharString (ByteString -> LazyCharString)
-> (LazyCharString -> ByteString)
-> LazyCharString
-> LazyCharString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ByteString -> ByteString
BSLC.cons Char
a (ByteString -> ByteString)
-> (LazyCharString -> ByteString) -> LazyCharString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LazyCharString -> ByteString
unLazyCharString
  unconsChunk :: LazyCharString -> Maybe (Char, LazyCharString)
unconsChunk = ((Char, ByteString) -> (Char, LazyCharString))
-> Maybe (Char, ByteString) -> Maybe (Char, LazyCharString)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((ByteString -> LazyCharString)
-> (Char, ByteString) -> (Char, LazyCharString)
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second ByteString -> LazyCharString
LazyCharString) (Maybe (Char, ByteString) -> Maybe (Char, LazyCharString))
-> (LazyCharString -> Maybe (Char, ByteString))
-> LazyCharString
-> Maybe (Char, LazyCharString)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Maybe (Char, ByteString)
BSLC.uncons (ByteString -> Maybe (Char, ByteString))
-> (LazyCharString -> ByteString)
-> LazyCharString
-> Maybe (Char, ByteString)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LazyCharString -> ByteString
unLazyCharString
  tokenToChunk :: Char -> LazyCharString
tokenToChunk = ByteString -> LazyCharString
LazyCharString (ByteString -> LazyCharString)
-> (Char -> ByteString) -> Char -> LazyCharString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ByteString
BSLC.singleton
  tokensToChunk :: String -> LazyCharString
tokensToChunk = ByteString -> LazyCharString
LazyCharString (ByteString -> LazyCharString)
-> (String -> ByteString) -> String -> LazyCharString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ByteString
BSLC.pack
  chunkToTokens :: LazyCharString -> String
chunkToTokens = ByteString -> String
BSLC.unpack (ByteString -> String)
-> (LazyCharString -> ByteString) -> LazyCharString -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LazyCharString -> ByteString
unLazyCharString
  chunkLength :: LazyCharString -> Int
chunkLength = Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int64 -> Int)
-> (LazyCharString -> Int64) -> LazyCharString -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Int64
BSLC.length (ByteString -> Int64)
-> (LazyCharString -> ByteString) -> LazyCharString -> Int64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LazyCharString -> ByteString
unLazyCharString
  chunkEmpty :: LazyCharString -> Bool
chunkEmpty = ByteString -> Bool
BSLC.null (ByteString -> Bool)
-> (LazyCharString -> ByteString) -> LazyCharString -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LazyCharString -> ByteString
unLazyCharString

instance TextualChunked LazyCharString where
  buildChunk :: LazyCharString -> Builder
buildChunk = ByteString -> Builder
TB.asciiByteString (ByteString -> Builder)
-> (LazyCharString -> ByteString) -> LazyCharString -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
BSLC.toStrict (ByteString -> ByteString)
-> (LazyCharString -> ByteString) -> LazyCharString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LazyCharString -> ByteString
unLazyCharString
  packChunk :: LazyCharString -> Text
packChunk = Text -> Text
TL.toStrict (Text -> Text)
-> (LazyCharString -> Text) -> LazyCharString -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Text
TLE.decodeLatin1 (ByteString -> Text)
-> (LazyCharString -> ByteString) -> LazyCharString -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LazyCharString -> ByteString
unLazyCharString
  unpackChunk :: Text -> LazyCharString
unpackChunk = ByteString -> LazyCharString
LazyCharString (ByteString -> LazyCharString)
-> (Text -> ByteString) -> Text -> LazyCharString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
TLE.encodeUtf8 (Text -> ByteString) -> (Text -> Text) -> Text -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
TL.fromStrict

instance Stream LazyCharString where
  type Chunk LazyCharString = LazyCharString
  type Token LazyCharString = Char

  streamTake1 :: LazyCharString -> Maybe (Token LazyCharString, LazyCharString)
streamTake1 = Maybe (Char, ByteString) -> Maybe (Char, LazyCharString)
coerce (Maybe (Char, ByteString) -> Maybe (Char, LazyCharString))
-> (LazyCharString -> Maybe (Char, ByteString))
-> LazyCharString
-> Maybe (Char, LazyCharString)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Maybe (Char, ByteString)
BSLC.uncons (ByteString -> Maybe (Char, ByteString))
-> (LazyCharString -> ByteString)
-> LazyCharString
-> Maybe (Char, ByteString)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LazyCharString -> ByteString
coerce
  streamTakeN :: Int
-> LazyCharString -> Maybe (Chunk LazyCharString, LazyCharString)
streamTakeN Int
n (LazyCharString ByteString
s)
    | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 = (LazyCharString, LazyCharString)
-> Maybe (LazyCharString, LazyCharString)
forall a. a -> Maybe a
Just ((ByteString, ByteString) -> (LazyCharString, LazyCharString)
coerce (ByteString
BSLC.empty, ByteString
s))
    | ByteString -> Bool
BSLC.null ByteString
s = Maybe (Chunk LazyCharString, LazyCharString)
forall a. Maybe a
Nothing
    | Bool
otherwise = (LazyCharString, LazyCharString)
-> Maybe (LazyCharString, LazyCharString)
forall a. a -> Maybe a
Just ((ByteString, ByteString) -> (LazyCharString, LazyCharString)
coerce (Int64 -> ByteString -> (ByteString, ByteString)
BSLC.splitAt (Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n) ByteString
s))
  streamTakeWhile :: (Token LazyCharString -> Bool)
-> LazyCharString -> (Chunk LazyCharString, LazyCharString)
streamTakeWhile = (ByteString -> (ByteString, ByteString))
-> LazyCharString -> (LazyCharString, LazyCharString)
coerce ((ByteString -> (ByteString, ByteString))
 -> LazyCharString -> (LazyCharString, LazyCharString))
-> ((Char -> Bool) -> ByteString -> (ByteString, ByteString))
-> (Char -> Bool)
-> LazyCharString
-> (LazyCharString, LazyCharString)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> ByteString -> (ByteString, ByteString)
BSLC.span