Skip to content

Commit

Permalink
♻️ zv: generalize ensure_correct_signature_str()
Browse files Browse the repository at this point in the history
Introduce a signature iterator, that we can later use for different
purposes.
  • Loading branch information
elmarco committed Aug 2, 2023
1 parent 1478b24 commit a0b92da
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 27 deletions.
32 changes: 5 additions & 27 deletions zvariant/src/signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ impl<'a> Signature<'a> {
/// [`Signature::into_owned`] do not clone the underlying bytes.
pub fn from_static_str(signature: &'static str) -> Result<Self> {
let bytes = signature.as_bytes();
ensure_correct_signature_str(bytes)?;
SignatureParser::validate(bytes)?;

Ok(Self {
bytes: Bytes::Static(bytes),
Expand All @@ -202,7 +202,7 @@ impl<'a> Signature<'a> {
/// `&'static [u8]`. The former will ensure that [`Signature::to_owned`] and
/// [`Signature::into_owned`] do not clone the underlying bytes.
pub fn from_static_bytes(bytes: &'static [u8]) -> Result<Self> {
ensure_correct_signature_str(bytes)?;
SignatureParser::validate(bytes)?;

Ok(Self {
bytes: Bytes::Static(bytes),
Expand Down Expand Up @@ -325,9 +325,9 @@ impl<'a> TryFrom<&'a [u8]> for Signature<'a> {
type Error = Error;

fn try_from(value: &'a [u8]) -> Result<Self> {
ensure_correct_signature_str(value)?;
SignatureParser::validate(value)?;

// SAFETY: ensure_correct_signature_str checks UTF8
// SAFETY: validate checks UTF8
unsafe { Ok(Self::from_bytes_unchecked(value)) }
}
}
Expand All @@ -345,7 +345,7 @@ impl<'a> TryFrom<String> for Signature<'a> {
type Error = Error;

fn try_from(value: String) -> Result<Self> {
ensure_correct_signature_str(value.as_bytes())?;
SignatureParser::validate(value.as_bytes())?;

Ok(Self::from_string_unchecked(value))
}
Expand Down Expand Up @@ -433,28 +433,6 @@ impl<'de> Visitor<'de> for SignatureVisitor {
}
}

fn ensure_correct_signature_str(signature: &[u8]) -> Result<()> {
if signature.len() > 255 {
return Err(serde::de::Error::invalid_length(
signature.len(),
&"<= 255 characters",
));
}

if signature.is_empty() {
return Ok(());
}

// SAFETY: SignatureParser never calls as_str
let signature = unsafe { Signature::from_bytes_unchecked(signature) };
let mut parser = SignatureParser::new(signature);
while !parser.done() {
let _ = parser.parse_next_signature()?;
}

Ok(())
}

/// Owned [`Signature`](struct.Signature.html)
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, Type)]
pub struct OwnedSignature(Signature<'static>);
Expand Down
32 changes: 32 additions & 0 deletions zvariant/src/signature_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,26 @@ impl<'s> SignatureParser<'s> {
}
}

pub(crate) unsafe fn from_bytes_unchecked(signature: &'s [u8]) -> Result<Self> {
if signature.len() > 255 {
return Err(serde::de::Error::invalid_length(
signature.len(),
&"<= 255 characters",
));
}

let signature = Signature::from_bytes_unchecked(signature);
Ok(Self::new(signature))
}

pub fn validate(signature: &'s [u8]) -> Result<()> {
// SAFETY: the parser is only used to validate the signature
for s in unsafe { Self::from_bytes_unchecked(signature)? } {
s?;
}
Ok(())
}

pub fn signature(&self) -> Signature<'_> {
self.signature.slice(self.pos..self.end)
}
Expand Down Expand Up @@ -297,3 +317,15 @@ impl<'s> SignatureParser<'s> {
self.signature.slice(self.pos + idx..self.pos + end)
}
}

impl<'a> Iterator for SignatureParser<'a> {
type Item = Result<Signature<'a>>;

fn next(&mut self) -> Option<Self::Item> {
if self.done() {
None
} else {
Some(self.parse_next_signature())
}
}
}

0 comments on commit a0b92da

Please sign in to comment.