diff --git a/src/instruments.rs b/src/instruments.rs index bdee226..0beb4c3 100644 --- a/src/instruments.rs +++ b/src/instruments.rs @@ -64,7 +64,9 @@ fn wave_numbers(input: &str) -> IResult<&str, (usize, u8)> { }) }), space1, - map_res(hexordecimal, |(radix, s)| u8::from_str_radix(s, radix)), + map_res(hexordecimal, |(radix, s)| { + u8::from_str_radix(s, radix) + }), )(input) } diff --git a/src/mfvi.rs b/src/mfvi.rs index 9073581..b1b554f 100644 --- a/src/mfvi.rs +++ b/src/mfvi.rs @@ -14,22 +14,22 @@ struct Translation<'a> { #[derive(Clone)] /// Holds the set of delimiters that should be removed from the MML to select a variant. -pub struct Variant { - keep_delim: char, - remove_delims: HashSet, +pub struct Variant<'v> { + keep_delim: &'v str, + remove_delims: HashSet<&'v str>, } -impl Variant { +impl<'v> Variant<'v> { /// Get the set of character delimiters to remove from MML for this variant. - pub fn ignores(&self) -> &HashSet { + pub fn ignores(&self) -> &HashSet<&str> { &self.remove_delims } } /// The list of all variants defined in an MML file. pub struct VariantList<'v> { - all_delims: HashSet, - variants: BTreeMap<&'v str, Variant>, + all_delims: HashSet<&'v str>, + variants: BTreeMap<&'v str, Variant<'v>>, } impl<'v> VariantList<'v> { @@ -43,16 +43,14 @@ impl<'v> VariantList<'v> { fn finish(mut self) -> Self { for (_, v) in self.variants.iter_mut() { v.remove_delims = self.all_delims.clone(); - v.remove_delims.remove(&v.keep_delim); + v.remove_delims.remove(v.keep_delim); } if self.variants.is_empty() { self.variants.insert( "_default_", Variant { - // Not that we expect to find NUL bytes, but effectively we will remove all - // delimiters with this variant. - keep_delim: '\0', + keep_delim: "", remove_delims: self.all_delims.clone(), }, ); @@ -117,17 +115,17 @@ pub fn get_variants<'a>(input: &'a str, sfx_mode: SfxMode) -> VariantList<'a> { if let Some((first, second)) = l.trim().rsplit_once(char::is_whitespace) { use SfxMode::*; match sfx_mode { - Off => state.all_delims.insert(first_char(first)), - On => state.all_delims.insert(first_char(second)), + Off => state.all_delims.insert(first), + On => state.all_delims.insert(second), }; } } else if let Some(l) = line.strip_prefix("#VARIANT") { let (first, second) = { let rest = l.trim(); if let Some((f, s)) = rest.rsplit_once(' ') { - (first_char(f), s) + (f, s) } else { - (first_char(rest), "_default_") + (rest, "_default_") } }; @@ -155,42 +153,3 @@ pub fn get_variants<'a>(input: &'a str, sfx_mode: SfxMode) -> VariantList<'a> { }) .finish() } - -fn first_char(s: &str) -> char { - s.chars().next().unwrap_or('\0') -} - -pub fn select_variant<'i>(input: &'i str, var: &'i Variant) -> String { - let mut output = input.to_string(); - // Workspace for converting char to &str in the loop. - let mut buf = [0; 4]; - // Set of chars to find in `input`. - let charlist: Vec = var - .remove_delims - .iter() - .copied() - .chain([var.keep_delim]) - .collect(); - let mut needles = input.rmatch_indices(&charlist[..]).peekable(); - - while let Some((idx, c)) = needles.next() { - match c { - // Remove the char if it is the `keep_delim`. - d if var.keep_delim.encode_utf8(&mut buf) == d => { - // `replace_range` doesn't make a full copy of the string the way `remove` does. - output.replace_range(idx..=idx, ""); - } - // Anything else will be in `remove_delim`, so find a matching pair and remove - // them and everything between them. - d => match needles.peek() { - Some(&(idx_1, d2)) if d == d2 => { - needles.next(); - output.replace_range(idx_1..=idx, ""); - } - _ => {} - }, - } - } - - output -}