jid: Factorize length check for shorter code

This commit is contained in:
xmppftw 2023-06-20 17:24:58 +02:00 committed by Emmanuel Gil Peyrot
parent cf25bd3fee
commit 2a3d393ad5

View file

@ -13,10 +13,19 @@
use crate::JidParseError as Error; use crate::JidParseError as Error;
use core::num::NonZeroU16; use core::num::NonZeroU16;
use memchr::memchr; use memchr::memchr;
use std::borrow::Cow;
use std::str::FromStr; use std::str::FromStr;
use stringprep::{nameprep, nodeprep, resourceprep}; use stringprep::{nameprep, nodeprep, resourceprep};
fn length_check(len: usize, error_empty: Error, error_too_long: Error) -> Result<(), Error> {
if len == 0 {
Err(error_empty)
} else if len > 1023 {
Err(error_too_long)
} else {
Ok(())
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub(crate) struct InnerJid { pub(crate) struct InnerJid {
pub(crate) normalized: String, pub(crate) normalized: String,
@ -37,93 +46,44 @@ impl InnerJid {
let normalized = match (orig_at, orig_slash) { let normalized = match (orig_at, orig_slash) {
(Some(at), Some(slash)) => { (Some(at), Some(slash)) => {
let node = nodeprep(&unnormalized[..at]).map_err(|_| Error::NodePrep)?; let node = nodeprep(&unnormalized[..at]).map_err(|_| Error::NodePrep)?;
if node.len() == 0 { length_check(node.len(), Error::EmptyNode, Error::NodeTooLong)?;
return Err(Error::EmptyNode);
}
if node.len() > 1023 {
return Err(Error::NodeTooLong);
}
let domain = nameprep(&unnormalized[at + 1..slash]).map_err(|_| Error::NamePrep)?; let domain = nameprep(&unnormalized[at + 1..slash]).map_err(|_| Error::NamePrep)?;
if domain.len() == 0 { length_check(domain.len(), Error::NoDomain, Error::DomainTooLong)?;
return Err(Error::NoDomain);
}
if domain.len() > 1023 {
return Err(Error::DomainTooLong);
}
let resource = let resource =
resourceprep(&unnormalized[slash + 1..]).map_err(|_| Error::ResourcePrep)?; resourceprep(&unnormalized[slash + 1..]).map_err(|_| Error::ResourcePrep)?;
if resource.len() == 0 { length_check(resource.len(), Error::EmptyResource, Error::ResourceTooLong)?;
return Err(Error::EmptyResource);
} orig_at = Some(node.len());
if resource.len() > 1023 { orig_slash = Some(node.len() + domain.len() + 1);
return Err(Error::ResourceTooLong); format!("{node}@{domain}/{resource}")
}
match (node, domain, resource) {
(Cow::Borrowed(_), Cow::Borrowed(_), Cow::Borrowed(_)) => {
unnormalized.to_owned()
}
(node, domain, resource) => {
orig_at = Some(node.len());
orig_slash = Some(node.len() + domain.len() + 1);
format!("{node}@{domain}/{resource}")
}
}
} }
(Some(at), None) => { (Some(at), None) => {
let node = nodeprep(&unnormalized[..at]).map_err(|_| Error::NodePrep)?; let node = nodeprep(&unnormalized[..at]).map_err(|_| Error::NodePrep)?;
if node.len() == 0 { length_check(node.len(), Error::EmptyNode, Error::NodeTooLong)?;
return Err(Error::EmptyNode);
}
if node.len() > 1023 {
return Err(Error::NodeTooLong);
}
let domain = nameprep(&unnormalized[at + 1..]).map_err(|_| Error::NamePrep)?; let domain = nameprep(&unnormalized[at + 1..]).map_err(|_| Error::NamePrep)?;
if domain.len() == 0 { length_check(domain.len(), Error::NoDomain, Error::DomainTooLong)?;
return Err(Error::NoDomain);
} orig_at = Some(node.len());
if domain.len() > 1023 { format!("{node}@{domain}")
return Err(Error::DomainTooLong);
}
match (node, domain) {
(Cow::Borrowed(_), Cow::Borrowed(_)) => unnormalized.to_owned(),
(node, domain) => {
orig_at = Some(node.len());
format!("{node}@{domain}")
}
}
} }
(None, Some(slash)) => { (None, Some(slash)) => {
let domain = nameprep(&unnormalized[..slash]).map_err(|_| Error::NamePrep)?; let domain = nameprep(&unnormalized[..slash]).map_err(|_| Error::NamePrep)?;
if domain.len() == 0 { length_check(domain.len(), Error::NoDomain, Error::DomainTooLong)?;
return Err(Error::NoDomain);
}
if domain.len() > 1023 {
return Err(Error::DomainTooLong);
}
let resource = let resource =
resourceprep(&unnormalized[slash + 1..]).map_err(|_| Error::ResourcePrep)?; resourceprep(&unnormalized[slash + 1..]).map_err(|_| Error::ResourcePrep)?;
if resource.len() == 0 { length_check(resource.len(), Error::EmptyResource, Error::ResourceTooLong)?;
return Err(Error::EmptyResource);
} orig_slash = Some(domain.len());
if resource.len() > 1023 { format!("{domain}/{resource}")
return Err(Error::ResourceTooLong);
}
match (domain, resource) {
(Cow::Borrowed(_), Cow::Borrowed(_)) => unnormalized.to_owned(),
(domain, resource) => {
orig_slash = Some(domain.len());
format!("{domain}/{resource}")
}
}
} }
(None, None) => { (None, None) => {
let domain = nameprep(unnormalized).map_err(|_| Error::NamePrep)?; let domain = nameprep(unnormalized).map_err(|_| Error::NamePrep)?;
if domain.len() == 0 { length_check(domain.len(), Error::NoDomain, Error::DomainTooLong)?;
return Err(Error::NoDomain);
}
if domain.len() > 1023 {
return Err(Error::DomainTooLong);
}
domain.into_owned() domain.into_owned()
} }
}; };