(*--------------------------------------------------------------------------- Copyright (c) 2024 Anil Madhavapeddy. All rights reserved. SPDX-License-Identifier: ISC ---------------------------------------------------------------------------*) module Unknown = struct type t = (string * Jsont.json) list let empty = [] let is_empty = function [] -> true | _ -> false end type t = { url : string; doi : string option; cito : Cito.t list option; unknown : Unknown.t; } let create ~url ?doi ?cito ?(unknown = Unknown.empty) () = { url; doi; cito; unknown } let url t = t.url let doi t = t.doi let cito t = t.cito let unknown t = t.unknown let equal a b = String.equal a.url b.url let pp ppf t = let open Format in fprintf ppf "%s" t.url; match t.doi with Some d -> fprintf ppf " [DOI: %s]" d | None -> () let jsont = let kind = "Reference" in let doc = "A reference to a cited source" in let unknown_mems : (Unknown.t, Jsont.json, Jsont.mem list) Jsont.Object.Mems.map = let open Jsont.Object.Mems in let dec_empty () = [] in let dec_add _meta (name : string) value acc = ((name, Jsont.Meta.none), value) :: acc in let dec_finish _meta mems = List.rev_map (fun ((name, _meta), value) -> (name, value)) mems in let enc = { enc = (fun (type acc) (f : Jsont.Meta.t -> string -> Jsont.json -> acc -> acc) unknown (acc : acc) -> List.fold_left (fun acc (name, value) -> f Jsont.Meta.none name value acc) acc unknown); } in map ~kind:"Unknown members" Jsont.json ~dec_empty ~dec_add ~dec_finish ~enc in let create_obj url doi cito unknown = create ~url ?doi ?cito ~unknown () in Jsont.Object.map ~kind ~doc create_obj |> Jsont.Object.mem "url" Jsont.string ~enc:url |> Jsont.Object.opt_mem "doi" Jsont.string ~enc:doi |> Jsont.Object.opt_mem "cito" (Jsont.list Cito.jsont) ~enc:cito |> Jsont.Object.keep_unknown unknown_mems ~enc:unknown |> Jsont.Object.finish