Codebase list haskell-hsyaml / ee9e9cb
almost completed doc vijayphoenix 4 years ago
11 changed file(s) with 528 addition(s) and 93 deletion(s). Raw diff Collapse all Expand all
00 ## 0.2.0.0
11
2 * Changes in `Data.YAML` module
3 * YAML 1.2 Schema encoders (#21)
4 * New `ToYAML` class for encoding Haskell Data-types from which YAML nodes can be constructed (#20)
5 * New functions like `encodeNode`, `encodeNode'` for constructing AST.
6 * New functions like `encode`, `encode1`, `encodeStrict`, `encode1Strict` for supporting typeclass-based dumping
7 * Some ToYAML instances and other api
8 * Modify `typeMismatch` function to show error source location in error messages (#19)
9
210 * Changes in `Data.YAML.Event` module
11 * Preserve and round-trip Comments at Event level(#24)
12 * New `Comment` Event to preserve comments while parsing
13 * Some additional implementations to preserve and round-trip comments
14 * Fix issue #22
15 * New `EvPos` type for recording event and their corresponding position (#19)
16 * Preserve Flow Mapping and Flow sequence (#18)
17 * Features to preserve Literal/Folded ScalarStyle (#15)
18 * New `Chomp` type denoting Block Chomping Indicator
19 * New `IndentOfs` type denoting Block Indentation Indicator
320 * New `NodeStyle` type denoting flow/block style
421 * `Event(SequenceStart,MappingStart)` constructors now record `NodeStyle`
522 * `Style` type renamed to `ScalarType`
1229 duplicate keys (under the respective YAML schema) in YAML mappings
1330 as a loader-error (controllable via new
1431 `schemaResolverMappingDuplicates` schema property)
32
33 * Fix X38W testcase (#13, #14)
1534
1635 ---
1736
11 name: HsYAML
22 version: 0.2.0.0
33
4 synopsis: Pure Haskell YAML 1.2 parser
4 synopsis: Pure Haskell YAML 1.2 parsing and encoding library
55 homepage: https://github.com/hvr/HsYAML
66 bug-reports: https://github.com/hvr/HsYAML/issues
77 license: GPL-2
1616 tested-with: GHC==8.6.1, GHC==8.4.3, GHC==8.4.1, GHC==8.2.2, GHC==8.0.2, GHC==7.10.3, GHC==7.8.4, GHC==7.6.3, GHC==7.4.2
1717
1818 description:
19 @HsYAML@ is a [YAML 1.2](http://yaml.org/spec/1.2/spec.html) parser implementation for Haskell.
19 @HsYAML@ is a [YAML 1.2](http://yaml.org/spec/1.2/spec.html) parsing and encoding library.
2020 .
2121 Features of @HsYAML@ include:
2222 .
1212 , toList
1313 ) where
1414
15 -- | A difference list is a function that, given a list, returns the original
16 -- contents of the difference list prepended to the given list.
1517 newtype DList a = DList ([a] -> [a])
1618
19 -- | Convert a dlist to a list
1720 toList :: DList a -> [a]
1821 toList (DList dl) = dl []
1922
23 -- | Create dlist with a single element
2024 singleton :: a -> DList a
2125 singleton x = DList (x:)
2226
27 -- | Create a dlist containing no elements
2328 empty :: DList a
2429 empty = DList id
2530
31 -- | O(1). Append dlists
2632 append :: DList a -> DList a -> DList a
2733 append (DList xs) (DList ys) = DList (xs . ys)
22 {-# LANGUAGE BangPatterns #-}
33 {-# LANGUAGE RecordWildCards #-}
44
5
5 -- |
6 -- Copyright: © Herbert Valerio Riedel 2015-2018
7 -- SPDX-License-Identifier: GPL-2.0-or-later
8 --
69 module Data.YAML.Dumper
710 ( encodeNode
811 , encodeNode'
1720 import qualified Data.Map as Map
1821 import qualified Data.Text as T
1922
20
23 -- internal
2124 type EvList = [Either String Event]
2225 type Node2EvList = [Node ()] -> EvList
2326
3737 -- document ::= 'DocumentStart' node 'DocumentEnd'
3838 -- node ::= 'Alias'
3939 -- | 'Scalar'
40 -- | 'Comment'
4041 -- | sequence
4142 -- | mapping
4243 -- sequence ::= 'SequenceStart' node* 'SequenceEnd'
44 -- Copyright: © Herbert Valerio Riedel 2015-2018
55 -- SPDX-License-Identifier: GPL-2.0-or-later
66 --
7 -- Event-stream oriented YAML parsing API
7 -- Event-stream oriented YAML parsing and serializing API
88 module Data.YAML.Event
9 ( parseEvents
9 (
10 -- * Tutorial
11 -- $start
12
13 -- ** Parsing YAML Documents
14 -- $parsing
15 parseEvents
16
17 -- ** Serializing Events to YAML Character Stream
18 -- $serialize
1019 , writeEvents
1120 , writeEventsText
21
22 -- ** How to comment your yaml document for best results
23 -- $commenting
24
25 -- ** Event-stream Internals
1226 , EvStream
1327 , Event(..)
1428 , EvPos(..)
1529 , Directives(..)
1630 , ScalarStyle(..)
1731 , NodeStyle(..)
32 , Chomp(..)
33 , IndentOfs(..)
1834 , Tag, untagged, isUntagged, tagToText, mkTag
1935 , Anchor
2036 , Pos(..)
5470 mkTag'' "" = error "mkTag''"
5571 mkTag'' s = Tag (Just $! T.pack ("tag:yaml.org,2002:" ++ s))
5672
57
73 -- Returns the position corresponding to the 'Token'
5874 tok2pos :: Y.Token -> Pos
5975 tok2pos Y.Token { Y.tByteOffset = posByteOffset, Y.tCharOffset = posCharOffset, Y.tLine = posLine, Y.tLineChar = posColumn } = Pos {..}
6076
77 -- Construct a 'EvPos' from the given 'Event' and 'Pos'
6178 getEvPos :: Event -> Y.Token -> EvPos
6279 getEvPos ev tok = EvPos { eEvent = ev , ePos = tok2pos tok }
6380
81 -- Initial position('Pos' corresponding to the 'StreamStart')
6482 initPos :: Pos
6583 initPos = Pos { posByteOffset = 0 , posCharOffset = 0 , posLine = 1 , posColumn = 0 }
6684
85 -- Initial 'EvPos'
6786 initEvPos :: Event -> EvPos
6887 initEvPos ev = EvPos { eEvent = ev, ePos = initPos }
6988
89 -- Pair Event with the corresponding Event-Start Position.
7090 delayPos :: Pos -> EvStream -> EvStream
7191 delayPos _ [] = []
7292 delayPos pos (Right EvPos{ eEvent = a ,ePos = nextPos } : rest ) = (Right EvPos{ eEvent = a , ePos = pos}: delayPos nextPos rest)
109129
110130 -- | Parse YAML 'Event's from a lazy 'BS.L.ByteString'.
111131 --
132 -- The parsed Events allow us to round-trip at the event-level while preserving many features and presentation details like
133 -- 'Comment's,'ScalarStyle','NodeStyle', 'Anchor's, 'Directives' marker along with YAML document version,
134 -- 'Chomp'ing Indicator,Indentation Indicator ('IndentOfs') ,ordering, etc.
135 -- It does not preserve non-content white spaces.
136 --
112137 -- The input 'BS.L.ByteString' is expected to have a YAML 1.2 stream
113138 -- using the UTF-8, UTF-16 (LE or BE), or UTF-32 (LE or BE) encodings
114139 -- (which will be auto-detected).
140
115141 parseEvents :: BS.L.ByteString -> EvStream
116142 parseEvents = \bs0 -> delayPos initPos $ Right (initEvPos StreamStart) : (go0 $ filter (not . isWhite) $ Y.tokenize bs0 False)
117143 where
498524 ]
499525 unescape _ = Nothing
500526
527 --
528 -- $start
529 --
530 -- "Data.YAML" module provides us with API which allow us to interact with YAML data at the cost of some presentation details.
531 -- In contrast, this module provide us with API which gives us access to a other significant details like 'ScalarStyle's, 'NodeStyle's, 'Comment's, etc.
532 --
533 -- $parsing
534 --
535 -- Suppose you want to parse this YAML Document while preserving its format and comments
536 --
537 -- @
538 -- # Home runs
539 -- hr: 65
540 -- # Runs Batted In
541 -- rbi: 147
542 -- @
543 --
544 -- then you might want to use the function 'parseEvents'.
545 --
546 -- The following is a reference implementation of a function using 'parseEvents'.
547 -- It takes a YAML document as input and prints the parsed YAML 'Event's.
548 --
549 -- @
550 -- import Data.YAML.Event
551 -- import qualified Data.ByteString.Lazy as BS.L
552 --
553 -- printEvents :: BS.L.ByteString -> IO ()
554 -- printEvents input =
555 -- forM_ ('parseEvents' input) $ \ev -> case ev of
556 -- Left _ -> error "Failed to parse"
557 -- Right event -> print ('eEvent' event)
558 -- @
559 --
560 -- When we pass the above mentioned YAML document to the function /printEvents/ it outputs the following:
561 --
562 -- > StreamStart
563 -- > DocumentStart NoDirEndMarker
564 -- > MappingStart Nothing Nothing Block
565 -- > Comment " Home runs"
566 -- > Scalar Nothing Nothing Plain "hr"
567 -- > Scalar Nothing Nothing Plain "65"
568 -- > Comment " Runs Batted In"
569 -- > Scalar Nothing Nothing Plain "rbi"
570 -- > Scalar Nothing Nothing Plain "147"
571 -- > MappingEnd
572 -- > DocumentEnd False
573 -- > StreamEnd
574 --
575 -- Notice that now we have all the necessary details in the form of 'Event's.
576 --
577 -- We can now write simple functions to work with this data without losing any more details.
578 --
579 -- $serialize
580 --
581 -- Now, suppose we want to generate back the YAML document after playing with the Event-stream,
582 -- then you might want to use 'writeEvents'.
583 --
584 -- The following function takes a YAML document as a input and dumps it back to STDOUT after a round-trip.
585 --
586 -- @
587 -- import Data.YAML.Event
588 -- import qualified Data.YAML.Token as YT
589 -- import qualified Data.ByteString.Lazy as BS.L
590 --
591 -- yaml2yaml :: BS.L.ByteString -> IO ()
592 -- yaml2yaml input = case sequence $ parseEvents input of
593 -- Left _ -> error "Parsing Failure!"
594 -- Right events -> do
595 -- BS.L.hPutStr stdout (writeEvents YT.UTF8 (map eEvent events))
596 -- hFlush stdout
597 -- @
598 --
599 -- Let this be the sample document passed to the above function
600 --
601 -- @
602 -- # This is a 'Directives' Marker
603 -- ---
604 -- # All 'Comment's are preserved
605 -- date : 2019-07-12
606 -- bill-to : # 'Anchor' represents a map node
607 -- &id001
608 -- address:
609 -- lines: # This a Block 'Scalar' with 'Keep' chomping Indicator and 'IndentAuto' Indentant indicator
610 -- |+ # Extra Indentation (non-content white space) will not be preserved
611 -- Vijay
612 -- IIT Hyderabad
613 --
614 --
615 -- # Trailing newlines are a preserved here as they are a part of the 'Scalar' node
616 -- country : India
617 -- ship-to : # This is an 'Alias'
618 -- *id001
619 -- # Key is a 'Scalar' and Value is a Sequence
620 -- Other Details:
621 -- total: $ 3000
622 -- # 'Tag's are also preserved
623 -- Online Payment: !!bool True
624 -- product:
625 -- - Item1
626 -- # This comment is inside a Sequence
627 -- - Item2
628 -- ...
629 -- # 'DocumentEnd' True
630 -- # 'StreamEnd'
631 -- @
632 --
633 -- This function outputs the following
634 --
635 -- @
636 -- # This is a 'Directives' Marker
637 -- ---
638 -- # All 'Comment's are preserved
639 -- date: 2019-07-12
640 -- bill-to: # 'Anchor' represents a map node
641 -- &id001
642 -- address:
643 -- lines: # This a Block 'Scalar' with 'Keep' chomping Indicator and 'IndentAuto' Indentant indicator
644 -- # Extra Indentation (non-content white space) will not be preserved
645 -- |+
646 -- Vijay
647 -- IIT Hyderabad
648 --
649 --
650 -- # Trailing newlines are a preserved here as they are a part of the 'Scalar' node
651 -- country: India
652 -- ship-to: # This is an 'Alias'
653 -- *id001
654 -- # Key is a 'Scalar' and Value is a Sequence
655 -- Other Details:
656 -- total: $ 3000
657 -- # 'Tag's are also preserved
658 -- Online Payment: !!bool True
659 -- product:
660 -- - Item1
661 -- # This comment is inside a Sequence
662 -- - Item2
663 -- ...
664 -- # 'DocumentEnd' True
665 -- # 'StreamEnd'
666 -- @
667 --
668 -- $commenting
669 --
670 -- Round-tripping at event-level will preserve all the comments and their relative position in the YAML-document but still,
671 -- we lose some information like the exact indentation and the position at which the comments were present previously.
672 -- This information sometimes can be quiet important for human-perception of comments.
673 -- Below are some guildlines, so that you can avoid ambiguities.
674 --
675 -- 1) Always try to start your comment in a newline. This step will avoid most of the ambiguities.
676 --
677 -- 2) Comments automaticly get indented according to the level in which they are present. For example,
678 --
679 -- Input YAML-document
680 --
681 -- @
682 -- # Level 0
683 -- - a
684 -- # Level 0
685 -- - - a
686 -- # Level 1
687 -- - a
688 -- - - a
689 -- # Level 2
690 -- - a
691 -- @
692 --
693 -- After a round-trip looks like
694 --
695 -- @
696 -- # Level 0
697 -- - a
698 -- # Level 0
699 -- - - a
700 -- # Level 1
701 -- - a
702 -- - - a
703 -- # Level 2
704 -- - a
705 -- @
706 --
707 -- 3) Comments immediately after a 'Scalar' node, start from a newline. So avoid commenting just after a scalar ends, as it may lead to some ambiguity. For example,
708 --
709 -- Input YAML-document
710 --
711 -- @
712 -- - scalar # After scalar
713 -- - random : scalar # After scalar
714 -- key: 1
715 -- # not after scalar
716 -- - random : scalar
717 -- key: 1
718 -- - random : # not after scalar
719 -- scalar
720 -- # not after scalar
721 -- key: 1
722 -- @
723 --
724 -- After a round-trip looks like
725 --
726 -- @
727 -- - scalar
728 -- # After scalar
729 -- - random: scalar
730 -- # After scalar
731 -- key: 1
732 -- # not after scalar
733 -- - random: scalar
734 -- key: 1
735 -- - random: # not after scalar
736 -- scalar
737 -- # not after scalar
738 -- key: 1
739 -- @
740 --
741 -- 4) Similarly in flow-style, avoid commenting immediately after a /comma/ (@,@) seperator. Comments immediately after a /comma/ (@,@) seperator will start from a new line
742 --
743 -- Input YAML-document
744 --
745 -- @
746 -- {
747 -- # comment 0
748 -- Name: Vijay # comment 1
749 -- ,
750 -- # comment 2
751 -- age: 19, # comment 3
752 -- # comment 4
753 -- country: India # comment 5
754 -- }
755 -- @
756 --
757 -- After a round-trip looks like
758 --
759 -- @
760 -- {
761 -- # comment 0
762 -- Name: Vijay,
763 -- # comment 1
764 -- # comment 2
765 -- age: 19,
766 -- # comment 3
767 -- # comment 4
768 -- country: India,
769 -- # comment 5
770 -- }
771 -- @
772 --
773 -- 5) Avoid commenting in between syntatical elements. For example,
774 --
775 -- Input YAML-document
776 --
777 -- @
778 -- ? # Complex key starts
779 -- [
780 -- a,
781 -- b
782 -- ]
783 -- # Complex key ends
784 -- : # Complex Value starts
785 -- ? # Complex key starts
786 -- [
787 -- a,
788 -- b
789 -- ]
790 -- # Complex key ends
791 -- : # Simple value
792 -- a
793 -- # Complex value ends
794 -- @
795 --
796 -- After a round-trip looks like
797 --
798 -- @
799 -- ? # Complex key starts
800 -- [
801 -- a,
802 -- b
803 -- ]
804 -- : # Complex key ends
805 -- # Complex Value starts
806 --
807 -- ? # Complex key starts
808 -- [
809 -- a,
810 -- b
811 -- ]
812 -- : # Complex key ends
813 -- # Simple value
814 -- a
815 -- # Complex value ends
816 -- @
817 --
818 -- The above two YAML-documents, after parsing produce the same 'Event'-stream.
819 --
820 -- So, these are some limitation of this Format-preserving YAML processor.
00 {-# LANGUAGE Safe #-}
11
2 -- |
3 -- Copyright: © Herbert Valerio Riedel 2015-2018
4 -- SPDX-License-Identifier: GPL-2.0-or-later
5 --
26 module Data.YAML.Internal
37 ( Node(..)
48 , NodeId
343343 , ("-.INF", (-1/0))
344344 ]
345345
346
346 -- | Some tags specified in YAML 1.2
347347 tagNull, tagBool, tagStr, tagInt, tagFloat, tagSeq, tagMap, tagBang :: Tag
348348 tagNull = mkTag "tag:yaml.org,2002:null"
349349 tagStr = mkTag "tag:yaml.org,2002:str"
88 -- SPDX-License-Identifier: GPL-2.0-or-later
99 --
1010 -- Document oriented [YAML](http://yaml.org/spec/1.2/spec.html) parsing API inspired by [aeson](http://hackage.haskell.org/package/aeson).
11 --
12 -- === Overview
11
12 module Data.YAML
13 (
14
15 -- * Overview
16 -- $overview
17
18 -- * Quick Start Tutorial
19 -- $start
20
21 -- ** Decoding/Loading YAML document
22 -- $loading
23
24 -- ** Encoding/dumping
25 -- $dumping
26
27 -- * Typeclass-based resolving/decoding
28 decode
29 , decode1
30 , decodeStrict
31 , decode1Strict
32 , FromYAML(..)
33 , Parser
34 , parseEither
35 , typeMismatch
36
37 -- ** Accessors for YAML 'Mapping's
38 , Mapping
39 , (.:), (.:?), (.:!), (.!=)
40
41 -- * Typeclass-based dumping
42 , encode
43 , encode1
44 , encodeStrict
45 , encode1Strict
46 , ToYAML(..)
47
48 -- ** Accessors for encoding
49 , mapping
50 , (.=)
51
52 -- ** Prism-style parsers
53 , withSeq
54 , withBool
55 , withFloat
56 , withInt
57 , withNull
58 , withStr
59 , withMap
60
61 -- * \"Concrete\" AST
62 , decodeNode
63 , decodeNode'
64 , encodeNode
65 , encodeNode'
66 , Doc(Doc)
67 , Node(..)
68 , Scalar(..)
69
70 -- * YAML 1.2 Schema resolvers
71 , SchemaResolver(..)
72 , failsafeSchemaResolver
73 , jsonSchemaResolver
74 , coreSchemaResolver
75
76 -- * YAML 1.2 Schema encoders
77 , SchemaEncoder(..)
78 , failsafeSchemaEncoder
79 , jsonSchemaEncoder
80 , coreSchemaEncoder
81
82 -- * Generalised AST construction
83 , decodeLoader
84 , Loader(..)
85 , NodeId
86
87 ) where
88
89 import qualified Control.Monad.Fail as Fail
90 import qualified Data.ByteString as BS
91 import qualified Data.ByteString.Lazy as BS.L
92 import qualified Data.Map as Map
93 import Data.Maybe (listToMaybe)
94 import qualified Data.Text as T
95
96 import Data.YAML.Dumper
97 import Data.YAML.Event (Pos (..), isUntagged, tagToText)
98 import Data.YAML.Internal
99 import Data.YAML.Loader
100 import Data.YAML.Schema
101
102 import Util
103
104 -- $overview
13105 --
14106 -- The diagram below depicts the standard layers of a [YAML 1.2](http://yaml.org/spec/1.2/spec.html) processor. This module covers the upper /Native/ and /Representation/ layers, whereas the "Data.YAML.Event" and "Data.YAML.Token" modules provide access to the lower /Serialization/ and /Presentation/ layers respectively.
15107 --
16108 -- <<http://yaml.org/spec/1.2/overview2.png>>
17109 --
18 -- === Quick Start Tutorial
110 -- $start
111 --
112 -- This section contains basic information on the different ways to work with YAML data using this library.
113 --
114 -- $loading
115 --
116 -- We address the process of loading data from a YAML document as decoding.
19117 --
20118 -- Let's assume we want to decode (i.e. /load/) a simple YAML document
21119 --
50148 -- >>> decode "- name: Erik Weisz\n age: 52\n magic: True\n- name: Mina Crandon\n age: 53" :: Either String [[Person]]
51149 -- Right [[Person {name = "Erik Weisz", age = 52, magic = True},Person {name = "Mina Crandon", age = 53, magic = False}]]
52150 --
53 --
54 module Data.YAML
55 (
56 -- * Typeclass-based dumping
57 encode
58 , encode1
59 , encodeStrict
60 , encode1Strict
61 , ToYAML(..)
62
63 -- * Typeclass-based resolving/decoding
64 , decode
65 , decode1
66 , decodeStrict
67 , decode1Strict
68 , FromYAML(..)
69 , Parser
70 , parseEither
71 , typeMismatch
72
73 -- ** Accessors for YAML 'Mapping's
74 , Mapping
75 , (.:), (.:?), (.:!), (.!=)
76
77 , mapping
78 , (.=)
79
80 -- ** Prism-style parsers
81 , withSeq
82 , withBool
83 , withFloat
84 , withInt
85 , withNull
86 , withStr
87 , withMap
88
89 -- * \"Concrete\" AST
90 , decodeNode
91 , decodeNode'
92 , encodeNode
93 , encodeNode'
94 , Doc(Doc)
95 , Node(..)
96 , Scalar(..)
97
98 -- * YAML 1.2 Schema resolvers
99 , SchemaResolver(..)
100 , failsafeSchemaResolver
101 , jsonSchemaResolver
102 , coreSchemaResolver
103
104 -- * YAML 1.2 Schema encoders
105 , SchemaEncoder(..)
106 , failsafeSchemaEncoder
107 , jsonSchemaEncoder
108 , coreSchemaEncoder
109
110 -- * Generalised AST construction
111 , decodeLoader
112 , Loader(..)
113 , NodeId
114
115 ) where
116
117 import qualified Control.Monad.Fail as Fail
118 import qualified Data.ByteString as BS
119 import qualified Data.ByteString.Lazy as BS.L
120 import qualified Data.Map as Map
121 import Data.Maybe (listToMaybe)
122 import qualified Data.Text as T
123
124 import Data.YAML.Dumper
125 import Data.YAML.Event (Pos (..), isUntagged, tagToText)
126 import Data.YAML.Internal
127 import Data.YAML.Loader
128 import Data.YAML.Schema
129
130 import Util
151 -- There are predefined 'FromYAML' instance for many types.
152 --
153 -- The example below shows decoding multiple YAML documents into a list of 'Int' lists:
154 --
155 -- >>> decode "---\n- 1\n- 2\n- 3\n---\n- 4\n- 5\n- 6" :: Either String [[Int]]
156 -- Right [[1,2,3],[4,5,6]]
157 --
158 -- If you are expecting exactly one YAML document then you can use convenience function 'decode1'
159 --
160 -- >>> decode1 "- 1\n- 2\n- 3\n" :: Either String [Int]
161 -- Right [1,2,3]
162 --
163 -- == Working with AST
164 --
165 -- Sometimes we want to work with YAML data directly, without first converting it to a custom data type.
166 --
167 -- We can easily do that by using the 'Node' type, which is an instance of 'FromYAML', is used to represent an arbitrary YAML AST (abstract syntax tree). For example,
168 --
169 -- >>> decode1 "Name: Vijay" :: Either String (Node Pos)
170 -- Right (Mapping (Pos {posByteOffset = 0, posCharOffset = 0, posLine = 1, posColumn = 0}) Just "tag:yaml.org,2002:map" (fromList [(Scalar (Pos {posByteOffset = 0, posCharOffset = 0, posLine = 1, posColumn = 0}) (SStr "Name"),Scalar (Pos {posByteOffset = 4, posCharOffset = 4, posLine = 1, posColumn = 4}) (SStr "Vijay"))]))
171 --
172 -- The type parameter 'Pos' is used to indicate the position of each YAML 'Node' in the document.
173 -- So using the 'Node' type we can easily decode any YAML document.
174
131175
132176 -- | Retrieve value in 'Mapping' indexed by a @!!str@ 'Text' key.
133177 --
511555
512556
513557
558 -- $dumping
559 --
560 -- We address the process of dumping information from a Haskell-data type(s) to a YAML document(s) as encoding.
561 --
562 -- Suppose we want to encode a Haskell-data type Person
563 -- @
564 -- data Person = Person {
565 -- name :: Text
566 -- , age :: Int
567 -- } deriving Show
568 --
569 -- To encode data, we need to define a 'ToYAML' instance.
570 -- @
571 -- @
572 -- instance 'ToYAML' Person where
573 -- \-- this generates a 'Node'
574 -- 'toYAML' (Person n a) = 'mapping' [ "name" .= n, "age" .= a]
575 -- @
576 -- We can now encode a value like so:
577 --
578 -- >>> encode [Person {name = "Vijay", age = 19})
579 -- "age: 19\nname: Vijay\n"
580 --
581 -- There are predefined 'ToYAML' instances for many types. Here's an example encoding a complex Haskell Node'
582 --
583 -- >>> encode1 $ toYAML ([1,2,3],Data.Map.fromList [(1, 2)])
584 -- "- - 1\n - 2\n - 3\n- 1: 2\n"
585 --
586
587
514588 -- | A type from which YAML nodes can be constructed
515589 --
516590 -- @since 0.2.0.0
6060
6161
6262 #if !MIN_VERSION_base(4,6,0)
63
64 -- | Parse a string using the Read instance. Succeeds if there is
65 -- exactly one valid result.
6366 readMaybe :: Read a => String -> Maybe a
6467 readMaybe = either (const Nothing) id . readEither
6568
69 -- | Parse a string using the Read instance. Succeeds if there is
70 -- exactly one valid result. A Left value indicates a parse error.
6671 readEither :: Read a => String -> Either String a
6772 readEither s = case [ x | (x,"") <- readPrec_to_S read' minPrec s ] of
6873 [x] -> Right x
7479 return x
7580 #endif
7681
77
82 -- | Succeeds if the Integral value is in the bounds of the given Data type.
83 -- A Nothing indicates that the value is outside the bounds.
7884 fromIntegerMaybe :: forall n . (Integral n, Bounded n) => Integer -> Maybe n
7985 fromIntegerMaybe j
8086 | l <= j, j <= u = Just (fromInteger j)
8490 l = toInteger (minBound :: n)
8591
8692
87
93 -- | A convience wrapper over 'mapInsertNoDupe'
8894 mapFromListNoDupes :: Ord k => [(k,a)] -> Either (k,a) (Map k a)
8995 mapFromListNoDupes = go mempty
9096 where
9399 Nothing -> Left (k,v)
94100 Just m' -> go m' rest
95101
102 -- | A convience wrapper over Data.Map.insertLookupWithKey
96103 mapInsertNoDupe :: Ord k => k -> a -> Map k a -> Maybe (Map k a)
97104 mapInsertNoDupe kx x t = case Map.insertLookupWithKey (\_ a _ -> a) kx x t of
98105 (Nothing, m) -> Just m
99106 (Just _, _) -> Nothing
100107
101108
109 -- | Equivalent to the fuction Data.ByteString.toStrict.
110 -- O(n) Convert a lazy ByteString into a strict ByteString.
102111 {-# INLINE bsToStrict #-}
103112 bsToStrict :: BS.L.ByteString -> BS.ByteString
104113 #if MIN_VERSION_bytestring(0,10,0)
174174 Left (ofs,msg) -> do
175175 hPutStrLn stderr ("Parsing error near byte offset " ++ show ofs ++ if null msg then "" else " (" ++ msg ++ ")")
176176 exitFailure
177 Right event -> do
178 print (eEvent event)
177 Right event -> print (eEvent event)
179178 -- hPutStrLn stdout (ev2str True (eEvent event))
180179 -- hFlush stdout
181180