make the parser use the TryFrom trait.

This commit is contained in:
Dietrich 2020-09-22 20:09:53 +02:00
parent c9cba38f2f
commit 8c1a0a52f6

View File

@ -1,4 +1,5 @@
use std::cmp::Eq;
use std::convert::TryFrom;
use std::fmt::{self, Display};
#[derive(Debug, PartialEq, Eq)]
@ -64,49 +65,23 @@ impl<'a> Passwd<'a> {
return Err("Failed to parse: not enough elements");
} else {
Ok(Passwd {
username: Username {
username: elements.get(0).unwrap(),
},
password: Password {
password: elements.get(1).unwrap(),
},
uid: Uid {
uid: elements.get(2).unwrap().parse::<u32>().unwrap(),
},
gid: Gid {
gid: elements.get(3).unwrap().parse::<u32>().unwrap(),
},
gecos: parse_gecos(elements.get(4).unwrap()).unwrap(),
home_dir: HomeDir {
dir: elements.get(5).unwrap(),
},
shell_dir: ShellDir {
shell: elements.get(6).unwrap(),
},
username: Username::try_from(*elements.get(0).unwrap())
.expect("failed to parse username."),
password: Password::try_from(*elements.get(1).unwrap())
.expect("Failed to parse Password"),
uid: Uid::try_from(*elements.get(2).unwrap()).expect("Failed to parse uid"),
gid: Gid::try_from(*elements.get(3).unwrap()).expect("Failed to parse gid"),
gecos: Gecos::try_from(*elements.get(4).unwrap())
.expect("Failed to parse Gecos field"),
home_dir: HomeDir::try_from(*elements.get(5).unwrap())
.expect("Failed to parse home directory"),
shell_dir: ShellDir::try_from(*elements.get(6).unwrap())
.expect("Failed to parse shell directory"),
})
}
}
}
fn parse_gecos(source: &str) -> Result<Gecos, &str> {
let vals: Vec<&str> = source.split(',').collect();
if vals.len() == 5 {
Ok(Gecos::Detail {
full_name: vals.get(0).unwrap(),
room: vals.get(1).unwrap(),
phone_work: vals.get(2).unwrap(),
phone_home: vals.get(3).unwrap(),
other: vals.get(4).unwrap(),
})
} else if vals.len() == 1 {
Ok(Gecos::Simple {
comment: vals.get(0).unwrap(),
})
} else {
panic!(format!("Could not parse this string: {}", source))
}
}
impl Default for Passwd<'_> {
fn default() -> Self {
Passwd {
@ -151,24 +126,56 @@ impl Display for Username<'_> {
}
}
impl<'a> TryFrom<&'a str> for Username<'a> {
type Error = &'static str;
fn try_from(source: &'a str) -> std::result::Result<Self, Self::Error> {
Ok(Self { username: source })
}
}
impl Display for Password<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.password,)
}
}
impl<'a> TryFrom<&'a str> for Password<'a> {
type Error = &'static str;
fn try_from(source: &'a str) -> std::result::Result<Self, Self::Error> {
Ok(Self { password: source })
}
}
impl Display for Uid {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.uid,)
}
}
impl TryFrom<&str> for Uid {
type Error = &'static str;
fn try_from(source: &str) -> std::result::Result<Self, Self::Error> {
Ok(Self {
uid: source.parse::<u32>().unwrap(),
})
}
}
impl Display for Gid {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.gid,)
}
}
impl TryFrom<&str> for Gid {
type Error = &'static str;
fn try_from(source: &str) -> std::result::Result<Self, Self::Error> {
Ok(Self {
gid: source.parse::<u32>().unwrap(),
})
}
}
impl Display for Gecos<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self {
@ -188,18 +195,54 @@ impl Display for Gecos<'_> {
}
}
impl<'a> TryFrom<&'a str> for Gecos<'a> {
type Error = &'static str;
fn try_from(source: &'a str) -> std::result::Result<Self, Self::Error> {
let vals: Vec<&str> = source.split(',').collect();
if vals.len() == 5 {
Ok(Gecos::Detail {
full_name: vals.get(0).unwrap(),
room: vals.get(1).unwrap(),
phone_work: vals.get(2).unwrap(),
phone_home: vals.get(3).unwrap(),
other: vals.get(4).unwrap(),
})
} else if vals.len() == 1 {
Ok(Gecos::Simple {
comment: vals.get(0).unwrap(),
})
} else {
panic!(format!("Could not parse this string: {}", source))
}
}
}
impl Display for HomeDir<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.dir,)
}
}
impl<'a> TryFrom<&'a str> for HomeDir<'a> {
type Error = &'static str;
fn try_from(source: &'a str) -> std::result::Result<Self, Self::Error> {
Ok(Self { dir: source })
}
}
impl Display for ShellDir<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.shell,)
}
}
impl<'a> TryFrom<&'a str> for ShellDir<'a> {
type Error = &'static str;
fn try_from(source: &'a str) -> std::result::Result<Self, Self::Error> {
Ok(Self { shell: source })
}
}
// Tests ----------------------------------------------------------------------
#[test]
@ -216,8 +259,8 @@ fn test_parse_gecos() {
// test if the Gecos field can be parsed and the resulting struct is populated correctly.
let gcd = "Full Name,504,11345342,ä1-2312,myemail@test.com";
let gcs = "A böring comment →";
let res_detail = parse_gecos(gcd).unwrap();
let res_simple = parse_gecos(gcs).unwrap();
let res_detail = Gecos::try_from(gcd).unwrap();
let res_simple = Gecos::try_from(gcs).unwrap();
match res_simple {
Gecos::Simple { comment } => assert_eq!(comment, "A böring comment →"),
_ => unreachable!(),