option_parser: Create generic type Tuple

Creates a new generic type Tuple so that the same implementation of
FromStr trait can be reused for both parsing a list of two integers and
parsing a list of one integer associated with a list of integers.

This anticipates the need for retrieving sublists, which will be needed
when trying to describe the host CPU affinity for every vCPU.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf 2021-11-08 16:52:53 +01:00
parent e4cbafcd01
commit ad521fd4e4
2 changed files with 35 additions and 15 deletions

View File

@ -5,6 +5,7 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt; use std::fmt;
use std::num::ParseIntError;
use std::str::FromStr; use std::str::FromStr;
#[derive(Default)] #[derive(Default)]
@ -240,17 +241,39 @@ impl FromStr for IntegerList {
} }
} }
pub struct TupleTwoIntegers(pub Vec<(u64, u64)>); pub trait TupleValue {
fn parse_value(input: &str) -> Result<Self, ParseIntError>
where
Self: Sized;
}
pub enum TupleTwoIntegersParseError { impl TupleValue for u64 {
fn parse_value(input: &str) -> Result<Self, ParseIntError> {
input.parse::<u64>()
}
}
impl TupleValue for Vec<u64> {
fn parse_value(input: &str) -> Result<Self, ParseIntError> {
input
.trim_matches(|c| c == '[' || c == ']')
.split(',')
.map(|i| i.parse::<u64>())
.collect::<Result<Vec<u64>, _>>()
}
}
pub struct Tuple<T>(pub Vec<(u64, T)>);
pub enum TupleError {
InvalidValue(String), InvalidValue(String),
} }
impl FromStr for TupleTwoIntegers { impl<T: TupleValue> FromStr for Tuple<T> {
type Err = TupleTwoIntegersParseError; type Err = TupleError;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> { fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
let mut list = Vec::new(); let mut list: Vec<(u64, T)> = Vec::new();
let tuples_list: Vec<&str> = s let tuples_list: Vec<&str> = s
.trim() .trim()
.trim_matches(|c| c == '[' || c == ']') .trim_matches(|c| c == '[' || c == ']')
@ -261,22 +284,19 @@ impl FromStr for TupleTwoIntegers {
let items: Vec<&str> = tuple.split('@').collect(); let items: Vec<&str> = tuple.split('@').collect();
if items.len() != 2 { if items.len() != 2 {
return Err(TupleTwoIntegersParseError::InvalidValue( return Err(TupleError::InvalidValue((*tuple).to_string()));
(*tuple).to_string(),
));
} }
let item1 = items[0] let item1 = items[0]
.parse::<u64>() .parse::<u64>()
.map_err(|_| TupleTwoIntegersParseError::InvalidValue(items[0].to_owned()))?; .map_err(|_| TupleError::InvalidValue(items[0].to_owned()))?;
let item2 = items[1] let item2 = TupleValue::parse_value(items[1])
.parse::<u64>() .map_err(|_| TupleError::InvalidValue(items[1].to_owned()))?;
.map_err(|_| TupleTwoIntegersParseError::InvalidValue(items[1].to_owned()))?;
list.push((item1, item2)); list.push((item1, item2));
} }
Ok(TupleTwoIntegers(list)) Ok(Tuple(list))
} }
} }

View File

@ -6,7 +6,7 @@
use clap::ArgMatches; use clap::ArgMatches;
use net_util::MacAddr; use net_util::MacAddr;
use option_parser::{ use option_parser::{
ByteSized, IntegerList, OptionParser, OptionParserError, StringList, Toggle, TupleTwoIntegers, ByteSized, IntegerList, OptionParser, OptionParserError, StringList, Toggle, Tuple,
}; };
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::From; use std::convert::From;
@ -1942,7 +1942,7 @@ impl NumaConfig {
.map_err(Error::ParseNuma)? .map_err(Error::ParseNuma)?
.map(|v| v.0.iter().map(|e| *e as u8).collect()); .map(|v| v.0.iter().map(|e| *e as u8).collect());
let distances = parser let distances = parser
.convert::<TupleTwoIntegers>("distances") .convert::<Tuple<u64>>("distances")
.map_err(Error::ParseNuma)? .map_err(Error::ParseNuma)?
.map(|v| { .map(|v| {
v.0.iter() v.0.iter()