diff --git a/option_parser/src/lib.rs b/option_parser/src/lib.rs index 86424ed95..327b982a8 100644 --- a/option_parser/src/lib.rs +++ b/option_parser/src/lib.rs @@ -38,6 +38,32 @@ impl fmt::Display for OptionParserError { } type OptionParserResult = std::result::Result; +fn split_commas_outside_brackets(s: &str) -> OptionParserResult> { + let mut list: Vec = Vec::new(); + let mut opened_brackets: usize = 0; + for element in s.trim().split(',') { + if opened_brackets > 0 { + if let Some(last) = list.last_mut() { + *last = format!("{},{}", last, element); + } else { + return Err(OptionParserError::InvalidSyntax(s.to_owned())); + } + } else { + list.push(element.to_string()); + } + + opened_brackets += element.matches('[').count(); + let closing_brackets = element.matches(']').count(); + if closing_brackets > opened_brackets { + return Err(OptionParserError::InvalidSyntax(s.to_owned())); + } else { + opened_brackets -= closing_brackets; + } + } + + Ok(list) +} + impl OptionParser { pub fn new() -> Self { Self { @@ -50,29 +76,7 @@ impl OptionParser { return Ok(()); } - let mut options_list: Vec = Vec::new(); - let mut opened_brackets: usize = 0; - for element in input.trim().split(',') { - if opened_brackets > 0 { - if let Some(last) = options_list.last_mut() { - *last = format!("{},{}", last, element); - } else { - return Err(OptionParserError::InvalidSyntax(input.to_owned())); - } - } else { - options_list.push(element.to_string()); - } - - opened_brackets += element.matches('[').count(); - let closing_brackets = element.matches(']').count(); - if closing_brackets > opened_brackets { - return Err(OptionParserError::InvalidSyntax(input.to_owned())); - } else { - opened_brackets -= closing_brackets; - } - } - - for option in options_list.iter() { + for option in split_commas_outside_brackets(input)?.iter() { let parts: Vec<&str> = option.split('=').collect(); match self.options.get_mut(parts[0]) { @@ -242,44 +246,54 @@ impl FromStr for IntegerList { } pub trait TupleValue { - fn parse_value(input: &str) -> Result + fn parse_value(input: &str) -> Result where Self: Sized; } impl TupleValue for u64 { - fn parse_value(input: &str) -> Result { - input.parse::() + fn parse_value(input: &str) -> Result { + input.parse::().map_err(TupleError::InvalidInteger) + } +} + +impl TupleValue for Vec { + fn parse_value(input: &str) -> Result { + Ok(IntegerList::from_str(input) + .map_err(TupleError::InvalidIntegerList)? + .0 + .iter() + .map(|v| *v as u8) + .collect()) } } impl TupleValue for Vec { - fn parse_value(input: &str) -> Result { - input - .trim_matches(|c| c == '[' || c == ']') - .split(',') - .map(|i| i.parse::()) - .collect::, _>>() + fn parse_value(input: &str) -> Result { + Ok(IntegerList::from_str(input) + .map_err(TupleError::InvalidIntegerList)? + .0) } } -pub struct Tuple(pub Vec<(u64, T)>); +pub struct Tuple(pub Vec<(S, T)>); pub enum TupleError { InvalidValue(String), + SplitOutsideBrackets(OptionParserError), + InvalidIntegerList(IntegerListParseError), + InvalidInteger(ParseIntError), } -impl FromStr for Tuple { +impl FromStr for Tuple { type Err = TupleError; fn from_str(s: &str) -> std::result::Result { - let mut list: Vec<(u64, T)> = Vec::new(); - let tuples_list: Vec<&str> = s - .trim() - .trim_matches(|c| c == '[' || c == ']') - .split(',') - .collect(); + let mut list: Vec<(S, T)> = Vec::new(); + let tuples_list = + split_commas_outside_brackets(s.trim().trim_matches(|c| c == '[' || c == ']')) + .map_err(TupleError::SplitOutsideBrackets)?; for tuple in tuples_list.iter() { let items: Vec<&str> = tuple.split('@').collect(); @@ -288,10 +302,9 @@ impl FromStr for Tuple { } let item1 = items[0] - .parse::() + .parse::() .map_err(|_| TupleError::InvalidValue(items[0].to_owned()))?; - let item2 = TupleValue::parse_value(items[1]) - .map_err(|_| TupleError::InvalidValue(items[1].to_owned()))?; + let item2 = TupleValue::parse_value(items[1])?; list.push((item1, item2)); } diff --git a/vmm/src/config.rs b/vmm/src/config.rs index ac0373ee6..ee3026884 100644 --- a/vmm/src/config.rs +++ b/vmm/src/config.rs @@ -1942,7 +1942,7 @@ impl NumaConfig { .map_err(Error::ParseNuma)? .map(|v| v.0.iter().map(|e| *e as u8).collect()); let distances = parser - .convert::>("distances") + .convert::>("distances") .map_err(Error::ParseNuma)? .map(|v| { v.0.iter()