JID stringprep errors return a JidParseError instead of panic (#84)

xmppftw created

Change summary

jid/CHANGELOG.md |  2 ++
jid/src/lib.rs   | 30 ++++++++++++++++++++++--------
2 files changed, 24 insertions(+), 8 deletions(-)

Detailed changes

jid/CHANGELOG.md 🔗

@@ -4,6 +4,8 @@ Unreleased
     - serde: Jid is now using untagged enum representation (#66)
   * Additions
     - From<&Jid> is now implemented for String (#69)
+    - Parsing invalid JIDs with stringprep feature no longer results in panic,
+    returning JidParseError::IcuError instead (#84)
 
 Version 0.9.3, release 2022-03-07:
   * Updates

jid/src/lib.rs 🔗

@@ -42,10 +42,18 @@ pub enum JidParseError {
     EmptyResource,
 
     #[cfg(feature = "icu")]
-    /// TODO
+    /// Happens when the JID is invalid according to stringprep. TODO: make errors
+    /// meaningful.
     IcuError(icu::Error),
 }
 
+#[cfg(feature = "icu")]
+impl From<icu::Error> for JidParseError {
+    fn from(e: icu::Error) -> JidParseError {
+        JidParseError::IcuError(e)
+    }
+}
+
 impl StdError for JidParseError {}
 
 impl fmt::Display for JidParseError {
@@ -410,13 +418,19 @@ fn _from_str(s: &str) -> Result<StringJid, JidParseError> {
     let domain = domain.ok_or(JidParseError::NoDomain)?;
     #[cfg(feature = "icu")]
     let (node, domain, resource) = {
-        let icu = Icu::new().unwrap();
-        let node = node.map(|node| icu.nodeprep(&node, Strict::AllowUnassigned).unwrap());
-        let domain = icu.idna2008.to_unicode(&domain).unwrap();
-        let resource = resource.map(|resource| {
-            icu.resourceprep(&resource, Strict::AllowUnassigned)
-                .unwrap()
-        });
+        let icu = Icu::new()?;
+        let node = if let Some(node) = node {
+            Some(icu.nodeprep(&node, Strict::AllowUnassigned)?)
+        } else {
+            None
+        };
+        let domain = icu.idna2008.to_unicode(&domain)?;
+        let resource = if let Some(resource) = resource {
+            Some(icu.resourceprep(&resource, Strict::AllowUnassigned)?)
+        } else {
+            None
+        };
+
         (node, domain, resource)
     };
     Ok((node, domain, resource))