Add custom errors
This commit is contained in:
parent
3232f2b1da
commit
5d83f1264f
@ -1,3 +1,3 @@
|
|||||||
pub mod passwd;
|
pub mod passwd;
|
||||||
|
pub mod userlib_error;
|
||||||
pub use passwd::{Password, Username};
|
pub use passwd::{Password, Username};
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
/*#![warn(
|
#![warn(
|
||||||
clippy::all,
|
clippy::all,
|
||||||
clippy::restriction,
|
/* clippy::restriction,*/
|
||||||
clippy::pedantic,
|
clippy::pedantic,
|
||||||
clippy::nursery,
|
clippy::nursery,
|
||||||
clippy::cargo
|
clippy::cargo
|
||||||
)]*/
|
)]
|
||||||
|
use crate::userlib_error::UserLibError;
|
||||||
use std::cmp::Eq;
|
use std::cmp::Eq;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::fmt::{self, Display};
|
use std::fmt::{self, Display};
|
||||||
@ -72,8 +73,20 @@ pub struct Passwd<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Passwd<'a> {
|
impl<'a> Passwd<'a> {
|
||||||
pub fn new_from_string(line: &'a str) -> Result<Self, &str> {
|
/// Parse a line formatted like one in `/etc/passwd` and construct a matching `Passwd` instance
|
||||||
let elements: Vec<&str> = line.split(":").collect();
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// let pwd = adduser::passwd::Passwd::new_from_string(
|
||||||
|
/// "testuser:testpassword:1001:1001:full Name,004,000342,001-2312,myemail@test.com:/home/test:/bin/test"
|
||||||
|
/// ).unwrap();
|
||||||
|
/// assert!(format!("{:?}", pwd).find("testuser") > Some(0));
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// When parsing fails this function returns a `UserLibError::Message` containing some information as to why the function failed.
|
||||||
|
pub fn new_from_string(line: &'a str) -> Result<Self, UserLibError> {
|
||||||
|
let elements: Vec<&str> = line.split(':').collect();
|
||||||
if elements.len() == 7 {
|
if elements.len() == 7 {
|
||||||
Ok(Passwd {
|
Ok(Passwd {
|
||||||
username: Username::try_from(*elements.get(0).unwrap())
|
username: Username::try_from(*elements.get(0).unwrap())
|
||||||
@ -90,7 +103,9 @@ impl<'a> Passwd<'a> {
|
|||||||
.expect("Failed to parse shell directory"),
|
.expect("Failed to parse shell directory"),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err("Failed to parse: not enough elements")
|
Err(UserLibError::Message(
|
||||||
|
"Failed to parse: not enough elements".to_owned(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -228,8 +243,7 @@ impl<'a> TryFrom<&'a str> for Gecos<'a> {
|
|||||||
phone_home: vals.get(3).unwrap(),
|
phone_home: vals.get(3).unwrap(),
|
||||||
other: "",
|
other: "",
|
||||||
})
|
})
|
||||||
}
|
} else if vals.len() == 1 {
|
||||||
else if vals.len() == 1 {
|
|
||||||
Ok(Gecos::Simple {
|
Ok(Gecos::Simple {
|
||||||
comment: vals.get(0).unwrap(),
|
comment: vals.get(0).unwrap(),
|
||||||
})
|
})
|
||||||
@ -279,11 +293,11 @@ fn test_default_user() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_parse_gecos() {
|
fn test_parse_gecos() {
|
||||||
// test if the Gecos field can be parsed and the resulting struct is populated correctly.
|
// 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 gcdetail = "Full Name,504,11345342,ä1-2312,myemail@test.com";
|
||||||
let gcs = "A böring comment →";
|
let gcsimple = "A böring comment →";
|
||||||
let gc_no_other: &str = "systemd Network Management,,,";
|
let gc_no_other: &str = "systemd Network Management,,,";
|
||||||
let res_detail = Gecos::try_from(gcd).unwrap();
|
let res_detail = Gecos::try_from(gcdetail).unwrap();
|
||||||
let res_simple = Gecos::try_from(gcs).unwrap();
|
let res_simple = Gecos::try_from(gcsimple).unwrap();
|
||||||
let res_no_other = Gecos::try_from(gc_no_other).unwrap();
|
let res_no_other = Gecos::try_from(gc_no_other).unwrap();
|
||||||
match res_simple {
|
match res_simple {
|
||||||
Gecos::Simple { comment } => assert_eq!(comment, "A böring comment →"),
|
Gecos::Simple { comment } => assert_eq!(comment, "A böring comment →"),
|
||||||
@ -369,8 +383,8 @@ fn test_parse_passwd() {
|
|||||||
let lineorig: String = line.unwrap();
|
let lineorig: String = line.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
// ignoring the numbers of `,` since the implementation does not (yet) reproduce a missing comment field.
|
// ignoring the numbers of `,` since the implementation does not (yet) reproduce a missing comment field.
|
||||||
format!("{}", Passwd::new_from_string(&lineorig.clone()).unwrap()).replace(",",""),
|
format!("{}", Passwd::new_from_string(&lineorig.clone()).unwrap()).replace(",", ""),
|
||||||
lineorig.replace(",","")
|
lineorig.replace(",", "")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
32
src/userlib_error.rs
Normal file
32
src/userlib_error.rs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
use std::error::Error;
|
||||||
|
use std::fmt::{self, Display};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum UserLibError {
|
||||||
|
NotFound,
|
||||||
|
Message(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for UserLibError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::NotFound => write!(f, ""),
|
||||||
|
Self::Message(message) => write!(f, "{}", message),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for UserLibError {
|
||||||
|
fn description(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
Self::NotFound => "not found",
|
||||||
|
Self::Message(message) => message,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<String> for UserLibError {
|
||||||
|
fn from(err: String) -> Self {
|
||||||
|
Self::Message(err)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user