diff options
author | Clombrong <cromblong@egregore.fun> | 2025-06-30 19:47:51 +0200 |
---|---|---|
committer | Clombrong <cromblong@egregore.fun> | 2025-07-26 21:55:11 +0200 |
commit | 95673ef3ad5e44980016a3e5045e6ed5f80f845f (patch) | |
tree | faaf587128b2af106bfaa482b0c34dc028ce8d99 | |
parent | ef5a9c62e1f77a93407cc533a045ffa8fb5d6d2e (diff) |
feat(jid): add function of_string
-rw-r--r-- | lib/jid.ml | 39 |
1 files changed, 39 insertions, 0 deletions
@@ -3,3 +3,42 @@ type t = { domainpart : string; resourcepart : string option; } + +exception InvalidUTF8 + +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); + } |