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
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
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
Ord, Int -> CharString -> ShowS
[CharString] -> ShowS
CharString -> String
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, NonEmpty CharString -> CharString
CharString -> CharString -> 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 :: forall b. Integral b => 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
[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
Monoid, String -> 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
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
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
Ord, Int -> LazyCharString -> ShowS
[LazyCharString] -> ShowS
LazyCharString -> String
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, NonEmpty LazyCharString -> LazyCharString
LazyCharString -> LazyCharString -> 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 :: forall b. Integral b => 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
[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
Monoid, String -> LazyCharString
forall a. (String -> a) -> IsString a
fromString :: String -> LazyCharString
$cfromString :: String -> LazyCharString
IsString)

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

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

instance Chunked CharString Char where
  consChunk :: Char -> CharString -> CharString
consChunk Char
a = ByteString -> CharString
CharString forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ByteString -> ByteString
BSC.cons Char
a forall b c a. (b -> c) -> (a -> b) -> a -> c
. CharString -> ByteString
unCharString
  unconsChunk :: CharString -> Maybe (Char, CharString)
unconsChunk = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second ByteString -> CharString
CharString) forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Maybe (Char, ByteString)
BSC.uncons forall b c a. (b -> c) -> (a -> b) -> a -> c
. CharString -> ByteString
unCharString
  tokenToChunk :: Char -> CharString
tokenToChunk = ByteString -> CharString
CharString forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ByteString
BSC.singleton
  tokensToChunk :: String -> CharString
tokensToChunk = ByteString -> CharString
CharString forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ByteString
BSC.pack
  chunkToTokens :: CharString -> String
chunkToTokens = ByteString -> String
BSC.unpack forall b c a. (b -> c) -> (a -> b) -> a -> c
. CharString -> ByteString
unCharString
  chunkLength :: CharString -> Int
chunkLength = ByteString -> Int
BSC.length forall b c a. (b -> c) -> (a -> b) -> a -> c
. CharString -> ByteString
unCharString
  chunkEmpty :: CharString -> Bool
chunkEmpty = ByteString -> Bool
BSC.null 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 forall b c a. (b -> c) -> (a -> b) -> a -> c
. CharString -> ByteString
unCharString
  packChunk :: CharString -> Text
packChunk = ByteString -> Text
TE.decodeLatin1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. CharString -> ByteString
unCharString
  unpackChunk :: Text -> CharString
unpackChunk = ByteString -> CharString
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 = coerce :: forall a b. Coercible a b => a -> b
coerce forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Maybe (Char, ByteString)
BSC.uncons forall b c a. (b -> c) -> (a -> b) -> a -> c
. coerce :: forall a b. Coercible a b => a -> b
coerce
  streamTakeN :: Int -> CharString -> Maybe (Chunk CharString, CharString)
streamTakeN Int
n (CharString ByteString
s)
    | Int
n forall a. Ord a => a -> a -> Bool
<= Int
0 = forall a. a -> Maybe a
Just (coerce :: forall a b. Coercible a b => a -> b
coerce (ByteString
BSC.empty, ByteString
s))
    | ByteString -> Bool
BSC.null ByteString
s = forall a. Maybe a
Nothing
    | Bool
otherwise = forall a. a -> Maybe a
Just (coerce :: forall a b. Coercible a b => a -> b
coerce (Int -> ByteString -> (ByteString, ByteString)
BSC.splitAt Int
n ByteString
s))
  streamTakeWhile :: (Token CharString -> Bool)
-> CharString -> (Chunk CharString, CharString)
streamTakeWhile = coerce :: forall a b. Coercible a b => a -> b
coerce 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 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ByteString -> ByteString
BSLC.cons Char
a forall b c a. (b -> c) -> (a -> b) -> a -> c
. LazyCharString -> ByteString
unLazyCharString
  unconsChunk :: LazyCharString -> Maybe (Char, LazyCharString)
unconsChunk = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second ByteString -> LazyCharString
LazyCharString) forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Maybe (Char, ByteString)
BSLC.uncons forall b c a. (b -> c) -> (a -> b) -> a -> c
. LazyCharString -> ByteString
unLazyCharString
  tokenToChunk :: Char -> LazyCharString
tokenToChunk = ByteString -> LazyCharString
LazyCharString forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ByteString
BSLC.singleton
  tokensToChunk :: String -> LazyCharString
tokensToChunk = ByteString -> LazyCharString
LazyCharString forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ByteString
BSLC.pack
  chunkToTokens :: LazyCharString -> String
chunkToTokens = ByteString -> String
BSLC.unpack forall b c a. (b -> c) -> (a -> b) -> a -> c
. LazyCharString -> ByteString
unLazyCharString
  chunkLength :: LazyCharString -> Int
chunkLength = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Int64
BSLC.length forall b c a. (b -> c) -> (a -> b) -> a -> c
. LazyCharString -> ByteString
unLazyCharString
  chunkEmpty :: LazyCharString -> Bool
chunkEmpty = ByteString -> Bool
BSLC.null 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 forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
BSLC.toStrict forall b c a. (b -> c) -> (a -> b) -> a -> c
. LazyCharString -> ByteString
unLazyCharString
  packChunk :: LazyCharString -> Text
packChunk = Text -> Text
TL.toStrict forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Text
TLE.decodeLatin1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. LazyCharString -> ByteString
unLazyCharString
  unpackChunk :: Text -> LazyCharString
unpackChunk = ByteString -> LazyCharString
LazyCharString forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
TLE.encodeUtf8 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 = coerce :: forall a b. Coercible a b => a -> b
coerce forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Maybe (Char, ByteString)
BSLC.uncons forall b c a. (b -> c) -> (a -> b) -> a -> c
. coerce :: forall a b. Coercible a b => a -> b
coerce
  streamTakeN :: Int
-> LazyCharString -> Maybe (Chunk LazyCharString, LazyCharString)
streamTakeN Int
n (LazyCharString ByteString
s)
    | Int
n forall a. Ord a => a -> a -> Bool
<= Int
0 = forall a. a -> Maybe a
Just (coerce :: forall a b. Coercible a b => a -> b
coerce (ByteString
BSLC.empty, ByteString
s))
    | ByteString -> Bool
BSLC.null ByteString
s = forall a. Maybe a
Nothing
    | Bool
otherwise = forall a. a -> Maybe a
Just (coerce :: forall a b. Coercible a b => a -> b
coerce (Int64 -> ByteString -> (ByteString, ByteString)
BSLC.splitAt (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n) ByteString
s))
  streamTakeWhile :: (Token LazyCharString -> Bool)
-> LazyCharString -> (Chunk LazyCharString, LazyCharString)
streamTakeWhile = coerce :: forall a b. Coercible a b => a -> b
coerce forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> ByteString -> (ByteString, ByteString)
BSLC.span