diff options
author | Clombrong <cromblong@egregore.fun> | 2025-07-01 11:57:57 +0200 |
---|---|---|
committer | Clombrong <cromblong@egregore.fun> | 2025-07-26 21:55:11 +0200 |
commit | b6abe9bfbe3d9fba58f3532e4323e340b0ae730b (patch) | |
tree | 75b009d0a0f457e7ebc2ab4d72fa70e476275c92 | |
parent | 664e930172603118f7341f7cfba284db61772876 (diff) |
feat(jid): use uchars for JID parsing
-rw-r--r-- | lib/jid.ml | 54 |
1 files changed, 19 insertions, 35 deletions
@@ -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) = |