taler-rust

GNU Taler code in Rust. Largely core banking integrations.
Log | Files | Refs | Submodules | README | LICENSE

commit 9fd9f8217e102c24ca980ec92f689403a64f3c2a
parent 77e9bb891753ecc6ef06660b7a339c9e07675ff4
Author: Antoine A <>
Date:   Sat, 11 Jan 2025 16:39:27 +0100

common: optimize subject parsing

Diffstat:
Mcommon/taler-api/src/subject.rs | 40++++++++++++----------------------------
1 file changed, 12 insertions(+), 28 deletions(-)

diff --git a/common/taler-api/src/subject.rs b/common/taler-api/src/subject.rs @@ -163,27 +163,13 @@ pub fn parse_incoming_unstructured(subject: &str) -> Option<IncomingSubjectResul // Find and concatenate valid parts of a keys let (parts, concatenated) = { - let mut parts = Vec::new(); - let mut concatenated = String::new(); - let mut part = None; - for (i, b) in subject.as_bytes().iter().enumerate() { - if b.is_ascii_alphanumeric() { - if part.is_none() { - part = Some(i); - } - } else if let Some(from) = part { - let start = concatenated.len() as u16; - concatenated.push_str(&subject[from..i]); - let end = concatenated.len() as u16; - parts.push(start..end); - part = None; - } - } - if let Some(from) = part { - let start = concatenated.len() as u16; - concatenated.push_str(&subject[from..]); - let end = concatenated.len() as u16; - parts.push(start..end); + let mut parts = Vec::with_capacity(4); + let mut concatenated = String::with_capacity(subject.len().min(KYC_SIZE + 10)); + parts.push(0u16); + for part in subject.as_bytes().split(|b| !b.is_ascii_alphanumeric()) { + // SAFETY: part are all valid ASCII alphanumeric + concatenated.push_str(unsafe { std::str::from_utf8_unchecked(part) }); + parts.push(concatenated.len() as u16); } (parts, concatenated) }; @@ -191,19 +177,17 @@ pub fn parse_incoming_unstructured(subject: &str) -> Option<IncomingSubjectResul // Find best candidates let mut best: Option<Candidate> = None; // For each part as a starting point - for (i, start) in parts.iter().enumerate() { + for (i, &start) in parts.iter().enumerate() { // Use progressively longer concatenation - for end in parts[i..].iter() { - let range = start.start..end.end; + for &end in &parts[i..] { // Until they are to long to be a key - if range.len() > KYC_SIZE { + if (end - start) as usize > KYC_SIZE { break; - } + }; // Parse the concatenated parts // SAFETY: we now end.end <= concatenated.len - let slice = - unsafe { &concatenated.get_unchecked(start.start as usize..end.end as usize) }; + let slice = unsafe { &concatenated.get_unchecked(start as usize..end as usize) }; if let Some(other) = parse_single(slice) { // On success update best candidate match &mut best {