Skip to content

Commit

Permalink
Merge pull request #1165 from zeenix/const-signature-str-len
Browse files Browse the repository at this point in the history
⚡️ zu: A few Signature micro optimizations
  • Loading branch information
zeenix authored Nov 30, 2024
2 parents 8f7418e + 35efa6c commit 3933c2b
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 6 deletions.
7 changes: 6 additions & 1 deletion zvariant_utils/src/signature/child.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,17 @@ static_assertions::assert_impl_all!(Child: Send, Sync, Unpin);

impl Child {
/// The underlying child `Signature`.
pub fn signature(&self) -> &Signature {
pub const fn signature(&self) -> &Signature {
match self {
Child::Static { child } => child,
Child::Dynamic { child } => child,
}
}

/// The length of the child signature in string form.
pub const fn string_len(&self) -> usize {
self.signature().string_len()
}
}

impl Deref for Child {
Expand Down
2 changes: 1 addition & 1 deletion zvariant_utils/src/signature/fields.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ impl Fields {
}

/// The number of fields.
pub fn len(&self) -> usize {
pub const fn len(&self) -> usize {
match self {
Self::Static { fields } => fields.len(),
Self::Dynamic { fields } => fields.len(),
Expand Down
25 changes: 21 additions & 4 deletions zvariant_utils/src/signature/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ pub enum Signature {

impl Signature {
/// The size of the string form of `self`.
pub fn string_len(&self) -> usize {
pub const fn string_len(&self) -> usize {
match self {
Signature::Unit => 0,
Signature::U8
Expand All @@ -123,8 +123,13 @@ impl Signature {
Signature::Dict { key, value } => 3 + key.string_len() + value.string_len(),
Signature::Structure(fields) => {
let mut len = 2;
for field in fields.iter() {
len += field.string_len();
let mut i = 0;
while i < fields.len() {
len += match fields {
Fields::Static { fields } => fields[i].string_len(),
Fields::Dynamic { fields } => fields[i].string_len(),
};
i += 1;
}
len
}
Expand All @@ -144,7 +149,7 @@ impl Signature {

/// Convert `self` to a string, without any enclosing parenthesis.
///
/// This produces the same output as the `ToString::to_string`, unless `self` is a
/// This produces the same output as the [`Signature::to_string`], unless `self` is a
/// [`Signature::Structure`], in which case the written string will **not** be wrapped in
/// parenthesis (`()`).
pub fn to_string_no_parens(&self) -> String {
Expand All @@ -154,6 +159,18 @@ impl Signature {
s
}

/// Convert `self` to a string.
///
/// This produces the same output as the `ToString::to_string`, except it preallocates the
/// required memory and hence avoids reallocations and moving of data.
#[allow(clippy::inherent_to_string_shadow_display)]
pub fn to_string(&self) -> String {
let mut s = String::with_capacity(self.string_len());
self.write_as_string(&mut s, true).unwrap();

s
}

/// Parse signature from a byte slice.
pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
parse(bytes, false)
Expand Down
11 changes: 11 additions & 0 deletions zvariant_utils/src/signature/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@ macro_rules! validate {
let parsed = Signature::from_str($signature).unwrap();
assert_eq!(parsed, $expected);
assert_eq!(parsed, $signature);
match parsed {
Signature::Structure(_) => {
assert!(
$signature.len() == parsed.string_len() - 2 ||
$signature.len() == parsed.string_len()
);
}
_ => {
assert_eq!(parsed.string_len(), $signature.len());
}
}
)+
};
}
Expand Down

0 comments on commit 3933c2b

Please sign in to comment.