Pure OCaml Yaml 1.2 reader and writer using Bytesrw

odoc

+30 -24
+29 -23
doc/tutorial.html
··· 80 80 (&quot;active&quot;, `Bool true); 81 81 (&quot;score&quot;, `Float 95.5) 82 82 ];; 83 - val data : [&gt; `Bool of bool | `Float of float | `O of (string * 'a) list | `String of string ] as 'a = 83 + val data : 84 + [&gt; `O of 85 + (string * [&gt; `Bool of bool | `Float of float | `String of string ]) 86 + list ] = 84 87 `O 85 88 [(&quot;name&quot;, `String &quot;Bob&quot;); (&quot;active&quot;, `Bool true); (&quot;score&quot;, `Float 95.5)] 86 89 # print_string (to_string data);; ··· 95 98 &quot;debug&quot;, Util.bool true; 96 99 &quot;tags&quot;, Util.strings [&quot;api&quot;; &quot;v2&quot;] 97 100 ];; 98 - val config : Util.t = 101 + val config : Value.t = 99 102 `O 100 103 [(&quot;server&quot;, `O [(&quot;host&quot;, `String &quot;0.0.0.0&quot;); (&quot;port&quot;, `Float 8080.)]); 101 - (&quot;debug&quot;, `Bool true); 102 - (&quot;tags&quot;, `A [`String &quot;api&quot;; `String &quot;v2&quot;])] 104 + (&quot;debug&quot;, `Bool true); (&quot;tags&quot;, `A [`String &quot;api&quot;; `String &quot;v2&quot;])] 103 105 # print_string (to_string config);; 104 106 server: 105 107 host: 0.0.0.0 ··· 110 112 - v2 111 113 - : unit = ()</code></pre><h3 id="controlling-output-style"><a href="#controlling-output-style" class="anchor"></a>Controlling Output Style</h3><p>You can control the output format with style options:</p><pre class="language-ocaml"><code># print_string (to_string ~layout_style:`Flow config);; 112 114 {server: {host: 0.0.0.0, port: 8080}, debug: true, tags: [api, v2</code></pre><ul><li>: unit = ()</li></ul><p>Scalar styles control how strings are written:</p><pre class="language-ocaml"><code># print_string (to_string ~scalar_style:`Double_quoted (Util.string &quot;hello&quot;));; 113 - &quot;hello&quot; 115 + hello 114 116 - : unit = () 115 117 # print_string (to_string ~scalar_style:`Single_quoted (Util.string &quot;hello&quot;));; 116 - 'hello' 118 + hello 117 119 - : unit = ()</code></pre><h2 id="full-yaml-representation"><a href="#full-yaml-representation" class="anchor"></a>Full YAML Representation</h2><p>The <code>Yamlrw.value</code> type is convenient but loses some YAML-specific information. For full fidelity, use the <code>Yamlrw.yaml</code> type:</p><pre class="language-ocaml"><code># let full = yaml_of_string ~resolve_aliases:false &quot;hello&quot;;; 118 120 val full : yaml = `Scalar &lt;abstr&gt;</code></pre><p>The <code>Yamlrw.yaml</code> type preserves:</p><ul><li>Scalar styles (plain, quoted, literal, folded)</li><li>Anchors and aliases</li><li>Type tags</li><li>Collection styles (block vs flow)</li></ul><h3 id="scalars-with-metadata"><a href="#scalars-with-metadata" class="anchor"></a>Scalars with Metadata</h3><pre class="language-ocaml"><code># let s = yaml_of_string ~resolve_aliases:false &quot;'quoted string'&quot;;; 119 121 val s : yaml = `Scalar &lt;abstr&gt; ··· 175 177 - : int = 2</code></pre><p>The <code>---</code> marker starts a document, and <code>...</code> optionally ends it.</p><h3 id="working-with-documents"><a href="#working-with-documents" class="anchor"></a>Working with Documents</h3><p>Each document has metadata and a root value:</p><pre class="language-ocaml"><code># List.map (fun d -&gt; Document.root d) docs;; 176 178 - : Yaml.t option list = 177 179 [Some (`O &lt;abstr&gt;); Some (`O &lt;abstr&gt;)]</code></pre><h3 id="serializing-multiple-documents"><a href="#serializing-multiple-documents" class="anchor"></a>Serializing Multiple Documents</h3><pre class="language-ocaml"><code># let doc1 = Document.make (Some (of_json (Util.obj [&quot;x&quot;, Util.int 1])));; 178 - val doc1 : Document.t = {Yamlrw.version = None; tags = []; root = Some (`O &lt;abstr&gt;); implicit_start = true; implicit_end = true} 180 + val doc1 : Document.t = 181 + {Document.version = None; tags = []; root = Some (`O &lt;abstr&gt;); 182 + implicit_start = true; implicit_end = true} 179 183 # let doc2 = Document.make (Some (of_json (Util.obj [&quot;x&quot;, Util.int 2])));; 180 - val doc2 : Document.t = {Yamlrw.version = None; tags = []; root = Some (`O &lt;abstr&gt;); implicit_start = true; implicit_end = true} 184 + val doc2 : Document.t = 185 + {Document.version = None; tags = []; root = Some (`O &lt;abstr&gt;); 186 + implicit_start = true; implicit_end = true} 181 187 # print_string (documents_to_string [doc1; doc2]);; 182 188 x: 1 183 189 --- ··· 186 192 val parser : Stream.parser = &lt;abstr&gt;</code></pre><p>Iterate over events:</p><pre class="language-ocaml"><code># Stream.iter (fun event _ _ -&gt; 187 193 Format.printf &quot;%a@.&quot; Event.pp event 188 194 ) parser;; 189 - Stream_start `Utf8 190 - Document_start { version = None; implicit = true } 191 - Mapping_start { anchor = None; tag = None; implicit = true; style = Block } 192 - Scalar { value = &quot;key&quot;; anchor = None; tag = None; plain_implicit = true; quoted_implicit = false; style = Plain } 193 - Scalar { value = &quot;value&quot;; anchor = None; tag = None; plain_implicit = true; quoted_implicit = false; style = Plain } 194 - Mapping_end 195 - Document_end { implicit = true } 196 - Stream_end 195 + stream-start(UTF-8) 196 + document-start(version=none, implicit=true) 197 + mapping-start(anchor=none, tag=none, implicit=true, style=block) 198 + scalar(anchor=none, tag=none, style=plain, value=&quot;key&quot;) 199 + scalar(anchor=none, tag=none, style=plain, value=&quot;value&quot;) 200 + mapping-end 201 + document-end(implicit=true) 202 + stream-end 197 203 - : unit = ()</code></pre><h3 id="building-yaml-with-events"><a href="#building-yaml-with-events" class="anchor"></a>Building YAML with Events</h3><p>You can also emit YAML by sending events:</p><pre class="language-ocaml"><code># let emitter = Stream.emitter ();; 198 204 val emitter : Stream.emitter = &lt;abstr&gt; 199 205 # Stream.stream_start emitter `Utf8;; ··· 219 225 &quot;ok&quot; 220 226 with Yamlrw_error e -&gt; 221 227 Error.to_string e;; 222 - - : string = 223 - &quot;Parse error at line 1, column 15: while parsing a flow sequence, expected ',' or ']', but got end of stream&quot;</code></pre><h3 id="type-errors"><a href="#type-errors" class="anchor"></a>Type Errors</h3><p>The <code>Yamlrw.Util</code> module raises <code>Yamlrw.Util.Type_error</code> for type mismatches:</p><pre class="language-ocaml"><code># try 228 + - : string = &quot;expected sequence end ']' at line 1, columns 15-15&quot;</code></pre><h3 id="type-errors"><a href="#type-errors" class="anchor"></a>Type Errors</h3><p>The <code>Yamlrw.Util</code> module raises <code>Yamlrw.Util.Type_error</code> for type mismatches:</p><pre class="language-ocaml"><code># try 224 229 ignore (Util.get_string (`Float 42.)); 225 230 &quot;ok&quot; 226 231 with Util.Type_error (expected, actual) -&gt; 227 232 Printf.sprintf &quot;expected %s, got %s&quot; expected (Value.type_name actual);; 228 - - : string = &quot;expected string, got number&quot;</code></pre><h2 id="common-patterns"><a href="#common-patterns" class="anchor"></a>Common Patterns</h2><h3 id="configuration-files"><a href="#configuration-files" class="anchor"></a>Configuration Files</h3><p>A typical configuration file pattern:</p><pre class="language-ocaml"><code># let config_yaml = {| 233 + - : string = &quot;expected string, got float&quot;</code></pre><h2 id="common-patterns"><a href="#common-patterns" class="anchor"></a>Common Patterns</h2><h3 id="configuration-files"><a href="#configuration-files" class="anchor"></a>Configuration Files</h3><p>A typical configuration file pattern:</p><pre class="language-ocaml"><code># let config_yaml = {| 229 234 app: 230 235 name: myapp 231 236 version: 1.0.0 ··· 287 292 acc +. Util.get_float (Util.get &quot;price&quot; item) 288 293 ) 0. items;; 289 294 val total : float = 59.97</code></pre><h3 id="transforming-data"><a href="#transforming-data" class="anchor"></a>Transforming Data</h3><p>Modifying YAML structures:</p><pre class="language-ocaml"><code># let original = of_string &quot;name: Alice\nstatus: active&quot;;; 290 - val original : value = `O [(&quot;name&quot;, `String &quot;Alice&quot;); (&quot;status&quot;, `String &quot;active&quot;)] 295 + val original : value = 296 + `O [(&quot;name&quot;, `String &quot;Alice&quot;); (&quot;status&quot;, `String &quot;active&quot;)] 291 297 # let updated = Util.update &quot;status&quot; (Util.string &quot;inactive&quot;) original;; 292 - val updated : Util.t = 298 + val updated : Value.t = 293 299 `O [(&quot;name&quot;, `String &quot;Alice&quot;); (&quot;status&quot;, `String &quot;inactive&quot;)] 294 300 # let with_timestamp = Util.update &quot;updated_at&quot; (Util.string &quot;2024-01-01&quot;) updated;; 295 - val with_timestamp : Util.t = 301 + val with_timestamp : Value.t = 296 302 `O 297 303 [(&quot;name&quot;, `String &quot;Alice&quot;); (&quot;status&quot;, `String &quot;inactive&quot;); 298 304 (&quot;updated_at&quot;, `String &quot;2024-01-01&quot;)] 299 305 # print_string (to_string with_timestamp);; 300 306 name: Alice 301 307 status: inactive 302 - updated_at: '2024-01-01' 308 + updated_at: 2024-01-01 303 309 - : unit = ()</code></pre><h2 id="summary"><a href="#summary" class="anchor"></a>Summary</h2><p>The <code>yamlrw</code> library provides:</p><ol><li><b>Simple parsing</b>: <code>Yamlrw.of_string</code> for JSON-compatible values</li><li><b>Full fidelity</b>: <code>Yamlrw.yaml_of_string</code> preserves all YAML metadata</li><li><b>Easy serialization</b>: <code>Yamlrw.to_string</code> with style options</li><li><b>Navigation</b>: <code>Yamlrw.Util</code> module for accessing and modifying values</li><li><b>Multi-document</b>: <code>Yamlrw.documents_of_string</code> for YAML streams</li><li><b>Streaming</b>: <code>Yamlrw.Stream</code> module for event-based processing</li></ol><p>Key types:</p><ul><li><code>Yamlrw.value</code> - JSON-compatible representation (<code>`Null</code>, <code>`Bool</code>, <code>`Float</code>, <code>`String</code>, <code>`A</code>, <code>`O</code>)</li><li><code>Yamlrw.yaml</code> - Full YAML with scalars, anchors, aliases, and metadata</li><li><code>Yamlrw.document</code> - A complete document with directives</li></ul><p>For more details, see the <span class="xref-unresolved" title="Yamlrw">API reference</span>.</p></div></body></html>
+1 -1
lib/token.mli
··· 14 14 | Document_end (** ... *) 15 15 | Block_sequence_start 16 16 | Block_mapping_start 17 - | Block_entry (** - *) 17 + | Block_entry (** [-] *) 18 18 | Block_end (** implicit, from dedent *) 19 19 | Flow_sequence_start (** \[ *) 20 20 | Flow_sequence_end (** \] *)