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 mapping (object) values with metadata *)
7
8type ('k, 'v) t = {
9 anchor : string option;
10 tag : string option;
11 implicit : bool;
12 style : Layout_style.t;
13 members : ('k * 'v) list;
14}
15
16let make ?(anchor : string option) ?(tag : string option) ?(implicit = true)
17 ?(style = `Any) members =
18 { anchor; tag; implicit; style; members }
19
20let members t = t.members
21let anchor t = t.anchor
22let tag t = t.tag
23let implicit t = t.implicit
24let style t = t.style
25let with_anchor anchor t = { t with anchor = Some anchor }
26let with_tag tag t = { t with tag = Some tag }
27let with_style style t = { t with style }
28
29let map_keys f t =
30 { t with members = List.map (fun (k, v) -> (f k, v)) t.members }
31
32let map_values f t =
33 { t with members = List.map (fun (k, v) -> (k, f v)) t.members }
34
35let map f t = { t with members = List.map (fun (k, v) -> f k v) t.members }
36let length t = List.length t.members
37let is_empty t = t.members = []
38
39let find pred t =
40 List.find_opt (fun (k, _) -> pred k) t.members |> Option.map snd
41
42let find_key pred t = List.find_opt (fun (k, _) -> pred k) t.members
43let mem pred t = List.exists (fun (k, _) -> pred k) t.members
44let keys t = List.map fst t.members
45let values t = List.map snd t.members
46let iter f t = List.iter (fun (k, v) -> f k v) t.members
47let fold f init t = List.fold_left (fun acc (k, v) -> f acc k v) init t.members
48
49let pp pp_key pp_val fmt t =
50 Format.fprintf fmt "@[<hv 2>mapping(@,";
51 Option.iter (Format.fprintf fmt "anchor=%s,@ ") t.anchor;
52 Option.iter (Format.fprintf fmt "tag=%s,@ ") t.tag;
53 Format.fprintf fmt "style=%a,@ " Layout_style.pp t.style;
54 Format.fprintf fmt "members={@,";
55 List.iteri
56 (fun i (k, v) ->
57 if i > 0 then Format.fprintf fmt ",@ ";
58 Format.fprintf fmt "@[<hv 2>%a:@ %a@]" pp_key k pp_val v)
59 t.members;
60 Format.fprintf fmt "@]@,})"
61
62let equal eq_k eq_v a b =
63 Option.equal String.equal a.anchor b.anchor
64 && Option.equal String.equal a.tag b.tag
65 && a.implicit = b.implicit
66 && Layout_style.equal a.style b.style
67 && List.equal
68 (fun (k1, v1) (k2, v2) -> eq_k k1 k2 && eq_v v1 v2)
69 a.members b.members
70
71let compare cmp_k cmp_v a b =
72 let c = Option.compare String.compare a.anchor b.anchor in
73 if c <> 0 then c
74 else
75 let c = Option.compare String.compare a.tag b.tag in
76 if c <> 0 then c
77 else
78 let c = Bool.compare a.implicit b.implicit in
79 if c <> 0 then c
80 else
81 let c = Layout_style.compare a.style b.style in
82 if c <> 0 then c
83 else
84 let cmp_pair (k1, v1) (k2, v2) =
85 let c = cmp_k k1 k2 in
86 if c <> 0 then c else cmp_v v1 v2
87 in
88 List.compare cmp_pair a.members b.members