IMAP in OCaml
at main 75 lines 2.6 kB view raw
1(*--------------------------------------------------------------------------- 2 Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 SPDX-License-Identifier: ISC 4 ---------------------------------------------------------------------------*) 5 6(** IMAP Client Errors 7 8 Error types for IMAP client operations, integrated with Eio's exception 9 handling. *) 10 11(** {1 Error Types} *) 12 13type t = 14 | Connection_error of { reason : string } 15 | Protocol_error of { code : Code.t option; text : string } 16 | Parse_error of { reason : string; data : string option } 17 | State_error of { expected : string; actual : string } 18 | Timeout of { operation : string } 19 | Capability_missing of { capability : string } 20 | Authentication_error of { mechanism : string; reason : string } 21 22(** {1 Pretty Printing} *) 23 24let pp ppf = function 25 | Connection_error { reason } -> Fmt.pf ppf "Connection error: %s" reason 26 | Protocol_error { code; text } -> 27 let code_str = Option.fold ~none:"" ~some:(Fmt.str " [%a]" Code.pp) code in 28 Fmt.pf ppf "Protocol error%s: %s" code_str text 29 | Parse_error { reason; data } -> 30 let truncate d = if String.length d > 50 then String.sub d 0 50 ^ "..." else d in 31 let suffix = Option.fold ~none:"" ~some:(fun d -> Fmt.str " (near: %s)" (truncate d)) data in 32 Fmt.pf ppf "Parse error: %s%s" reason suffix 33 | State_error { expected; actual } -> 34 Fmt.pf ppf "State error: expected %s, got %s" expected actual 35 | Timeout { operation } -> Fmt.pf ppf "Timeout: %s" operation 36 | Capability_missing { capability } -> 37 Fmt.pf ppf "Capability missing: %s" capability 38 | Authentication_error { mechanism; reason } -> 39 Fmt.pf ppf "Authentication error (%s): %s" mechanism reason 40 41let to_string e = Fmt.str "%a" pp e 42 43(** {1 Eio Integration} *) 44 45type Eio.Exn.err += E of t 46 47let () = 48 Eio.Exn.register_pp (fun ppf exn -> 49 match exn with 50 | E e -> 51 pp ppf e; 52 true 53 | _ -> false) 54 55let err e = Eio.Exn.create (E e) 56let raise e = Stdlib.raise (err e) 57 58let of_eio_exn = function 59 | Eio.Exn.Io (E e, _) -> Some e 60 | _ -> None 61 62(** {1 Error Classification} *) 63 64let is_retryable = function 65 | Connection_error _ | Timeout _ -> true 66 | Protocol_error { code = Some Code.Unavailable; _ } -> true 67 | _ -> false 68 69let is_auth_error = function 70 | Protocol_error { code = Some Code.Authenticationfailed; _ } -> true 71 | Protocol_error { code = Some Code.Authorizationfailed; _ } -> true 72 | Authentication_error _ -> true 73 | _ -> false 74 75let is_state_error = function State_error _ -> true | _ -> false