{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE Safe #-}
module Data.YAML.Dumper
( encodeNode
, encodeNode'
) where
import Data.YAML.Event.Internal as YE
import Data.YAML.Event.Writer (writeEvents)
import Data.YAML.Internal as YI
import Data.YAML.Schema.Internal as YS
import qualified Data.ByteString.Lazy as BS.L
import qualified Data.Map as Map
import qualified Data.Text as T
type EvList = [Either String Event]
type Node2EvList = [Node ()] -> EvList
encodeNode :: [Doc (Node ())] -> BS.L.ByteString
encodeNode :: [Doc (Node ())] -> ByteString
encodeNode = SchemaEncoder -> Encoding -> [Doc (Node ())] -> ByteString
encodeNode' SchemaEncoder
coreSchemaEncoder Encoding
UTF8
encodeNode' :: SchemaEncoder -> Encoding -> [Doc (Node ())] -> BS.L.ByteString
encodeNode' :: SchemaEncoder -> Encoding -> [Doc (Node ())] -> ByteString
encodeNode' SchemaEncoder{Tag -> Either String Tag
Scalar -> Either String (Tag, ScalarStyle, Text)
schemaEncoderMapping :: SchemaEncoder -> Tag -> Either String Tag
schemaEncoderSequence :: SchemaEncoder -> Tag -> Either String Tag
schemaEncoderScalar :: SchemaEncoder -> Scalar -> Either String (Tag, ScalarStyle, Text)
schemaEncoderMapping :: Tag -> Either String Tag
schemaEncoderSequence :: Tag -> Either String Tag
schemaEncoderScalar :: Scalar -> Either String (Tag, ScalarStyle, Text)
..} Encoding
encoding [Doc (Node ())]
nodes = Encoding -> [Event] -> ByteString
writeEvents Encoding
encoding ([Event] -> ByteString) -> [Event] -> ByteString
forall a b. (a -> b) -> a -> b
$ (Either String Event -> Event) -> [Either String Event] -> [Event]
forall a b. (a -> b) -> [a] -> [b]
map Either String Event -> Event
getEvent (Node2EvList
dumpEvents ((Doc (Node ()) -> Node ()) -> [Doc (Node ())] -> [Node ()]
forall a b. (a -> b) -> [a] -> [b]
map Doc (Node ()) -> Node ()
forall n. Doc n -> n
docRoot [Doc (Node ())]
nodes))
where
getEvent :: Either String Event -> Event
getEvent :: Either String Event -> Event
getEvent = \Either String Event
x -> case Either String Event
x of
Right Event
ev -> Event
ev
Left String
str -> String -> Event
forall a. HasCallStack => String -> a
error String
str
dumpEvents :: Node2EvList
dumpEvents :: Node2EvList
dumpEvents [Node ()]
nodes' = Event -> Either String Event
forall a b. b -> Either a b
Right Event
StreamStartEither String Event
-> [Either String Event] -> [Either String Event]
forall a. a -> [a] -> [a]
: Node2EvList
go0 [Node ()]
nodes'
where
go0 :: [Node ()] -> EvList
go0 :: Node2EvList
go0 [] = [Event -> Either String Event
forall a b. b -> Either a b
Right Event
StreamEnd]
go0 [Node ()]
n = Event -> Either String Event
forall a b. b -> Either a b
Right (Directives -> Event
DocumentStart Directives
NoDirEndMarker)Either String Event
-> [Either String Event] -> [Either String Event]
forall a. a -> [a] -> [a]
: Int -> [Node ()] -> Node2EvList -> [Either String Event]
goNode (Int
0 :: Int) [Node ()]
n (\[Node ()]
ev -> Node2EvList
go0 [Node ()]
ev)
goNode :: Int -> [Node ()] -> Node2EvList -> EvList
goNode :: Int -> [Node ()] -> Node2EvList -> [Either String Event]
goNode Int
_ [] Node2EvList
_ = [String -> Either String Event
forall a b. a -> Either a b
Left String
"Dumper: unexpected pattern in goNode"]
goNode Int
lvl (Node ()
node: [Node ()]
rest) Node2EvList
cont = case Node ()
node of
YI.Scalar ()
_ Scalar
scalar -> Scalar -> Maybe Text -> Either String Event
goScalar Scalar
scalar Maybe Text
forall a. Maybe a
NothingEither String Event
-> [Either String Event] -> [Either String Event]
forall a. a -> [a] -> [a]
: Int -> [Node ()] -> Node2EvList -> [Either String Event]
isDocEnd Int
lvl [Node ()]
rest Node2EvList
cont
Mapping ()
_ Tag
tag Mapping ()
m -> Event -> Either String Event
forall a b. b -> Either a b
Right (Maybe Text -> Tag -> NodeStyle -> Event
MappingStart Maybe Text
forall a. Maybe a
Nothing ((Tag -> Either String Tag) -> Tag -> Tag
getTag Tag -> Either String Tag
schemaEncoderMapping Tag
tag) NodeStyle
Block) Either String Event
-> [Either String Event] -> [Either String Event]
forall a. a -> [a] -> [a]
: Int
-> Mapping () -> [Node ()] -> Node2EvList -> [Either String Event]
goMap (Int
lvl Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Mapping ()
m [Node ()]
rest Node2EvList
cont
Sequence ()
_ Tag
tag [Node ()]
s -> Event -> Either String Event
forall a b. b -> Either a b
Right (Maybe Text -> Tag -> NodeStyle -> Event
SequenceStart Maybe Text
forall a. Maybe a
Nothing ((Tag -> Either String Tag) -> Tag -> Tag
getTag Tag -> Either String Tag
schemaEncoderSequence Tag
tag) NodeStyle
Block) Either String Event
-> [Either String Event] -> [Either String Event]
forall a. a -> [a] -> [a]
: Int
-> [Node ()] -> [Node ()] -> Node2EvList -> [Either String Event]
goSeq (Int
lvl Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) [Node ()]
s [Node ()]
rest Node2EvList
cont
Anchor ()
_ NodeId
nid Node ()
n -> Int
-> NodeId
-> Node ()
-> [Node ()]
-> Node2EvList
-> [Either String Event]
goAnchor Int
lvl NodeId
nid Node ()
n [Node ()]
rest Node2EvList
cont
goScalar :: YS.Scalar -> Maybe Anchor -> Either String Event
goScalar :: Scalar -> Maybe Text -> Either String Event
goScalar Scalar
s Maybe Text
anc = case Scalar -> Either String (Tag, ScalarStyle, Text)
schemaEncoderScalar Scalar
s of
Right (Tag
t, ScalarStyle
sty, Text
text) -> Event -> Either String Event
forall a b. b -> Either a b
Right (Maybe Text -> Tag -> ScalarStyle -> Text -> Event
YE.Scalar Maybe Text
anc Tag
t ScalarStyle
sty Text
text)
Left String
err -> String -> Either String Event
forall a b. a -> Either a b
Left String
err
goMap :: Int -> Mapping () -> [Node ()] -> Node2EvList -> EvList
goMap :: Int
-> Mapping () -> [Node ()] -> Node2EvList -> [Either String Event]
goMap Int
lvl Mapping ()
m [Node ()]
rest Node2EvList
cont = case (Mapping () -> [Node ()]
forall a. Map a a -> [a]
mapToList Mapping ()
m) of
[] -> Event -> Either String Event
forall a b. b -> Either a b
Right Event
MappingEnd Either String Event
-> [Either String Event] -> [Either String Event]
forall a. a -> [a] -> [a]
: Int -> [Node ()] -> Node2EvList -> [Either String Event]
isDocEnd (Int
lvl Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) [Node ()]
rest Node2EvList
cont
[Node ()]
list -> Int -> [Node ()] -> Node2EvList -> [Either String Event]
goNode Int
lvl [Node ()]
list Node2EvList
g
where
g :: Node2EvList
g [] = Event -> Either String Event
forall a b. b -> Either a b
Right Event
MappingEnd Either String Event
-> [Either String Event] -> [Either String Event]
forall a. a -> [a] -> [a]
: Int -> [Node ()] -> Node2EvList -> [Either String Event]
isDocEnd (Int
lvl Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) [Node ()]
rest Node2EvList
cont
g [Node ()]
rest' = Int -> [Node ()] -> Node2EvList -> [Either String Event]
goNode Int
lvl [Node ()]
rest' Node2EvList
g
mapToList :: Map a a -> [a]
mapToList = (a -> a -> [a] -> [a]) -> [a] -> Map a a -> [a]
forall k a b. (k -> a -> b -> b) -> b -> Map k a -> b
Map.foldrWithKey (\a
k a
v [a]
a -> a
k a -> [a] -> [a]
forall a. a -> [a] -> [a]
: a
v a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
a) []
goSeq :: Int -> [Node ()] -> [Node ()] -> Node2EvList -> EvList
goSeq :: Int
-> [Node ()] -> [Node ()] -> Node2EvList -> [Either String Event]
goSeq Int
lvl [] [Node ()]
rest Node2EvList
cont = Event -> Either String Event
forall a b. b -> Either a b
Right Event
SequenceEnd Either String Event
-> [Either String Event] -> [Either String Event]
forall a. a -> [a] -> [a]
: Int -> [Node ()] -> Node2EvList -> [Either String Event]
isDocEnd (Int
lvl Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) [Node ()]
rest Node2EvList
cont
goSeq Int
lvl [Node ()]
nod [Node ()]
rest Node2EvList
cont = Int -> [Node ()] -> Node2EvList -> [Either String Event]
goNode Int
lvl [Node ()]
nod Node2EvList
g
where
g :: Node2EvList
g [] = Event -> Either String Event
forall a b. b -> Either a b
Right Event
SequenceEnd Either String Event
-> [Either String Event] -> [Either String Event]
forall a. a -> [a] -> [a]
: Int -> [Node ()] -> Node2EvList -> [Either String Event]
isDocEnd (Int
lvl Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) [Node ()]
rest Node2EvList
cont
g [Node ()]
rest' = Int -> [Node ()] -> Node2EvList -> [Either String Event]
goNode Int
lvl [Node ()]
rest' Node2EvList
g
goAnchor :: Int -> NodeId -> Node () -> [Node ()] -> Node2EvList -> EvList
goAnchor :: Int
-> NodeId
-> Node ()
-> [Node ()]
-> Node2EvList
-> [Either String Event]
goAnchor Int
lvl NodeId
nid Node ()
nod [Node ()]
rest Node2EvList
cont = case Node ()
nod of
YI.Scalar ()
_ Scalar
scalar -> Scalar -> Maybe Text -> Either String Event
goScalar Scalar
scalar (NodeId -> Maybe Text
ancName NodeId
nid)Either String Event
-> [Either String Event] -> [Either String Event]
forall a. a -> [a] -> [a]
: Int -> [Node ()] -> Node2EvList -> [Either String Event]
isDocEnd Int
lvl [Node ()]
rest Node2EvList
cont
Mapping ()
_ Tag
tag Mapping ()
m -> Event -> Either String Event
forall a b. b -> Either a b
Right (Maybe Text -> Tag -> NodeStyle -> Event
MappingStart (NodeId -> Maybe Text
ancName NodeId
nid) ((Tag -> Either String Tag) -> Tag -> Tag
getTag Tag -> Either String Tag
schemaEncoderMapping Tag
tag) NodeStyle
Block) Either String Event
-> [Either String Event] -> [Either String Event]
forall a. a -> [a] -> [a]
: Int
-> Mapping () -> [Node ()] -> Node2EvList -> [Either String Event]
goMap (Int
lvl Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Mapping ()
m [Node ()]
rest Node2EvList
cont
Sequence ()
_ Tag
tag [Node ()]
s -> Event -> Either String Event
forall a b. b -> Either a b
Right (Maybe Text -> Tag -> NodeStyle -> Event
SequenceStart (NodeId -> Maybe Text
ancName NodeId
nid) ((Tag -> Either String Tag) -> Tag -> Tag
getTag Tag -> Either String Tag
schemaEncoderSequence Tag
tag) NodeStyle
Block) Either String Event
-> [Either String Event] -> [Either String Event]
forall a. a -> [a] -> [a]
: Int
-> [Node ()] -> [Node ()] -> Node2EvList -> [Either String Event]
goSeq (Int
lvl Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) [Node ()]
s [Node ()]
rest Node2EvList
cont
Anchor ()
_ NodeId
_ Node ()
_ -> String -> Either String Event
forall a b. a -> Either a b
Left String
"Anchor has a anchor node" Either String Event
-> [Either String Event] -> [Either String Event]
forall a. a -> [a] -> [a]
: (Node2EvList
cont [Node ()]
rest)
isDocEnd :: Int -> [Node ()] -> Node2EvList -> EvList
isDocEnd :: Int -> [Node ()] -> Node2EvList -> [Either String Event]
isDocEnd Int
lvl [Node ()]
rest Node2EvList
cont = if Int
lvl Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then Event -> Either String Event
forall a b. b -> Either a b
Right (Bool -> Event
DocumentEnd ([Node ()]
rest [Node ()] -> [Node ()] -> Bool
forall a. Eq a => a -> a -> Bool
/= []))Either String Event
-> [Either String Event] -> [Either String Event]
forall a. a -> [a] -> [a]
: (Node2EvList
cont [Node ()]
rest) else (Node2EvList
cont [Node ()]
rest)
ancName :: NodeId -> Maybe Anchor
ancName :: NodeId -> Maybe Text
ancName NodeId
nid
| NodeId
nid NodeId -> NodeId -> Bool
forall a. Eq a => a -> a -> Bool
== (NodeId
0NodeId -> NodeId -> NodeId
forall a. Num a => a -> a -> a
-NodeId
1) = Maybe Text
forall a. Maybe a
Nothing
| Bool
otherwise = Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$! String -> Text
T.pack (String
"a" String -> String -> String
forall a. [a] -> [a] -> [a]
++ NodeId -> String
forall a. Show a => a -> String
show NodeId
nid)
getTag :: (Tag -> Either String Tag) -> Tag -> Tag
getTag :: (Tag -> Either String Tag) -> Tag -> Tag
getTag Tag -> Either String Tag
f Tag
tag = case Tag -> Either String Tag
f Tag
tag of
Right Tag
t -> Tag
t
Left String
err -> String -> Tag
forall a. HasCallStack => String -> a
error String
err