use std::str::FromStr;
pub(crate) trait StrParts<'a> {
fn split_line(self) -> Vec<&'a str>;
}
impl<'a> StrParts<'a> for &'a str {
fn split_line(self) -> Vec<&'a str> {
self.split_whitespace()
.map_while(|s| (!s.starts_with('#')).then(|| s))
.collect()
}
}
pub(crate) trait ConvertVec {
fn parse_string_to<T, G>(self) -> Result<Vec<T>, G>
where
T: FromStr<Err = G>;
}
impl ConvertVec for Vec<&str> {
fn parse_string_to<T, G>(self) -> Result<Vec<T>, G>
where
T: FromStr<Err = G>,
{
self.into_iter()
.map(FromStr::from_str)
.collect::<Result<Vec<T>, G>>()
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::num::IntErrorKind;
#[test]
fn split_line() {
assert_eq!("".split_line(), Vec::<&str>::new());
assert_eq!("1 2 3".split_line(), vec!["1", "2", "3"]);
assert_eq!("1 2 3.0".split_line(), vec!["1", "2", "3.0"]);
}
#[test]
fn convert_vec() {
assert_eq!(
vec!["1.0", "2.0", "-3.0"].parse_string_to::<f64, _>(),
Ok(vec![1.0, 2.0, -3.0])
);
assert_eq!(
vec!["1", "2", "3"].parse_string_to::<u8, _>(),
Ok(vec![1u8, 2u8, 3u8])
);
assert_eq!(
vec!["1", "2", "3.0"]
.parse_string_to::<u8, _>()
.unwrap_err()
.kind(),
&IntErrorKind::InvalidDigit
);
}
#[test]
fn split_convert() {
assert_eq!(
" 1 2 3 ".split_line().parse_string_to::<f64, _>(),
Ok(vec![1.0, 2.0, 3.0])
);
assert_eq!(
" 1 2 3".split_line().parse_string_to::<f32, _>(),
Ok(vec![1.0, 2.0, 3.0])
);
}
}