Pure OCaml Yaml 1.2 reader and writer using Bytesrw
1(*---------------------------------------------------------------------------
2 Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved.
3 SPDX-License-Identifier: ISC
4 ---------------------------------------------------------------------------*)
5
6(** YAML tags for type information *)
7
8type t = {
9 handle : string; (** e.g., "!" or "!!" or "!foo!" *)
10 suffix : string; (** e.g., "str", "int", "custom/type" *)
11}
12
13let make ~handle ~suffix = { handle; suffix }
14
15let of_string s =
16 let len = String.length s in
17 match len with
18 | 0 -> None
19 | _ when s.[0] <> '!' -> None
20 | 1 -> Some { handle = "!"; suffix = "" }
21 | _ ->
22 match s.[1] with
23 | '!' -> (* !! handle *)
24 Some { handle = "!!"; suffix = String.sub s 2 (len - 2) }
25 | '<' -> (* Verbatim tag !<...> *)
26 if len > 2 && s.[len - 1] = '>' then
27 Some { handle = "!"; suffix = String.sub s 2 (len - 3) }
28 else
29 None
30 | _ -> (* Primary handle or local tag *)
31 Some { handle = "!"; suffix = String.sub s 1 (len - 1) }
32
33let to_string t =
34 if t.handle = "!" && t.suffix = "" then "!"
35 else t.handle ^ t.suffix
36
37let to_uri t =
38 match t.handle with
39 | "!!" -> "tag:yaml.org,2002:" ^ t.suffix
40 | "!" -> "!" ^ t.suffix
41 | h -> h ^ t.suffix
42
43let pp fmt t =
44 Format.pp_print_string fmt (to_string t)
45
46let equal a b =
47 String.equal a.handle b.handle && String.equal a.suffix b.suffix
48
49let compare a b =
50 let c = String.compare a.handle b.handle in
51 if c <> 0 then c else String.compare a.suffix b.suffix
52
53(** Standard tags *)
54
55let null = { handle = "!!"; suffix = "null" }
56let bool = { handle = "!!"; suffix = "bool" }
57let int = { handle = "!!"; suffix = "int" }
58let float = { handle = "!!"; suffix = "float" }
59let str = { handle = "!!"; suffix = "str" }
60let seq = { handle = "!!"; suffix = "seq" }
61let map = { handle = "!!"; suffix = "map" }
62let binary = { handle = "!!"; suffix = "binary" }
63let timestamp = { handle = "!!"; suffix = "timestamp" }
64
65(** Check if tag matches a standard type *)
66
67let is_null t = equal t null || (t.handle = "!" && t.suffix = "")
68let is_bool t = equal t bool
69let is_int t = equal t int
70let is_float t = equal t float
71let is_str t = equal t str
72let is_seq t = equal t seq
73let is_map t = equal t map