From 307c246b779e089775be31699663c22e89dbd6c8 Mon Sep 17 00:00:00 2001 From: Nikita Koss Date: Fri, 6 Oct 2023 06:50:32 +0300 Subject: [PATCH] replace spec indices search with regex --- src/patch/mod.rs | 45 +++++++++++++++++++++++++++-------------- src/patch/peripheral.rs | 26 +++++++++++++++++++----- src/patch/register.rs | 6 +++++- 3 files changed, 56 insertions(+), 21 deletions(-) diff --git a/src/patch/mod.rs b/src/patch/mod.rs index 738521b9..cec4bea3 100644 --- a/src/patch/mod.rs +++ b/src/patch/mod.rs @@ -569,22 +569,37 @@ fn make_cpu(cmod: &Hash) -> Result { } /// Find left and right indices of enumeration token in specification string -fn spec_ind(spec: &str) -> (usize, usize) { +/// +/// # Examples +/// +/// ```ignore +/// let cases = [ +/// ("RELOAD?", (6, 0)), +/// ("TMR[1-57]_MUX", (3, 4)), +/// ("DT[1-3]?", (2, 0)), +/// ("GPIO[ABCDE]", (4, 0)), +/// ("CSPT[1][7-9],CSPT[2][0-5]", (4, 0)), +/// ]; +/// for (spec, (li, ri)) in cases { +/// assert_eq!(spec_ind(spec), Some((li, ri))); +/// } +/// ``` +/// +fn spec_ind(spec: &str) -> Option<(usize, usize)> { + use once_cell::sync::Lazy; + use regex::Regex; let spec = spec.split(',').next().unwrap_or(spec); - let li = spec - .bytes() - .position(|b| b == b'*') - .or_else(|| spec.bytes().position(|b| b == b'?')) - .or_else(|| spec.bytes().position(|b| b == b'[')) - .unwrap(); - let ri = spec - .bytes() - .rev() - .position(|b| b == b'*') - .or_else(|| spec.bytes().rev().position(|b| b == b'?')) - .or_else(|| spec.bytes().rev().position(|b| b == b']')) - .unwrap(); - (li, ri) + static RE: Lazy = Lazy::new(|| { + Regex::new(r"^\w*((?:[\?*]|\[\d+(?:-\d+)?\]|\[[a-zA-Z]+(?:-[a-zA-Z]+)?\])+)\w*$").unwrap() + }); + let Some(caps) = RE.captures(spec) else { + return None; + }; + let spec = caps.get(0).unwrap(); + let token = caps.get(1).unwrap(); + let li = token.start(); + let ri = spec.end() - token.end(); + Some((li, ri)) } fn check_offsets(offsets: &[u32], dim_increment: u32) -> bool { diff --git a/src/patch/peripheral.rs b/src/patch/peripheral.rs index c4d70314..3edb9cd5 100644 --- a/src/patch/peripheral.rs +++ b/src/patch/peripheral.rs @@ -1135,7 +1135,11 @@ fn collect_in_array( return Err(anyhow!("{path}: registers {rspec} not found")); } registers.sort_by_key(|r| r.address_offset); - let (li, ri) = spec_ind(rspec); + let Some((li, ri)) = spec_ind(rspec) else { + return Err(anyhow!( + "`{rspec}` contains no tokens or contains more than one token" + )); + }; let dim = registers.len(); let dim_index = if rmod.contains_key(&"_start_from_zero".to_yaml()) { (0..dim).map(|v| v.to_string()).collect::>() @@ -1241,10 +1245,18 @@ fn collect_in_cluster( .iter() .map(|r| { let match_rspec = matchsubspec(&r.name, rspec).unwrap(); - let (li, ri) = spec_ind(match_rspec); - r.name[li..r.name.len() - ri].to_string() + let Some((li, ri)) = spec_ind(match_rspec) else { + return Err(anyhow!( + "`{match_rspec}` contains no tokens or contains more than one token" + )); + }; + Ok(r.name[li..r.name.len() - ri].to_string()) }) - .collect::>(); + .collect::, _>>(); + let new_dim_index = match new_dim_index { + Ok(v) => v, + Err(e) => return Err(e), + }; if first { dim = registers.len(); dim_index = new_dim_index; @@ -1316,7 +1328,11 @@ fn collect_in_cluster( reg.name = if let Some(name) = rmod.get_str("name")? { name.into() } else { - let (li, ri) = spec_ind(&rspec); + let Some((li, ri)) = spec_ind(&rspec) else { + return Err(anyhow!( + "`{rspec}` contains no tokens or contains more than one token" + )); + }; format!("{}{}", &rspec[..li], &rspec[rspec.len() - ri..]) }; if let Some(desc) = rmod.get_str("description")? { diff --git a/src/patch/register.rs b/src/patch/register.rs index fc40abc9..03c7fea3 100644 --- a/src/patch/register.rs +++ b/src/patch/register.rs @@ -373,7 +373,11 @@ impl RegisterExt for Register { return Err(anyhow!("{}: fields {fspec} not found", self.name)); } fields.sort_by_key(|f| f.bit_range.offset); - let (li, ri) = spec_ind(fspec); + let Some((li, ri)) = spec_ind(fspec) else { + return Err(anyhow!( + "`{fspec}` contains no tokens or contains more than one token" + )); + }; let dim = fields.len(); let dim_index = if fmod.contains_key(&"_start_from_zero".to_yaml()) { (0..dim).map(|v| v.to_string()).collect::>()