{-# LANGUAGE CPP
            ,MultiParamTypeClasses
            ,TypeFamilies
            ,FlexibleInstances #-}

module Data.ListLike.Chars

where

#if !MIN_VERSION_base(4,8,0)
import           Control.Applicative
import           Data.Monoid
#endif
import           Control.DeepSeq
--import           Control.Monad
import           Data.String as String (IsString)
#if !MIN_VERSION_base(4,11,0)
import Data.Semigroup (Semigroup(..))
#endif
import qualified Data.Text.Lazy as T
--import qualified Data.Text.Lazy.IO as TI
import qualified Data.Text.Lazy.Builder as Builder
--import           Data.Text.Encoding (decodeUtf8)
import           Data.ListLike.Base as LL
import           Data.ListLike.FoldableLL as LL
import           Data.ListLike.IO
import           Data.ListLike.String as LL
import           Data.ListLike.Text ()
import           GHC.Exts (IsList(..))

data Chars
    = B Builder.Builder
    | T T.Text
    deriving (Int -> Chars -> ShowS
[Chars] -> ShowS
Chars -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Chars] -> ShowS
$cshowList :: [Chars] -> ShowS
show :: Chars -> String
$cshow :: Chars -> String
showsPrec :: Int -> Chars -> ShowS
$cshowsPrec :: Int -> Chars -> ShowS
Show, Chars -> Chars -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Chars -> Chars -> Bool
$c/= :: Chars -> Chars -> Bool
== :: Chars -> Chars -> Bool
$c== :: Chars -> Chars -> Bool
Eq, Eq Chars
Chars -> Chars -> Bool
Chars -> Chars -> Ordering
Chars -> Chars -> Chars
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 :: Chars -> Chars -> Chars
$cmin :: Chars -> Chars -> Chars
max :: Chars -> Chars -> Chars
$cmax :: Chars -> Chars -> Chars
>= :: Chars -> Chars -> Bool
$c>= :: Chars -> Chars -> Bool
> :: Chars -> Chars -> Bool
$c> :: Chars -> Chars -> Bool
<= :: Chars -> Chars -> Bool
$c<= :: Chars -> Chars -> Bool
< :: Chars -> Chars -> Bool
$c< :: Chars -> Chars -> Bool
compare :: Chars -> Chars -> Ordering
$ccompare :: Chars -> Chars -> Ordering
Ord)

builder :: Chars -> Builder.Builder
builder :: Chars -> Builder
builder (B Builder
x) = Builder
x
builder (T Text
s) = Text -> Builder
Builder.fromLazyText Text
s
{-# INLINE builder #-}

instance Semigroup Chars where
  Chars
a <> :: Chars -> Chars -> Chars
<> Chars
b = Builder -> Chars
B forall a b. (a -> b) -> a -> b
$ Chars -> Builder
builder Chars
a forall a. Semigroup a => a -> a -> a
<> Chars -> Builder
builder Chars
b

instance Monoid Chars where
  mempty :: Chars
mempty  = Builder -> Chars
B forall a. Monoid a => a
mempty
  mappend :: Chars -> Chars -> Chars
mappend = forall a. Semigroup a => a -> a -> a
(<>)

instance String.IsString Chars where
  -- Builder already has an IsString instance, do we want to use it?
  -- fromString = B . String.fromString
  -- or do we want the implementation that used to be in the StringLike instance?
  fromString :: String -> Chars
fromString = Builder -> Chars
B forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Builder
Builder.fromLazyText forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. IsString a => String -> a
LL.fromString

instance FoldableLL Chars Char where
    foldl :: forall a. (a -> Char -> a) -> a -> Chars -> a
foldl a -> Char -> a
f a
r0 (B Builder
b) = forall full item a.
FoldableLL full item =>
(a -> item -> a) -> a -> full -> a
LL.foldl a -> Char -> a
f a
r0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> Text
Builder.toLazyText forall a b. (a -> b) -> a -> b
$ Builder
b
    foldl a -> Char -> a
f a
r0 (T Text
s) = forall full item a.
FoldableLL full item =>
(a -> item -> a) -> a -> full -> a
LL.foldl a -> Char -> a
f a
r0 forall a b. (a -> b) -> a -> b
$ Text
s
    foldr :: forall b. (Char -> b -> b) -> b -> Chars -> b
foldr Char -> b -> b
f b
r0 (B Builder
b) = forall full item b.
FoldableLL full item =>
(item -> b -> b) -> b -> full -> b
LL.foldr Char -> b -> b
f b
r0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> Text
Builder.toLazyText forall a b. (a -> b) -> a -> b
$ Builder
b
    foldr Char -> b -> b
f b
r0 (T Text
s) = forall full item b.
FoldableLL full item =>
(item -> b -> b) -> b -> full -> b
LL.foldr Char -> b -> b
f b
r0 forall a b. (a -> b) -> a -> b
$ Text
s
    --
    foldl' :: forall a. (a -> Char -> a) -> a -> Chars -> a
foldl' a -> Char -> a
f a
r0 (B Builder
b) = forall full item a.
FoldableLL full item =>
(a -> item -> a) -> a -> full -> a
LL.foldl' a -> Char -> a
f a
r0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> Text
Builder.toLazyText forall a b. (a -> b) -> a -> b
$ Builder
b
    foldl' a -> Char -> a
f a
r0 (T Text
s) = forall full item a.
FoldableLL full item =>
(a -> item -> a) -> a -> full -> a
LL.foldl' a -> Char -> a
f a
r0 forall a b. (a -> b) -> a -> b
$ Text
s
    foldl1 :: (Char -> Char -> Char) -> Chars -> Char
foldl1 Char -> Char -> Char
f (B Builder
b) = forall full item.
FoldableLL full item =>
(item -> item -> item) -> full -> item
LL.foldl1 Char -> Char -> Char
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> Text
Builder.toLazyText forall a b. (a -> b) -> a -> b
$ Builder
b
    foldl1 Char -> Char -> Char
f (T Text
s) = forall full item.
FoldableLL full item =>
(item -> item -> item) -> full -> item
LL.foldl1 Char -> Char -> Char
f forall a b. (a -> b) -> a -> b
$ Text
s
    foldr' :: forall b. (Char -> b -> b) -> b -> Chars -> b
foldr' Char -> b -> b
f b
r0 (B Builder
b) = forall full item b.
FoldableLL full item =>
(item -> b -> b) -> b -> full -> b
LL.foldr' Char -> b -> b
f b
r0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> Text
Builder.toLazyText forall a b. (a -> b) -> a -> b
$ Builder
b
    foldr' Char -> b -> b
f b
r0 (T Text
s) = forall full item b.
FoldableLL full item =>
(item -> b -> b) -> b -> full -> b
LL.foldr' Char -> b -> b
f b
r0 forall a b. (a -> b) -> a -> b
$ Text
s
    foldr1 :: (Char -> Char -> Char) -> Chars -> Char
foldr1 Char -> Char -> Char
f (B Builder
b) = forall full item.
FoldableLL full item =>
(item -> item -> item) -> full -> item
LL.foldr1 Char -> Char -> Char
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> Text
Builder.toLazyText forall a b. (a -> b) -> a -> b
$ Builder
b
    foldr1 Char -> Char -> Char
f (T Text
s) = forall full item.
FoldableLL full item =>
(item -> item -> item) -> full -> item
LL.foldr1 Char -> Char -> Char
f forall a b. (a -> b) -> a -> b
$ Text
s

instance IsList Chars where
    type Item Chars = Char
    toList :: Chars -> [Item Chars]
toList = forall full item. ListLike full item => full -> [item]
LL.toList'
    fromList :: [Item Chars] -> Chars
fromList = forall full item. ListLike full item => [item] -> full
LL.fromList'

instance ListLike Chars Char where
    singleton :: Char -> Chars
singleton = Builder -> Chars
B forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Builder
Builder.singleton
    uncons :: Chars -> Maybe (Char, Chars)
uncons (B Builder
b) =
        case forall full item. ListLike full item => full -> Maybe (item, full)
LL.uncons (Builder -> Text
Builder.toLazyText Builder
b) of
          Maybe (Char, Text)
Nothing -> forall a. Maybe a
Nothing
          Just (Char
c, Text
s) -> forall a. a -> Maybe a
Just (Char
c, Text -> Chars
T Text
s)
    uncons (T Text
s) =
        case forall full item. ListLike full item => full -> Maybe (item, full)
LL.uncons Text
s of
          Maybe (Char, Text)
Nothing -> forall a. Maybe a
Nothing
          Just (Char
c, Text
s') -> forall a. a -> Maybe a
Just (Char
c, Text -> Chars
T Text
s')
    null :: Chars -> Bool
null (B Builder
b) = forall full item. ListLike full item => full -> Bool
LL.null forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> Text
Builder.toLazyText forall a b. (a -> b) -> a -> b
$ Builder
b
    null (T Text
t) = forall full item. ListLike full item => full -> Bool
LL.null Text
t

instance ListLikeIO Chars Char where
    hGetLine :: Handle -> IO Chars
hGetLine Handle
h = Text -> Chars
T forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall full item. ListLikeIO full item => Handle -> IO full
hGetLine Handle
h
    hGetContents :: Handle -> IO Chars
hGetContents Handle
h = Text -> Chars
T forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall full item. ListLikeIO full item => Handle -> IO full
hGetContents Handle
h
    hGet :: Handle -> Int -> IO Chars
hGet Handle
h Int
n = Text -> Chars
T forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall full item. ListLikeIO full item => Handle -> Int -> IO full
hGet Handle
h Int
n
    hGetNonBlocking :: Handle -> Int -> IO Chars
hGetNonBlocking Handle
h Int
n = Text -> Chars
T forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall full item. ListLikeIO full item => Handle -> Int -> IO full
hGetNonBlocking Handle
h Int
n
    hPutStr :: Handle -> Chars -> IO ()
hPutStr Handle
h (B Builder
b) = forall full item. ListLikeIO full item => Handle -> full -> IO ()
hPutStr Handle
h forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> Text
Builder.toLazyText forall a b. (a -> b) -> a -> b
$ Builder
b
    hPutStr Handle
h (T Text
s) = forall full item. ListLikeIO full item => Handle -> full -> IO ()
hPutStr Handle
h forall a b. (a -> b) -> a -> b
$ Text
s

instance StringLike Chars where
    toString :: Chars -> String
toString (B Builder
b) = forall s. StringLike s => s -> String
toString forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> Text
Builder.toLazyText forall a b. (a -> b) -> a -> b
$ Builder
b
    toString (T Text
s) = forall s. StringLike s => s -> String
toString forall a b. (a -> b) -> a -> b
$ Text
s
    fromLazyText :: StringLike Text => Text -> Chars
fromLazyText = Builder -> Chars
B forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Builder
Builder.fromLazyText
    fromText :: StringLike Text => Text -> Chars
fromText = Builder -> Chars
B forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Builder
Builder.fromText

instance NFData Chars where
    rnf :: Chars -> ()
rnf (B Builder
b) = forall a. NFData a => a -> ()
rnf forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> Text
Builder.toLazyText forall a b. (a -> b) -> a -> b
$ Builder
b
    rnf (T Text
s) = forall a. NFData a => a -> ()
rnf Text
s