Source file reverse_path.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
type t = Path.t option
let equal a b =
match (a, b) with
| Some a, Some b -> Path.equal a b
| None, None -> true
| _, _ -> false
let pp = Fmt.option Path.pp
module Decoder = struct
open Angstrom
let reverse_path =
Path.Decoder.path >>| (fun t -> Some t) <|> string "<>" *> return None
let esmtp_keyword =
satisfy Domain.Decoder.(is_alpha or is_digit) >>= fun pre ->
take_while Domain.Decoder.(is_alpha or is_digit or is_dash) >>| fun lst ->
String.concat "" [ String.make 1 pre; lst ]
let esmtp_value =
take_while1 (function
| '\033' .. '\060' | '\062' .. '\126' -> true
| _ -> false)
let esmtp_param =
esmtp_keyword >>= fun key ->
option None (char '=' *> esmtp_value >>| fun x -> Some x) >>| fun value ->
(key, value)
let mail_parameters =
esmtp_param >>= fun x ->
many (char ' ' *> esmtp_param) >>| fun r -> x :: r
let of_string x =
let p =
reverse_path >>= fun reverse_path ->
option [] (char ' ' *> mail_parameters) >>| fun parameters ->
(reverse_path, parameters) in
match parse_string ~consume:Consume.All p x with
| Ok v -> v
| Error _ -> Fmt.invalid_arg "Invalid reverse-path: %s" x
end
module Encoder = struct
let to_string = function
| None -> "<>"
| Some path -> Path.Encoder.to_string path
end