{-# LANGUAGE CPP #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternSynonyms #-}
module Xmlbf
(
runParser
, Parser
, pElement
, pAnyElement
, pName
, pAttr
, pAttrs
, pChildren
, pText
, pEndOfInput
, encode
, Node
, node
, pattern Element
, element
, element'
, pattern Text
, text
, text'
, dfpos
, dfposM
, dfpre
, dfpreM
, FromXml(fromXml)
, ToXml(toXml)
)
where
import Control.Applicative (Alternative(empty, (<|>)), liftA2)
import Control.DeepSeq (NFData(rnf))
import Control.Monad (MonadPlus(mplus, mzero), join, when)
import qualified Control.Monad.Fail
import Control.Monad.Fix (MonadFix(mfix))
import Control.Monad.Zip (MonadZip(mzipWith))
import Control.Selective (Selective(select))
import qualified Data.ByteString.Builder as BB
import qualified Data.ByteString.Builder.Prim as BBP
import qualified Data.Char as Char
import Data.Foldable (for_, toList)
import Data.Function (fix)
import Data.Functor.Identity (Identity(Identity), runIdentity)
import qualified Data.HashMap.Strict as HM
import qualified Data.Map.Strict as Map
import Data.Sequence (Seq)
import qualified Data.Sequence as Seq
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.Encoding as TL
import Data.Traversable (for)
import Data.Word (Word8)
data Node
= Element' !T.Text !(HM.HashMap T.Text T.Text) ![Node]
| Text' !TL.Text
deriving (Node -> Node -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Node -> Node -> Bool
$c/= :: Node -> Node -> Bool
== :: Node -> Node -> Bool
$c== :: Node -> Node -> Bool
Eq)
instance NFData Node where
rnf :: Node -> ()
rnf = \case
Element' Text
n HashMap Text Text
as [Node]
cs -> forall a. NFData a => a -> ()
rnf Text
n seq :: forall a b. a -> b -> b
`seq` forall a. NFData a => a -> ()
rnf HashMap Text Text
as seq :: forall a b. a -> b -> b
`seq` forall a. NFData a => a -> ()
rnf [Node]
cs seq :: forall a b. a -> b -> b
`seq` ()
Text' Text
t -> forall a. NFData a => a -> ()
rnf Text
t seq :: forall a b. a -> b -> b
`seq` ()
{-# INLINABLE rnf #-}
instance Show Node where
showsPrec :: Int -> Node -> ShowS
showsPrec Int
n = \Node
x -> Bool -> ShowS -> ShowS
showParen (Int
n forall a. Ord a => a -> a -> Bool
> Int
10) forall a b. (a -> b) -> a -> b
$ case Node
x of
Text' Text
t -> String -> ShowS
showString String
"Text " forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => Int -> a -> ShowS
showsPrec Int
0 Text
t
Element' Text
t HashMap Text Text
as [Node]
cs ->
String -> ShowS
showString String
"Element " forall b c a. (b -> c) -> (a -> b) -> a -> c
.
forall a. Show a => Int -> a -> ShowS
showsPrec Int
0 Text
t forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ShowS
showChar Char
' ' forall b c a. (b -> c) -> (a -> b) -> a -> c
.
forall a. Show a => Int -> a -> ShowS
showsPrec Int
0 (forall k v. HashMap k v -> [(k, v)]
HM.toList HashMap Text Text
as) forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> ShowS
showChar Char
' ' forall b c a. (b -> c) -> (a -> b) -> a -> c
.
forall a. Show a => Int -> a -> ShowS
showsPrec Int
0 [Node]
cs
pattern Element :: T.Text -> HM.HashMap T.Text T.Text -> [Node] -> Node
pattern $mElement :: forall {r}.
Node
-> (Text -> HashMap Text Text -> [Node] -> r) -> ((# #) -> r) -> r
Element t as cs <- Element' t as cs
{-# COMPLETE Element #-}
pattern Text :: TL.Text -> Node
pattern $mText :: forall {r}. Node -> (Text -> r) -> ((# #) -> r) -> r
Text t <- Text' t
{-# COMPLETE Text #-}
node
:: (T.Text -> HM.HashMap T.Text T.Text -> [Node] -> a)
-> (TL.Text -> a)
-> Node
-> a
{-# INLINE node #-}
node :: forall a.
(Text -> HashMap Text Text -> [Node] -> a)
-> (Text -> a) -> Node -> a
node Text -> HashMap Text Text -> [Node] -> a
fe Text -> a
ft = \case
Text' Text
t -> Text -> a
ft Text
t
Element' Text
t HashMap Text Text
as [Node]
cs -> Text -> HashMap Text Text -> [Node] -> a
fe Text
t HashMap Text Text
as [Node]
cs
normalize :: [Node] -> [Node]
{-# INLINE normalize #-}
normalize :: [Node] -> [Node]
normalize = \case
Text' Text
"" : [Node]
ns -> [Node] -> [Node]
normalize [Node]
ns
Text' Text
a : Text' Text
b : [Node]
ns -> [Node] -> [Node]
normalize (Text -> [Node]
text (Text
a forall a. Semigroup a => a -> a -> a
<> Text
b) forall a. Semigroup a => a -> a -> a
<> [Node]
ns)
Text' Text
a : [Node]
ns -> Text -> Node
Text' Text
a forall a. a -> [a] -> [a]
: [Node] -> [Node]
normalize [Node]
ns
Element' Text
t HashMap Text Text
as [Node]
cs : [Node]
ns -> Text -> HashMap Text Text -> [Node] -> Node
Element' Text
t HashMap Text Text
as ([Node] -> [Node]
normalize [Node]
cs) forall a. a -> [a] -> [a]
: [Node] -> [Node]
normalize [Node]
ns
[] -> []
text
:: TL.Text
-> [Node]
{-# INLINE text #-}
text :: Text -> [Node]
text Text
t = case Text -> Either String Node
text' Text
t of
Right Node
x -> [Node
x]
Left String
_ -> []
text'
:: TL.Text
-> Either String Node
{-# INLINE text' #-}
text' :: Text -> Either String Node
text' = \case
Text
"" -> forall a b. a -> Either a b
Left String
"Empty text"
Text
t -> forall a b. b -> Either a b
Right (Text -> Node
Text' Text
t)
element
:: T.Text
-> HM.HashMap T.Text T.Text
-> [Node]
-> [Node]
{-# INLINE element #-}
element :: Text -> HashMap Text Text -> [Node] -> [Node]
element Text
t HashMap Text Text
hm [Node]
ns = case Text -> HashMap Text Text -> [Node] -> Either String Node
element' Text
t HashMap Text Text
hm [Node]
ns of
Right Node
x -> [Node
x]
Left String
_ -> []
element'
:: T.Text
-> HM.HashMap T.Text T.Text
-> [Node]
-> Either String Node
element' :: Text -> HashMap Text Text -> [Node] -> Either String Node
element' Text
t0 HashMap Text Text
hm0 [Node]
ns0 = do
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Text
t0 forall a. Eq a => a -> a -> Bool
/= Text -> Text
T.strip Text
t0)
(forall a b. a -> Either a b
Left (String
"Element name has surrounding whitespace: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Text
t0))
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Text -> Bool
T.null Text
t0)
(forall a b. a -> Either a b
Left (String
"Element name is blank: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Text
t0))
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ (forall k v. HashMap k v -> [k]
HM.keys HashMap Text Text
hm0) forall a b. (a -> b) -> a -> b
$ \Text
k -> do
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Text
k forall a. Eq a => a -> a -> Bool
/= Text -> Text
T.strip Text
k)
(forall a b. a -> Either a b
Left (String
"Attribute name has surrounding whitespace: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Text
k))
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Text -> Bool
T.null Text
k)
(forall a b. a -> Either a b
Left (String
"Attribute name is blank: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Text
k))
forall a b. b -> Either a b
Right (Text -> HashMap Text Text -> [Node] -> Node
Element' Text
t0 HashMap Text Text
hm0 ([Node] -> [Node]
normalize [Node]
ns0))
class FromXml a where
fromXml :: Parser a
data S
= STop ![Node]
| SReg !T.Text !(HM.HashMap T.Text T.Text) ![Node]
initialS :: [Node] -> S
initialS :: [Node] -> S
initialS = [Node] -> S
STop forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Node] -> [Node]
normalize
{-# INLINE initialS #-}
newtype Parser a = Parser { forall a. Parser a -> S -> Either String (S, a)
unParser :: S -> Either String (S, a) }
runParser
:: Parser a
-> [Node]
-> Either String a
runParser :: forall a. Parser a -> [Node] -> Either String a
runParser Parser a
p = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (a, b) -> b
snd forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Parser a -> S -> Either String (S, a)
unParser Parser a
p forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Node] -> S
initialS
{-# INLINE runParser #-}
#if MIN_VERSION_base(4,9,0)
instance Semigroup a => Semigroup (Parser a) where
<> :: Parser a -> Parser a -> Parser a
(<>) = forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 forall a. Semigroup a => a -> a -> a
(<>)
{-# INLINE (<>) #-}
#endif
instance Monoid a => Monoid (Parser a) where
mempty :: Parser a
mempty = forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. Monoid a => a
mempty
{-# INLINE mempty #-}
#if MIN_VERSION_base(4,9,0)
mappend :: Parser a -> Parser a -> Parser a
mappend = forall a. Semigroup a => a -> a -> a
(<>)
#else
mappend = liftA2 mappend
#endif
{-# INLINE mappend #-}
instance Functor Parser where
fmap :: forall a b. (a -> b) -> Parser a -> Parser b
fmap a -> b
f = \Parser a
pa -> forall a. (S -> Either String (S, a)) -> Parser a
Parser (\S
s -> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f) (forall a. Parser a -> S -> Either String (S, a)
unParser Parser a
pa S
s))
{-# INLINE fmap #-}
instance Applicative Parser where
pure :: forall a. a -> Parser a
pure = \a
a -> forall a. (S -> Either String (S, a)) -> Parser a
Parser (\S
s -> forall a b. b -> Either a b
Right (S
s, a
a))
{-# INLINE pure #-}
Parser (a -> b)
pf <*> :: forall a b. Parser (a -> b) -> Parser a -> Parser b
<*> Parser a
pa = forall a. (S -> Either String (S, a)) -> Parser a
Parser (\S
s0 -> do
(S
s1, a -> b
f) <- forall a. Parser a -> S -> Either String (S, a)
unParser Parser (a -> b)
pf S
s0
(S
s2, a
a) <- forall a. Parser a -> S -> Either String (S, a)
unParser Parser a
pa S
s1
forall a b. b -> Either a b
Right (S
s2, a -> b
f a
a))
{-# INLINABLE (<*>) #-}
instance Alternative Parser where
empty :: forall a. Parser a
empty = forall a. String -> Parser a
pFail String
"empty"
{-# INLINE empty #-}
Parser a
pa <|> :: forall a. Parser a -> Parser a -> Parser a
<|> Parser a
pb = forall a. (S -> Either String (S, a)) -> Parser a
Parser (\S
s0 ->
case forall a. Parser a -> S -> Either String (S, a)
unParser Parser a
pa S
s0 of
Right (S
s1, a
a) -> forall a b. b -> Either a b
Right (S
s1, a
a)
Left String
_ -> forall a. Parser a -> S -> Either String (S, a)
unParser Parser a
pb S
s0)
{-# INLINABLE (<|>) #-}
instance Selective Parser where
select :: forall a b. Parser (Either a b) -> Parser (a -> b) -> Parser b
select Parser (Either a b)
pe Parser (a -> b)
pf = forall a. (S -> Either String (S, a)) -> Parser a
Parser (\S
s0 -> do
(S
s1, Either a b
ea) <- forall a. Parser a -> S -> Either String (S, a)
unParser Parser (Either a b)
pe S
s0
case Either a b
ea of
Right b
b -> forall a b. b -> Either a b
Right (S
s1, b
b)
Left a
a -> do
(S
s2, a -> b
f) <- forall a. Parser a -> S -> Either String (S, a)
unParser Parser (a -> b)
pf S
s1
forall a b. b -> Either a b
Right (S
s2, a -> b
f a
a))
{-# INLINABLE select #-}
instance Monad Parser where
return :: forall a. a -> Parser a
return = forall (f :: * -> *) a. Applicative f => a -> f a
pure
{-# INLINE return #-}
Parser a
pa >>= :: forall a b. Parser a -> (a -> Parser b) -> Parser b
>>= a -> Parser b
kpb = forall a. (S -> Either String (S, a)) -> Parser a
Parser (\S
s0 -> do
(S
s1, a
a) <- forall a. Parser a -> S -> Either String (S, a)
unParser Parser a
pa S
s0
forall a. Parser a -> S -> Either String (S, a)
unParser (a -> Parser b
kpb a
a) S
s1)
{-# INLINABLE (>>=) #-}
#if !MIN_VERSION_base(4,13,0)
fail = pFail
{-# INLINE fail #-}
#endif
#if MIN_VERSION_base(4,9,0)
instance Control.Monad.Fail.MonadFail Parser where
fail :: forall a. String -> Parser a
fail = forall a. String -> Parser a
pFail
{-# INLINE fail #-}
#endif
pFail :: String -> Parser a
pFail :: forall a. String -> Parser a
pFail = \String
msg -> forall a. (S -> Either String (S, a)) -> Parser a
Parser (\S
_ -> forall a b. a -> Either a b
Left String
msg)
{-# INLINE pFail #-}
instance MonadPlus Parser where
mzero :: forall a. Parser a
mzero = forall (f :: * -> *) a. Alternative f => f a
empty
{-# INLINE mzero #-}
mplus :: forall a. Parser a -> Parser a -> Parser a
mplus = forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
(<|>)
{-# INLINE mplus #-}
instance MonadFix Parser where
mfix :: forall a. (a -> Parser a) -> Parser a
mfix a -> Parser a
f =
let die :: String -> a
die = \String
msg -> forall a. HasCallStack => String -> a
error (String
"mfix (Parser): " forall a. Semigroup a => a -> a -> a
<> String
msg)
in forall a. (S -> Either String (S, a)) -> Parser a
Parser (\S
s0 -> forall a. (a -> a) -> a
fix (forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a. Parser a -> S -> Either String (S, a)
unParser S
s0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Parser a
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either forall {a}. String -> a
die forall a b. (a, b) -> b
snd))
{-# INLINABLE mfix #-}
instance MonadZip Parser where
mzipWith :: forall a b c. (a -> b -> c) -> Parser a -> Parser b -> Parser c
mzipWith = forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2
{-# INLINE mzipWith #-}
pElement
:: T.Text
-> Parser a
-> Parser a
pElement :: forall a. Text -> Parser a -> Parser a
pElement Text
t0 Parser a
p0 = forall a. (S -> Either String (S, a)) -> Parser a
Parser forall a b. (a -> b) -> a -> b
$ \case
SReg Text
t1 HashMap Text Text
as0 (Element' Text
t HashMap Text Text
as [Node]
cs : [Node]
cs0) | Text
t forall a. Eq a => a -> a -> Bool
== Text
t0 ->
case forall a. Parser a -> S -> Either String (S, a)
unParser Parser a
p0 (Text -> HashMap Text Text -> [Node] -> S
SReg Text
t HashMap Text Text
as [Node]
cs) of
Right (S
_, a
a) -> forall a b. b -> Either a b
Right (Text -> HashMap Text Text -> [Node] -> S
SReg Text
t1 HashMap Text Text
as0 [Node]
cs0, a
a)
Left String
msg -> forall a b. a -> Either a b
Left String
msg
STop (Element' Text
t HashMap Text Text
as [Node]
cs : [Node]
cs0) | Text
t forall a. Eq a => a -> a -> Bool
== Text
t0 ->
case forall a. Parser a -> S -> Either String (S, a)
unParser Parser a
p0 (Text -> HashMap Text Text -> [Node] -> S
SReg Text
t HashMap Text Text
as [Node]
cs) of
Right (S
_, a
a) -> forall a b. b -> Either a b
Right ([Node] -> S
STop [Node]
cs0, a
a)
Left String
msg -> forall a b. a -> Either a b
Left String
msg
SReg Text
t HashMap Text Text
as (Text' Text
x : [Node]
cs) | (Char -> Bool) -> Text -> Bool
TL.all Char -> Bool
Char.isSpace Text
x ->
forall a. Parser a -> S -> Either String (S, a)
unParser (forall a. Text -> Parser a -> Parser a
pElement Text
t0 Parser a
p0) (Text -> HashMap Text Text -> [Node] -> S
SReg Text
t HashMap Text Text
as [Node]
cs)
STop (Text' Text
x : [Node]
cs) | (Char -> Bool) -> Text -> Bool
TL.all Char -> Bool
Char.isSpace Text
x ->
forall a. Parser a -> S -> Either String (S, a)
unParser (forall a. Text -> Parser a -> Parser a
pElement Text
t0 Parser a
p0) ([Node] -> S
STop [Node]
cs)
S
_ -> forall a b. a -> Either a b
Left (String
"Missing element " forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> String
show Text
t0)
{-# INLINABLE pElement #-}
pAnyElement
:: Parser a
-> Parser a
pAnyElement :: forall a. Parser a -> Parser a
pAnyElement Parser a
p0 = forall a. (S -> Either String (S, a)) -> Parser a
Parser forall a b. (a -> b) -> a -> b
$ \case
SReg Text
t0 HashMap Text Text
as0 (Element' Text
t HashMap Text Text
as [Node]
cs : [Node]
cs0) ->
case forall a. Parser a -> S -> Either String (S, a)
unParser Parser a
p0 (Text -> HashMap Text Text -> [Node] -> S
SReg Text
t HashMap Text Text
as [Node]
cs) of
Right (S
_, a
a) -> forall a b. b -> Either a b
Right (Text -> HashMap Text Text -> [Node] -> S
SReg Text
t0 HashMap Text Text
as0 [Node]
cs0, a
a)
Left String
msg -> forall a b. a -> Either a b
Left String
msg
STop (Element' Text
t HashMap Text Text
as [Node]
cs : [Node]
cs0) ->
case forall a. Parser a -> S -> Either String (S, a)
unParser Parser a
p0 (Text -> HashMap Text Text -> [Node] -> S
SReg Text
t HashMap Text Text
as [Node]
cs) of
Right (S
_, a
a) -> forall a b. b -> Either a b
Right ([Node] -> S
STop [Node]
cs0, a
a)
Left String
msg -> forall a b. a -> Either a b
Left String
msg
SReg Text
t HashMap Text Text
as (Text' Text
x : [Node]
cs) | (Char -> Bool) -> Text -> Bool
TL.all Char -> Bool
Char.isSpace Text
x ->
forall a. Parser a -> S -> Either String (S, a)
unParser (forall a. Parser a -> Parser a
pAnyElement Parser a
p0) (Text -> HashMap Text Text -> [Node] -> S
SReg Text
t HashMap Text Text
as [Node]
cs)
STop (Text' Text
x : [Node]
cs) | (Char -> Bool) -> Text -> Bool
TL.all Char -> Bool
Char.isSpace Text
x ->
forall a. Parser a -> S -> Either String (S, a)
unParser (forall a. Parser a -> Parser a
pAnyElement Parser a
p0) ([Node] -> S
STop [Node]
cs)
S
_ -> forall a b. a -> Either a b
Left String
"Missing element"
{-# INLINABLE pAnyElement #-}
pName :: Parser T.Text
pName :: Parser Text
pName = forall a. (S -> Either String (S, a)) -> Parser a
Parser (\case
s :: S
s@(SReg Text
t HashMap Text Text
_ [Node]
_) -> forall a b. b -> Either a b
Right (S
s, Text
t)
S
_ -> forall a b. a -> Either a b
Left String
"Before selecting an name, you must select an element")
{-# INLINABLE pName #-}
pAttr
:: T.Text
-> Parser T.Text
pAttr :: Text -> Parser Text
pAttr Text
n = forall a. (S -> Either String (S, a)) -> Parser a
Parser (\case
SReg Text
t HashMap Text Text
as [Node]
cs -> case forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HM.lookup Text
n HashMap Text Text
as of
Just Text
x -> forall a b. b -> Either a b
Right (Text -> HashMap Text Text -> [Node] -> S
SReg Text
t (forall k v. (Eq k, Hashable k) => k -> HashMap k v -> HashMap k v
HM.delete Text
n HashMap Text Text
as) [Node]
cs, Text
x)
Maybe Text
Nothing -> forall a b. a -> Either a b
Left (String
"Missing attribute " forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> String
show Text
n)
S
_ -> forall a b. a -> Either a b
Left String
"Before selecting an attribute, you must select an element")
{-# INLINABLE pAttr #-}
pAttrs
:: Parser (HM.HashMap T.Text T.Text)
pAttrs :: Parser (HashMap Text Text)
pAttrs = forall a. (S -> Either String (S, a)) -> Parser a
Parser (\case
SReg Text
t HashMap Text Text
as [Node]
cs -> forall a b. b -> Either a b
Right (Text -> HashMap Text Text -> [Node] -> S
SReg Text
t forall a. Monoid a => a
mempty [Node]
cs, HashMap Text Text
as)
S
_ -> forall a b. a -> Either a b
Left String
"Before selecting an attribute, you must select an element")
{-# INLINABLE pAttrs #-}
pChildren
:: Parser [Node]
pChildren :: Parser [Node]
pChildren = forall a. (S -> Either String (S, a)) -> Parser a
Parser (\case
STop [Node]
cs -> forall a b. b -> Either a b
Right ([Node] -> S
STop forall a. Monoid a => a
mempty, [Node]
cs)
SReg Text
t HashMap Text Text
as [Node]
cs -> forall a b. b -> Either a b
Right (Text -> HashMap Text Text -> [Node] -> S
SReg Text
t HashMap Text Text
as forall a. Monoid a => a
mempty, [Node]
cs))
{-# INLINABLE pChildren #-}
pText
:: Parser TL.Text
pText :: Parser Text
pText = forall a. (S -> Either String (S, a)) -> Parser a
Parser (\case
STop (Text Text
x : [Node]
ns) -> forall a b. b -> Either a b
Right ([Node] -> S
STop [Node]
ns, Text
x)
SReg Text
t HashMap Text Text
as (Text Text
x : [Node]
cs) -> forall a b. b -> Either a b
Right (Text -> HashMap Text Text -> [Node] -> S
SReg Text
t HashMap Text Text
as [Node]
cs, Text
x)
S
_ -> forall a b. a -> Either a b
Left String
"Missing text node")
{-# INLINABLE pText #-}
pEndOfInput :: Parser ()
pEndOfInput :: Parser ()
pEndOfInput = forall a. (S -> Either String (S, a)) -> Parser a
Parser (\S
s -> case S -> Bool
isEof S
s of
Bool
True -> forall a b. b -> Either a b
Right (S
s, ())
Bool
False -> forall a b. a -> Either a b
Left String
"Not end of input yet")
{-# INLINABLE pEndOfInput #-}
isEof :: S -> Bool
isEof :: S -> Bool
isEof = \case
SReg Text
_ HashMap Text Text
as [Node]
cs -> forall k v. HashMap k v -> Bool
HM.null HashMap Text Text
as Bool -> Bool -> Bool
&& forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Node]
cs
STop [Node]
ns -> forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Node]
ns
{-# INLINE isEof #-}
class ToXml a where
toXml :: a -> [Node]
encode :: [Node] -> BB.Builder
encode :: [Node] -> Builder
encode [Node]
xs = forall a. Monoid a => [a] -> a
mconcat (forall a b. (a -> b) -> [a] -> [b]
map Node -> Builder
encodeNode [Node]
xs)
where
encodeNode :: Node -> BB.Builder
encodeNode :: Node -> Builder
encodeNode = \case
Text Text
x -> Text -> Builder
encodeXmlUtf8Lazy Text
x
Element Text
t HashMap Text Text
as [Node]
cs ->
Builder
"<" forall a. Semigroup a => a -> a -> a
<> Text -> Builder
encodeUtf8 Text
t
forall a. Semigroup a => a -> a -> a
<> Builder -> Map Text Text -> Builder
encodeAttrs (Builder
">" forall a. Semigroup a => a -> a -> a
<> [Node] -> Builder
encode [Node]
cs forall a. Semigroup a => a -> a -> a
<> Builder
"</" forall a. Semigroup a => a -> a -> a
<> Text -> Builder
encodeUtf8 Text
t forall a. Semigroup a => a -> a -> a
<> Builder
">")
(forall k v. Ord k => HashMap k v -> Map k v
mapFromHashMap HashMap Text Text
as)
{-# INLINE encodeNode #-}
encodeAttrs :: BB.Builder -> Map.Map T.Text T.Text -> BB.Builder
encodeAttrs :: Builder -> Map Text Text -> Builder
encodeAttrs = forall k a b. (k -> a -> b -> b) -> b -> Map k a -> b
Map.foldrWithKey
(\Text
k Text
v Builder
o -> Builder
" " forall a. Semigroup a => a -> a -> a
<> Text -> Builder
encodeUtf8 Text
k forall a. Semigroup a => a -> a -> a
<> Builder
"=\"" forall a. Semigroup a => a -> a -> a
<> Text -> Builder
encodeXmlUtf8 Text
v forall a. Semigroup a => a -> a -> a
<> Builder
"\"" forall a. Semigroup a => a -> a -> a
<> Builder
o)
{-# INLINE encodeAttrs #-}
dfpos :: ((Node -> [Node]) -> Node -> [Node]) -> Node -> [Node]
dfpos :: ((Node -> [Node]) -> Node -> [Node]) -> Node -> [Node]
dfpos (Node -> [Node]) -> Node -> [Node]
f = forall a. Identity a -> a
runIdentity forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *).
Monad m =>
((Node -> m [Node]) -> Node -> m [Node]) -> Node -> m [Node]
dfposM (\Node -> Identity [Node]
k -> forall a. a -> Identity a
Identity forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Node -> [Node]) -> Node -> [Node]
f (forall a. Identity a -> a
runIdentity forall b c a. (b -> c) -> (a -> b) -> a -> c
. Node -> Identity [Node]
k))
dfposM :: Monad m => ((Node -> m [Node]) -> Node -> m [Node]) -> Node -> m [Node]
dfposM :: forall (m :: * -> *).
Monad m =>
((Node -> m [Node]) -> Node -> m [Node]) -> Node -> m [Node]
dfposM (Node -> m [Node]) -> Node -> m [Node]
f = \Node
n0 -> do
Cursor
c1 <- forall (m :: * -> *).
Monad m =>
(Node -> m [Node]) -> Cursor -> m Cursor
traverseChildren (forall (m :: * -> *).
Monad m =>
((Node -> m [Node]) -> Node -> m [Node]) -> Node -> m [Node]
dfposM (Node -> m [Node]) -> Node -> m [Node]
f) (Node -> Cursor
cursorFromNode Node
n0)
Cursor
c2 <- forall (m :: * -> *).
Monad m =>
(Node -> m [Node]) -> Cursor -> m Cursor
traverseRightSiblings (forall (m :: * -> *).
Monad m =>
((Node -> m [Node]) -> Node -> m [Node]) -> Node -> m [Node]
dfposM (Node -> m [Node]) -> Node -> m [Node]
f) Cursor
c1
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ([Node] -> [Node]
normalize forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a. Monad m => m (m a) -> m a
join)
(forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse ((Node -> m [Node]) -> Node -> m [Node]
f (forall (m :: * -> *).
Monad m =>
((Node -> m [Node]) -> Node -> m [Node]) -> Node -> m [Node]
dfposM (Node -> m [Node]) -> Node -> m [Node]
f)) (Cursor -> [Node]
cursorSiblings Cursor
c2))
dfpre :: ((Node -> [Node]) -> Node -> [Node]) -> Node -> [Node]
dfpre :: ((Node -> [Node]) -> Node -> [Node]) -> Node -> [Node]
dfpre (Node -> [Node]) -> Node -> [Node]
f = forall a. Identity a -> a
runIdentity forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *).
Monad m =>
((Node -> m [Node]) -> Node -> m [Node]) -> Node -> m [Node]
dfpreM (\Node -> Identity [Node]
k -> forall a. a -> Identity a
Identity forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Node -> [Node]) -> Node -> [Node]
f (forall a. Identity a -> a
runIdentity forall b c a. (b -> c) -> (a -> b) -> a -> c
. Node -> Identity [Node]
k))
dfpreM :: Monad m => ((Node -> m [Node]) -> Node -> m [Node]) -> Node -> m [Node]
dfpreM :: forall (m :: * -> *).
Monad m =>
((Node -> m [Node]) -> Node -> m [Node]) -> Node -> m [Node]
dfpreM (Node -> m [Node]) -> Node -> m [Node]
f = \Node
n0 -> do
[Node]
ns <- (Node -> m [Node]) -> Node -> m [Node]
f (forall (m :: * -> *).
Monad m =>
((Node -> m [Node]) -> Node -> m [Node]) -> Node -> m [Node]
dfpreM (Node -> m [Node]) -> Node -> m [Node]
f) Node
n0
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ([Node] -> [Node]
normalize forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a. Monad m => m (m a) -> m a
join) forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
t a -> (a -> f b) -> f (t b)
for [Node]
ns forall a b. (a -> b) -> a -> b
$ \Node
n -> do
Cursor
c1 <- forall (m :: * -> *).
Monad m =>
(Node -> m [Node]) -> Cursor -> m Cursor
traverseChildren (forall (m :: * -> *).
Monad m =>
((Node -> m [Node]) -> Node -> m [Node]) -> Node -> m [Node]
dfpreM (Node -> m [Node]) -> Node -> m [Node]
f) (Node -> Cursor
cursorFromNode Node
n)
Cursor -> [Node]
cursorSiblings forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *).
Monad m =>
(Node -> m [Node]) -> Cursor -> m Cursor
traverseRightSiblings (forall (m :: * -> *).
Monad m =>
((Node -> m [Node]) -> Node -> m [Node]) -> Node -> m [Node]
dfpreM (Node -> m [Node]) -> Node -> m [Node]
f) Cursor
c1
data Cursor = Cursor
{ Cursor -> Node
_cursorCurrent :: !Node
, Cursor -> Seq Node
_cursorLefts :: !(Seq Node)
, Cursor -> Seq Node
_cursorRights :: !(Seq Node)
, Cursor -> Seq (Seq Node, Text, HashMap Text Text, Seq Node)
_cursorParents :: !(Seq (Seq Node, T.Text, HM.HashMap T.Text T.Text, Seq Node))
}
traverseChildren :: Monad m => (Node -> m [Node]) -> Cursor -> m Cursor
{-# INLINABLE traverseChildren #-}
traverseChildren :: forall (m :: * -> *).
Monad m =>
(Node -> m [Node]) -> Cursor -> m Cursor
traverseChildren Node -> m [Node]
f Cursor
c0 = case Cursor -> Node
_cursorCurrent Cursor
c0 of
Text Text
_ -> forall (f :: * -> *) a. Applicative f => a -> f a
pure Cursor
c0
Element Text
t HashMap Text Text
as [Node]
cs -> do
[Node]
n1s <- forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ([Node] -> [Node]
normalize forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a. Monad m => m (m a) -> m a
join) (forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse Node -> m [Node]
f [Node]
cs)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Cursor
c0 {_cursorCurrent :: Node
_cursorCurrent = Text -> HashMap Text Text -> [Node] -> Node
Element' Text
t HashMap Text Text
as [Node]
n1s})
traverseRightSiblings :: Monad m => (Node -> m [Node]) -> Cursor -> m Cursor
{-# INLINABLE traverseRightSiblings #-}
traverseRightSiblings :: forall (m :: * -> *).
Monad m =>
(Node -> m [Node]) -> Cursor -> m Cursor
traverseRightSiblings Node -> m [Node]
f Cursor
c0 = case Cursor -> Maybe (Node, Cursor)
cursorRemoveRight Cursor
c0 of
Maybe (Node, Cursor)
Nothing -> forall (f :: * -> *) a. Applicative f => a -> f a
pure Cursor
c0
Just (Node
n1, Cursor
c1) -> do
[Node]
n2s <- forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Node] -> [Node]
normalize (Node -> m [Node]
f Node
n1)
forall (m :: * -> *).
Monad m =>
(Node -> m [Node]) -> Cursor -> m Cursor
traverseRightSiblings Node -> m [Node]
f ([Node] -> Cursor -> Cursor
cursorInsertManyRight [Node]
n2s Cursor
c1)
cursorFromNode :: Node -> Cursor
{-# INLINE cursorFromNode #-}
cursorFromNode :: Node -> Cursor
cursorFromNode Node
n = Node
-> Seq Node
-> Seq Node
-> Seq (Seq Node, Text, HashMap Text Text, Seq Node)
-> Cursor
Cursor Node
n forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty forall a. Monoid a => a
mempty
cursorSiblings :: Cursor -> [Node]
{-# INLINE cursorSiblings #-}
cursorSiblings :: Cursor -> [Node]
cursorSiblings (Cursor Node
cur Seq Node
ls Seq Node
rs Seq (Seq Node, Text, HashMap Text Text, Seq Node)
_) =
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (forall a. Seq a -> Seq a
Seq.reverse Seq Node
ls forall a. Semigroup a => a -> a -> a
<> (Node
cur forall a. a -> Seq a -> Seq a
Seq.<| Seq Node
rs))
cursorRemoveRight :: Cursor -> Maybe (Node, Cursor)
{-# INLINABLE cursorRemoveRight #-}
cursorRemoveRight :: Cursor -> Maybe (Node, Cursor)
cursorRemoveRight = \case
Cursor Node
n Seq Node
ls Seq Node
rs0 Seq (Seq Node, Text, HashMap Text Text, Seq Node)
ps | Bool -> Bool
not (forall a. Seq a -> Bool
Seq.null Seq Node
rs0) ->
case forall a. Seq a -> ViewL a
Seq.viewl Seq Node
rs0 of
Node
r Seq.:< Seq Node
rs -> forall a. a -> Maybe a
Just (Node
r, Node
-> Seq Node
-> Seq Node
-> Seq (Seq Node, Text, HashMap Text Text, Seq Node)
-> Cursor
Cursor Node
n Seq Node
ls Seq Node
rs Seq (Seq Node, Text, HashMap Text Text, Seq Node)
ps)
ViewL Node
_ -> forall a. HasCallStack => a
undefined
Cursor
_ -> forall a. Maybe a
Nothing
cursorInsertManyRight :: [Node] -> Cursor -> Cursor
{-# INLINE cursorInsertManyRight #-}
cursorInsertManyRight :: [Node] -> Cursor -> Cursor
cursorInsertManyRight [Node]
ns (Cursor Node
nn Seq Node
ls Seq Node
rs Seq (Seq Node, Text, HashMap Text Text, Seq Node)
ps) =
Node
-> Seq Node
-> Seq Node
-> Seq (Seq Node, Text, HashMap Text Text, Seq Node)
-> Cursor
Cursor Node
nn Seq Node
ls (forall a. [a] -> Seq a
Seq.fromList [Node]
ns forall a. Semigroup a => a -> a -> a
<> Seq Node
rs) Seq (Seq Node, Text, HashMap Text Text, Seq Node)
ps
encodeUtf8 :: T.Text -> BB.Builder
{-# INLINE encodeUtf8 #-}
encodeUtf8 :: Text -> Builder
encodeUtf8 = Text -> Builder
T.encodeUtf8Builder
encodeXmlUtf8 :: T.Text -> BB.Builder
{-# INLINE encodeXmlUtf8 #-}
encodeXmlUtf8 :: Text -> Builder
encodeXmlUtf8 = BoundedPrim Word8 -> Text -> Builder
T.encodeUtf8BuilderEscaped BoundedPrim Word8
xmlEscaped
encodeXmlUtf8Lazy :: TL.Text -> BB.Builder
{-# INLINE encodeXmlUtf8Lazy #-}
encodeXmlUtf8Lazy :: Text -> Builder
encodeXmlUtf8Lazy = BoundedPrim Word8 -> Text -> Builder
TL.encodeUtf8BuilderEscaped BoundedPrim Word8
xmlEscaped
xmlEscaped :: BBP.BoundedPrim Word8
{-# INLINE xmlEscaped #-}
xmlEscaped :: BoundedPrim Word8
xmlEscaped =
forall a.
(a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a
BBP.condB (forall a. Eq a => a -> a -> Bool
== Word8
38) ((Word8, (Word8, (Word8, (Word8, Word8)))) -> BoundedPrim Word8
fixed5 (Word8
38,(Word8
97,(Word8
109,(Word8
112,Word8
59))))) forall a b. (a -> b) -> a -> b
$
forall a.
(a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a
BBP.condB (forall a. Eq a => a -> a -> Bool
== Word8
60) ((Word8, (Word8, (Word8, Word8))) -> BoundedPrim Word8
fixed4 (Word8
38,(Word8
108,(Word8
116,Word8
59)))) forall a b. (a -> b) -> a -> b
$
forall a.
(a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a
BBP.condB (forall a. Eq a => a -> a -> Bool
== Word8
62) ((Word8, (Word8, (Word8, Word8))) -> BoundedPrim Word8
fixed4 (Word8
38,(Word8
103,(Word8
116,Word8
59)))) forall a b. (a -> b) -> a -> b
$
forall a.
(a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a
BBP.condB (forall a. Eq a => a -> a -> Bool
== Word8
34) ((Word8, (Word8, (Word8, (Word8, Word8)))) -> BoundedPrim Word8
fixed5 (Word8
38,(Word8
35,(Word8
51,(Word8
52,Word8
59))))) forall a b. (a -> b) -> a -> b
$
forall a. FixedPrim a -> BoundedPrim a
BBP.liftFixedToBounded FixedPrim Word8
BBP.word8
where
{-# INLINE fixed4 #-}
fixed4 :: (Word8, (Word8, (Word8, Word8))) -> BBP.BoundedPrim Word8
fixed4 :: (Word8, (Word8, (Word8, Word8))) -> BoundedPrim Word8
fixed4 (Word8, (Word8, (Word8, Word8)))
x = forall a. FixedPrim a -> BoundedPrim a
BBP.liftFixedToBounded
(forall a b. a -> b -> a
const (Word8, (Word8, (Word8, Word8)))
x forall (f :: * -> *) b a. Contravariant f => (b -> a) -> f a -> f b
BBP.>$< FixedPrim Word8
BBP.word8 forall (f :: * -> *) a b. Monoidal f => f a -> f b -> f (a, b)
BBP.>*< FixedPrim Word8
BBP.word8
forall (f :: * -> *) a b. Monoidal f => f a -> f b -> f (a, b)
BBP.>*< FixedPrim Word8
BBP.word8 forall (f :: * -> *) a b. Monoidal f => f a -> f b -> f (a, b)
BBP.>*< FixedPrim Word8
BBP.word8)
{-# INLINE fixed5 #-}
fixed5 :: (Word8, (Word8, (Word8, (Word8, Word8)))) -> BBP.BoundedPrim Word8
fixed5 :: (Word8, (Word8, (Word8, (Word8, Word8)))) -> BoundedPrim Word8
fixed5 (Word8, (Word8, (Word8, (Word8, Word8))))
x = forall a. FixedPrim a -> BoundedPrim a
BBP.liftFixedToBounded
(forall a b. a -> b -> a
const (Word8, (Word8, (Word8, (Word8, Word8))))
x forall (f :: * -> *) b a. Contravariant f => (b -> a) -> f a -> f b
BBP.>$< FixedPrim Word8
BBP.word8 forall (f :: * -> *) a b. Monoidal f => f a -> f b -> f (a, b)
BBP.>*< FixedPrim Word8
BBP.word8
forall (f :: * -> *) a b. Monoidal f => f a -> f b -> f (a, b)
BBP.>*< FixedPrim Word8
BBP.word8 forall (f :: * -> *) a b. Monoidal f => f a -> f b -> f (a, b)
BBP.>*< FixedPrim Word8
BBP.word8 forall (f :: * -> *) a b. Monoidal f => f a -> f b -> f (a, b)
BBP.>*< FixedPrim Word8
BBP.word8)
mapFromHashMap :: Ord k => HM.HashMap k v -> Map.Map k v
mapFromHashMap :: forall k v. Ord k => HashMap k v -> Map k v
mapFromHashMap = forall k v a. (k -> v -> a -> a) -> a -> HashMap k v -> a
HM.foldrWithKey' forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert forall k a. Map k a
Map.empty
{-# INLINE mapFromHashMap #-}