this repo has no description

Refactor mail-flag to use polymorphic variants and move wire modules

- Convert Flag_color to polymorphic variants (`Red, `Orange, etc.)
- Remove Imap_wire module from mail-flag, merge into ocaml-imap Flag
- Flag.system now uses polymorphic variants
- Flag.Keyword now wraps Mail_flag.Keyword.t directly
- Add flags_of_keywords/keywords_of_flags batch conversions
- Remove Jmap_wire module from mail-flag, merge into ocaml-jmap
- Add role_of_special_use/special_use_of_role to Mail_mailbox
- Add keywords_to_assoc/keywords_of_assoc to Mail_email
- Create toplevel mail_flag.mli with module aliases and full API docs
- Update all IMAP library code and tests for polymorphic variant types

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

+77
+10
lib/mail/mail_email.ml
··· 525 525 |> Jsont.Object.opt_mem "maxBodyValueBytes" Proto_int53.Unsigned.jsont 526 526 ~enc:(fun a -> a.max_body_value_bytes) 527 527 |> Jsont.Object.finish 528 + 529 + (* Conversion to/from mail-flag keywords *) 530 + 531 + let keywords_to_assoc keywords = 532 + List.map (fun k -> (Mail_flag.Keyword.to_string k, true)) keywords 533 + 534 + let keywords_of_assoc assoc = 535 + List.filter_map (fun (s, v) -> 536 + if v then Some (Mail_flag.Keyword.of_string s) else None 537 + ) assoc
+25
lib/mail/mail_email.mli
··· 399 399 (** Convenience constructor with sensible defaults. *) 400 400 401 401 val get_args_extra_jsont : get_args_extra Jsont.t 402 + 403 + (** {1 Conversion to/from mail-flag Keywords} *) 404 + 405 + val keywords_to_assoc : Mail_flag.Keyword.t list -> (string * bool) list 406 + (** [keywords_to_assoc keywords] converts a list of mail-flag keywords to 407 + JMAP keywords object entries. Each keyword is converted to a [(string, true)] 408 + pair using {!Mail_flag.Keyword.to_string} for the string representation. 409 + 410 + Example: 411 + {[ 412 + keywords_to_assoc [`Seen; `Flagged; `Custom "label"] 413 + (* returns [("$seen", true); ("$flagged", true); ("label", true)] *) 414 + ]} *) 415 + 416 + val keywords_of_assoc : (string * bool) list -> Mail_flag.Keyword.t list 417 + (** [keywords_of_assoc assoc] parses JMAP keywords from object entries. 418 + Only entries with [true] value are included in the result. 419 + Entries with [false] value are ignored (they represent the absence 420 + of the keyword). 421 + 422 + Example: 423 + {[ 424 + keywords_of_assoc [("$seen", true); ("$draft", false); ("label", true)] 425 + (* returns [`Seen; `Custom "label"] *) 426 + ]} *)
+33
lib/mail/mail_mailbox.ml
··· 145 145 ~enc:role_to_string 146 146 Jsont.string 147 147 148 + (** {1 Conversion to/from mail-flag} *) 149 + 150 + let role_of_special_use : Mail_flag.Mailbox_attr.special_use -> role = function 151 + | `All -> `All 152 + | `Archive -> `Archive 153 + | `Drafts -> `Drafts 154 + | `Flagged -> `Flagged 155 + | `Important -> `Important 156 + | `Inbox -> `Inbox 157 + | `Junk -> `Junk 158 + | `Sent -> `Sent 159 + | `Subscribed -> `Subscribed 160 + | `Trash -> `Trash 161 + | `Snoozed -> `Snoozed 162 + | `Scheduled -> `Scheduled 163 + | `Memos -> `Memos 164 + 165 + let special_use_of_role : role -> Mail_flag.Mailbox_attr.special_use option = function 166 + | `All -> Some `All 167 + | `Archive -> Some `Archive 168 + | `Drafts -> Some `Drafts 169 + | `Flagged -> Some `Flagged 170 + | `Important -> Some `Important 171 + | `Inbox -> Some `Inbox 172 + | `Junk -> Some `Junk 173 + | `Sent -> Some `Sent 174 + | `Subscribed -> Some `Subscribed 175 + | `Trash -> Some `Trash 176 + | `Snoozed -> Some `Snoozed 177 + | `Scheduled -> Some `Scheduled 178 + | `Memos -> Some `Memos 179 + | `Other _ -> None 180 + 148 181 type t = { 149 182 id : Proto_id.t option; 150 183 name : string option;
+9
lib/mail/mail_mailbox.mli
··· 86 86 val role_of_string : string -> role 87 87 val role_jsont : role Jsont.t 88 88 89 + (** {2 Conversion to/from mail-flag} *) 90 + 91 + val role_of_special_use : Mail_flag.Mailbox_attr.special_use -> role 92 + (** [role_of_special_use su] converts a mail-flag special-use attribute to a JMAP role. *) 93 + 94 + val special_use_of_role : role -> Mail_flag.Mailbox_attr.special_use option 95 + (** [special_use_of_role r] converts a JMAP role to a mail-flag special-use attribute. 96 + Returns [None] for [`Other _] roles that don't correspond to standard special-use values. *) 97 + 89 98 (** {1 Mailbox} *) 90 99 91 100 type t = {