aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClombrong <cromblong@egregore.fun>2025-07-01 11:57:57 +0200
committerClombrong <cromblong@egregore.fun>2025-07-26 21:55:11 +0200
commitb6abe9bfbe3d9fba58f3532e4323e340b0ae730b (patch)
tree75b009d0a0f457e7ebc2ab4d72fa70e476275c92
parent664e930172603118f7341f7cfba284db61772876 (diff)
feat(jid): use uchars for JID parsing
-rw-r--r--lib/jid.ml54
1 files changed, 19 insertions, 35 deletions
diff --git a/lib/jid.ml b/lib/jid.ml
index b06a00c..ec24a30 100644
--- a/lib/jid.ml
+++ b/lib/jid.ml
@@ -29,41 +29,25 @@ let string_of_uchars (u : uchars) =
List.iter (Buffer.add_utf_8_uchar buf) u;
Buffer.to_bytes buf |> String.of_bytes
-let of_string (jid : string) : t =
- let open Uchar in
- let len = String.length jid in
- let rec to_localpart i =
- if i <= 0 then
- None
- else
- let c = String.get_utf_8_uchar jid i in
- if not (utf_decode_is_valid c)
- then raise InvalidUTF8
- else
- let k = utf_decode_length c in
- match utf_decode_uchar c |> to_char with
- | '@' -> Some (i + 1)
- | _ -> to_localpart (i - k)
- and to_resourcepart i =
- if i >= len then
- None
- else
- let c = String.get_utf_8_uchar jid i in
- if not (utf_decode_is_valid c)
- then raise InvalidUTF8
- else
- let k = utf_decode_length c in
- match utf_decode_uchar c |> to_char with
- | '/' -> Some i
- | _ -> to_resourcepart (i + k)
- in let r = to_resourcepart 0 in
- let rv = Option.value ~default:len r in
- let l = to_localpart (rv-1) in
- let lv = Option.value ~default:0 l in
- {
- localpart = Option.map (fun i -> String.sub jid 0 (i-1)) l;
- resourcepart = Option.map (fun i -> String.sub jid (i+1) (len-i-1)) r;
- domainpart = String.sub jid lv (rv-lv);
+let of_string (jid : uchars) : t =
+ let open List in
+ let dend, resourcepart =
+ find_mapi (fun i c ->
+ if c = Uchar.of_char '/'
+ then Some (i, drop i jid |> string_of_uchars)
+ else None) jid
+ |> Option.fold ~none:(length jid, None) ~some:(fun (i, s) -> i, Some s)
+ and dstart, localpart =
+ rev jid
+ |> find_mapi (fun i c ->
+ if c = Uchar.of_char '@'
+ then Some (i, take i jid |> rev |> string_of_uchars)
+ else None)
+ |> Option.fold ~none:(0, None) ~some:(fun (i, s) -> i, Some s)
+ in {
+ localpart;
+ resourcepart;
+ domainpart = drop dstart jid |> take (dend-dstart) |> string_of_uchars
}
let to_string ({ localpart; domainpart; resourcepart } : t) =