OCaml library for JSONfeed parsing and creation
1(*--------------------------------------------------------------------------- 2 Copyright (c) 2024 Anil Madhavapeddy. All rights reserved. 3 SPDX-License-Identifier: ISC 4 ---------------------------------------------------------------------------*) 5 6module Unknown = struct 7 type t = (string * Jsont.json) list 8 9 let empty = [] 10 let is_empty = function [] -> true | _ -> false 11end 12 13type t = { 14 url : string; 15 mime_type : string; 16 title : string option; 17 size_in_bytes : int64 option; 18 duration_in_seconds : int option; 19 unknown : Unknown.t; 20} 21 22let make ~url ~mime_type ?title ?size_in_bytes ?duration_in_seconds ?(unknown = Unknown.empty) () = 23 { url; mime_type; title; size_in_bytes; duration_in_seconds; unknown } 24 25let create ~url ~mime_type ?title ?size_in_bytes ?duration_in_seconds () = 26 make ~url ~mime_type ?title ?size_in_bytes ?duration_in_seconds () 27 28let url t = t.url 29let mime_type t = t.mime_type 30let title t = t.title 31let size_in_bytes t = t.size_in_bytes 32let duration_in_seconds t = t.duration_in_seconds 33let unknown t = t.unknown 34 35let equal a b = 36 a.url = b.url && 37 a.mime_type = b.mime_type && 38 a.title = b.title && 39 a.size_in_bytes = b.size_in_bytes && 40 a.duration_in_seconds = b.duration_in_seconds 41 42let pp ppf t = 43 (* Extract filename from URL *) 44 let filename = 45 try 46 let parts = String.split_on_char '/' t.url in 47 List.nth parts (List.length parts - 1) 48 with _ -> t.url 49 in 50 51 Format.fprintf ppf "%s (%s" filename t.mime_type; 52 53 (match t.size_in_bytes with 54 | Some size -> 55 let mb = Int64.to_float size /. (1024. *. 1024.) in 56 Format.fprintf ppf ", %.1f MB" mb 57 | None -> ()); 58 59 (match t.duration_in_seconds with 60 | Some duration -> 61 let mins = duration / 60 in 62 let secs = duration mod 60 in 63 Format.fprintf ppf ", %dm%ds" mins secs 64 | None -> ()); 65 66 Format.fprintf ppf ")" 67 68let jsont = 69 let kind = "Attachment" in 70 let doc = "An attachment object" in 71 let unknown_mems : (Unknown.t, Jsont.json, Jsont.mem list) Jsont.Object.Mems.map = 72 let open Jsont.Object.Mems in 73 let dec_empty () = [] in 74 let dec_add _meta (name : string) value acc = 75 ((name, Jsont.Meta.none), value) :: acc 76 in 77 let dec_finish _meta mems = 78 List.rev_map (fun ((name, _meta), value) -> (name, value)) mems in 79 let enc = { 80 enc = fun (type acc) (f : Jsont.Meta.t -> string -> Jsont.json -> acc -> acc) unknown (acc : acc) -> 81 List.fold_left (fun acc (name, value) -> 82 83 f Jsont.Meta.none name value acc 84 ) acc unknown 85 } in 86 map ~kind:"Unknown members" Jsont.json ~dec_empty ~dec_add ~dec_finish ~enc 87 in 88 let make_obj url mime_type title size_in_bytes duration_in_seconds unknown = 89 make ~url ~mime_type ?title ?size_in_bytes ?duration_in_seconds ~unknown () 90 in 91 Jsont.Object.map ~kind ~doc make_obj 92 |> Jsont.Object.mem "url" Jsont.string ~enc:url 93 |> Jsont.Object.mem "mime_type" Jsont.string ~enc:mime_type 94 |> Jsont.Object.opt_mem "title" Jsont.string ~enc:title 95 |> Jsont.Object.opt_mem "size_in_bytes" Jsont.int64 ~enc:size_in_bytes 96 |> Jsont.Object.opt_mem "duration_in_seconds" Jsont.int ~enc:duration_in_seconds 97 |> Jsont.Object.keep_unknown unknown_mems ~enc:unknown 98 |> Jsont.Object.finish