option.go raw
1 package yaml
2
3 import (
4 "io"
5
6 "github.com/goccy/go-yaml/ast"
7 )
8
9 // DecodeOption functional option type for Decoder
10 type DecodeOption func(d *Decoder) error
11
12 // ReferenceReaders pass to Decoder that reference to anchor defined by passed readers
13 func ReferenceReaders(readers ...io.Reader) DecodeOption {
14 return func(d *Decoder) error {
15 d.referenceReaders = append(d.referenceReaders, readers...)
16 return nil
17 }
18 }
19
20 // ReferenceFiles pass to Decoder that reference to anchor defined by passed files
21 func ReferenceFiles(files ...string) DecodeOption {
22 return func(d *Decoder) error {
23 d.referenceFiles = files
24 return nil
25 }
26 }
27
28 // ReferenceDirs pass to Decoder that reference to anchor defined by files under the passed dirs
29 func ReferenceDirs(dirs ...string) DecodeOption {
30 return func(d *Decoder) error {
31 d.referenceDirs = dirs
32 return nil
33 }
34 }
35
36 // RecursiveDir search yaml file recursively from passed dirs by ReferenceDirs option
37 func RecursiveDir(isRecursive bool) DecodeOption {
38 return func(d *Decoder) error {
39 d.isRecursiveDir = isRecursive
40 return nil
41 }
42 }
43
44 // Validator set StructValidator instance to Decoder
45 func Validator(v StructValidator) DecodeOption {
46 return func(d *Decoder) error {
47 d.validator = v
48 return nil
49 }
50 }
51
52 // Strict enable DisallowUnknownField and DisallowDuplicateKey
53 func Strict() DecodeOption {
54 return func(d *Decoder) error {
55 d.disallowUnknownField = true
56 d.disallowDuplicateKey = true
57 return nil
58 }
59 }
60
61 // DisallowUnknownField causes the Decoder to return an error when the destination
62 // is a struct and the input contains object keys which do not match any
63 // non-ignored, exported fields in the destination.
64 func DisallowUnknownField() DecodeOption {
65 return func(d *Decoder) error {
66 d.disallowUnknownField = true
67 return nil
68 }
69 }
70
71 // DisallowDuplicateKey causes an error when mapping keys that are duplicates
72 func DisallowDuplicateKey() DecodeOption {
73 return func(d *Decoder) error {
74 d.disallowDuplicateKey = true
75 return nil
76 }
77 }
78
79 // UseOrderedMap can be interpreted as a map,
80 // and uses MapSlice ( ordered map ) aggressively if there is no type specification
81 func UseOrderedMap() DecodeOption {
82 return func(d *Decoder) error {
83 d.useOrderedMap = true
84 return nil
85 }
86 }
87
88 // UseJSONUnmarshaler if neither `BytesUnmarshaler` nor `InterfaceUnmarshaler` is implemented
89 // and `UnmashalJSON([]byte)error` is implemented, convert the argument from `YAML` to `JSON` and then call it.
90 func UseJSONUnmarshaler() DecodeOption {
91 return func(d *Decoder) error {
92 d.useJSONUnmarshaler = true
93 return nil
94 }
95 }
96
97 // EncodeOption functional option type for Encoder
98 type EncodeOption func(e *Encoder) error
99
100 // Indent change indent number
101 func Indent(spaces int) EncodeOption {
102 return func(e *Encoder) error {
103 e.indent = spaces
104 return nil
105 }
106 }
107
108 // IndentSequence causes sequence values to be indented the same value as Indent
109 func IndentSequence(indent bool) EncodeOption {
110 return func(e *Encoder) error {
111 e.indentSequence = indent
112 return nil
113 }
114 }
115
116 // UseSingleQuote determines if single or double quotes should be preferred for strings.
117 func UseSingleQuote(sq bool) EncodeOption {
118 return func(e *Encoder) error {
119 e.singleQuote = sq
120 return nil
121 }
122 }
123
124 // Flow encoding by flow style
125 func Flow(isFlowStyle bool) EncodeOption {
126 return func(e *Encoder) error {
127 e.isFlowStyle = isFlowStyle
128 return nil
129 }
130 }
131
132 // UseLiteralStyleIfMultiline causes encoding multiline strings with a literal syntax,
133 // no matter what characters they include
134 func UseLiteralStyleIfMultiline(useLiteralStyleIfMultiline bool) EncodeOption {
135 return func(e *Encoder) error {
136 e.useLiteralStyleIfMultiline = useLiteralStyleIfMultiline
137 return nil
138 }
139 }
140
141 // JSON encode in JSON format
142 func JSON() EncodeOption {
143 return func(e *Encoder) error {
144 e.isJSONStyle = true
145 e.isFlowStyle = true
146 return nil
147 }
148 }
149
150 // MarshalAnchor call back if encoder find an anchor during encoding
151 func MarshalAnchor(callback func(*ast.AnchorNode, interface{}) error) EncodeOption {
152 return func(e *Encoder) error {
153 e.anchorCallback = callback
154 return nil
155 }
156 }
157
158 // UseJSONMarshaler if neither `BytesMarshaler` nor `InterfaceMarshaler`
159 // nor `encoding.TextMarshaler` is implemented and `MarshalJSON()([]byte, error)` is implemented,
160 // call `MarshalJSON` to convert the returned `JSON` to `YAML` for processing.
161 func UseJSONMarshaler() EncodeOption {
162 return func(e *Encoder) error {
163 e.useJSONMarshaler = true
164 return nil
165 }
166 }
167
168 // CommentPosition type of the position for comment.
169 type CommentPosition int
170
171 const (
172 CommentLinePosition CommentPosition = iota
173 CommentHeadPosition
174 )
175
176 func (p CommentPosition) String() string {
177 switch p {
178 case CommentLinePosition:
179 return "Line"
180 case CommentHeadPosition:
181 return "Head"
182 default:
183 return ""
184 }
185 }
186
187 // LineComment create a one-line comment for CommentMap.
188 func LineComment(text string) *Comment {
189 return &Comment{
190 Texts: []string{text},
191 Position: CommentLinePosition,
192 }
193 }
194
195 // HeadComment create a multiline comment for CommentMap.
196 func HeadComment(texts ...string) *Comment {
197 return &Comment{
198 Texts: texts,
199 Position: CommentHeadPosition,
200 }
201 }
202
203 // Comment raw data for comment.
204 type Comment struct {
205 Texts []string
206 Position CommentPosition
207 }
208
209 // CommentMap map of the position of the comment and the comment information.
210 type CommentMap map[string]*Comment
211
212 // WithComment add a comment using the location and text information given in the CommentMap.
213 func WithComment(cm CommentMap) EncodeOption {
214 return func(e *Encoder) error {
215 commentMap := map[*Path]*Comment{}
216 for k, v := range cm {
217 path, err := PathString(k)
218 if err != nil {
219 return err
220 }
221 commentMap[path] = v
222 }
223 e.commentMap = commentMap
224 return nil
225 }
226 }
227
228 // CommentToMap apply the position and content of comments in a YAML document to a CommentMap.
229 func CommentToMap(cm CommentMap) DecodeOption {
230 return func(d *Decoder) error {
231 if cm == nil {
232 return ErrInvalidCommentMapValue
233 }
234 d.toCommentMap = cm
235 return nil
236 }
237 }
238