OCaml library for JSONfeed parsing and creation
1(*---------------------------------------------------------------------------
2 Copyright (c) 2025 Anil Madhavapeddy. All rights reserved.
3 SPDX-License-Identifier: ISC
4 ---------------------------------------------------------------------------*)
5
6(** Attachments for JSON Feed items.
7
8 An attachment represents an external resource related to a feed item, such
9 as audio files for podcasts, video files, or other downloadable content.
10 Attachments with identical titles indicate alternate formats of the same
11 resource.
12
13 @see <https://www.jsonfeed.org/version/1.1/> JSON Feed Specification *)
14
15type t
16(** The type representing an attachment. *)
17
18(** {1 Unknown Fields} *)
19
20module Unknown : sig
21 type t = Jsont.json
22 (** Unknown/unrecognized JSON object members as a generic JSON object. Useful
23 for preserving fields from custom extensions or future spec versions. *)
24
25 val empty : t
26 (** [empty] is the empty list of unknown fields. *)
27
28 val is_empty : t -> bool
29 (** [is_empty u] returns [true] if there are no unknown fields. *)
30end
31
32(** {1 Jsont Type} *)
33
34val jsont : t Jsont.t
35(** Declarative JSON type for attachments.
36
37 Maps JSON objects with "url" (required), "mime_type" (required), and
38 optional "title", "size_in_bytes", "duration_in_seconds" fields. *)
39
40(** {1 Construction} *)
41
42val create :
43 url:string ->
44 mime_type:string ->
45 ?title:string ->
46 ?size_in_bytes:int64 ->
47 ?duration_in_seconds:int ->
48 ?unknown:Unknown.t ->
49 unit ->
50 t
51(** [create ~url ~mime_type ?title ?size_in_bytes ?duration_in_seconds ?unknown
52 ()] creates an attachment object.
53
54 @param url The location of the attachment (required)
55 @param mime_type
56 The MIME type of the attachment, e.g. ["audio/mpeg"] (required)
57 @param title
58 The name of the attachment; identical titles indicate alternate formats of
59 the same resource
60 @param size_in_bytes The size of the attachment file in bytes
61 @param duration_in_seconds
62 The duration of the attachment in seconds (for audio/video)
63 @param unknown Unknown/custom fields for extensions (default: empty)
64
65 {b Examples:}
66 {[
67 (* Simple attachment *)
68 let att =
69 Attachment.create ~url:"https://example.com/episode.mp3"
70 ~mime_type:"audio/mpeg" ()
71
72 (* Podcast episode with metadata *)
73 let att =
74 Attachment.create ~url:"https://example.com/episode.mp3"
75 ~mime_type:"audio/mpeg" ~title:"Episode 42" ~size_in_bytes:15_728_640L
76 ~duration_in_seconds:1800 ()
77 ]} *)
78
79(** {1 Accessors} *)
80
81val url : t -> string
82(** [url t] returns the attachment's URL. *)
83
84val mime_type : t -> string
85(** [mime_type t] returns the attachment's MIME type. *)
86
87val title : t -> string option
88(** [title t] returns the attachment's title, if set. *)
89
90val size_in_bytes : t -> int64 option
91(** [size_in_bytes t] returns the attachment's size in bytes, if set. *)
92
93val duration_in_seconds : t -> int option
94(** [duration_in_seconds t] returns the attachment's duration, if set. *)
95
96val unknown : t -> Unknown.t
97(** [unknown t] returns unrecognized fields from the JSON. *)
98
99(** {1 Comparison} *)
100
101val equal : t -> t -> bool
102(** [equal a b] tests equality between two attachments. *)
103
104(** {1 Pretty Printing} *)
105
106val pp : Format.formatter -> t -> unit
107(** [pp ppf t] pretty prints an attachment to the formatter.
108
109 The output is human-readable and suitable for debugging.
110
111 {b Example output:}
112 {v episode.mp3 (audio/mpeg, 15.0 MB, 30m0s) v} *)