diff --git a/src/group/mod.rs b/src/group/mod.rs index b8a9df6..cf1fcda 100644 --- a/src/group/mod.rs +++ b/src/group/mod.rs @@ -106,15 +106,15 @@ impl NewFromString for Group { /// use crate::adduser::api::GroupRead; /// use adduser::NewFromString; /// let grp = adduser::Group::new_from_string( - /// "teste:x:1002:test,teste".to_owned() + /// "teste:x:1002:test,teste".to_owned(), + /// 0, /// ).unwrap(); /// assert_eq!(grp.get_groupname().unwrap(), "teste"); /// ``` /// /// # Errors /// When parsing fails this function returns a `UserLibError::Message` containing some information as to why the function failed. - fn new_from_string(line: String) -> Result { - println!("{}", &line); + fn new_from_string(line: String, position: u32) -> Result { let elements: Vec = line.split(':').map(ToString::to_string).collect(); if elements.len() == 4 { Ok(Self { @@ -150,19 +150,19 @@ fn parse_members_list(source: &str) -> Vec { #[test] fn test_parse_and_back_identity() { let line = "teste:x:1002:test,teste"; - let line2 = Group::new_from_string(line.to_owned()).unwrap(); + let line2 = Group::new_from_string(line.to_owned(), 0).unwrap(); assert_eq!(format!("{}", line2), line); } #[test] fn test_groupname() { let line = "teste:x:1002:test,teste"; - let line2 = Group::new_from_string(line.to_owned()).unwrap(); + let line2 = Group::new_from_string(line.to_owned(), 0).unwrap(); assert_eq!(line2.get_groupname().unwrap(), "teste"); } #[test] fn test_root_group() { let line = "root:x:0:"; - let line2 = Group::new_from_string(line.to_owned()).unwrap(); + let line2 = Group::new_from_string(line.to_owned(), 0).unwrap(); assert_eq!(line2.get_groupname().unwrap(), "root"); } diff --git a/src/user/gecos_fields.rs b/src/user/gecos_fields.rs index cb52765..a7fc8ee 100644 --- a/src/user/gecos_fields.rs +++ b/src/user/gecos_fields.rs @@ -205,7 +205,6 @@ fn test_gecos_getters() { assert_eq!(res_simple.get_comment(), Some("A böring comment →")); assert_eq!(res_detail.get_comment(), None); - println!("{:?}", res_detail); assert_eq!(res_detail.get_full_name(), Some("Full Name")); assert_eq!(res_detail.get_room(), Some("504")); assert_eq!(res_detail.get_phone_work(), Some("11345342")); diff --git a/src/user/mod.rs b/src/user/mod.rs index b5a468b..eb384c4 100644 --- a/src/user/mod.rs +++ b/src/user/mod.rs @@ -10,6 +10,7 @@ use std::fmt::{self, Display}; #[derive(Debug, PartialEq, Eq)] pub struct User { source: String, + pos: u32, username: crate::Username, /* Username. */ pub(crate) password: crate::Password, /* Hashed passphrase, if shadow database not in use (see shadow.h). */ uid: crate::Uid, /* User ID. */ @@ -27,13 +28,13 @@ impl NewFromString for User { /// use crate::adduser::api::UserRead; /// use adduser::NewFromString; /// let pwd = adduser::User::new_from_string( - /// "testuser:testpassword:1001:1001:full Name,,,,:/home/test:/bin/test".to_string()).unwrap(); + /// "testuser:testpassword:1001:1001:full Name,,,,:/home/test:/bin/test".to_string(), 0).unwrap(); /// assert_eq!(pwd.get_username().unwrap(), "testuser"); /// ``` /// /// # Errors /// When parsing fails this function returns a [`UserLibError::Message`](crate::userlib_error::UserLibError::Message) containing some information as to why the function failed. - fn new_from_string(line: String) -> Result + fn new_from_string(line: String, position: u32) -> Result where Self: Sized, { @@ -41,6 +42,7 @@ impl NewFromString for User { if elements.len() == 7 { Ok(Self { source: line, + pos: position, username: crate::Username::try_from(elements.get(0).unwrap().to_string())?, password: crate::Password::Encrypted(crate::EncryptedPassword::try_from( elements.get(1).unwrap().to_string(), @@ -112,10 +114,23 @@ impl crate::api::UserRead for User { } } +impl PartialOrd for User { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.pos.cmp(&other.pos)) + } +} + +impl Ord for User { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.pos.cmp(&other.pos) + } +} + impl Default for User { fn default() -> Self { Self { source: "".to_owned(), + pos: u32::MAX, username: crate::Username { username: "defaultuser".to_owned(), }, @@ -165,17 +180,18 @@ fn test_default_user() { #[test] fn test_new_from_string() { // Test if a single line can be parsed and if the resulting struct is populated correctly. - let fail = User::new_from_string("".into()).err().unwrap(); + let fail = User::new_from_string("".into(), 0).err().unwrap(); assert_eq!( fail, crate::UserLibError::Message("Failed to parse: not enough elements".into()) ); let pwd = User::new_from_string( "testuser:testpassword:1001:1001:testcomment:/home/test:/bin/test".into(), + 0, ) .unwrap(); let pwd2 = - User::new_from_string("testuser:testpassword:1001:1001:full Name,004,000342,001-2312,myemail@test.com:/home/test:/bin/test".into()) + User::new_from_string("testuser:testpassword:1001:1001:full Name,004,000342,001-2312,myemail@test.com:/home/test:/bin/test".into(),0) .unwrap(); assert_eq!(pwd.username.username, "testuser"); assert_eq!(pwd.home_dir.dir, "/home/test"); @@ -210,10 +226,10 @@ fn test_parse_passwd() { let file = File::open("/etc/passwd").unwrap(); let reader = BufReader::new(file); - for line in reader.lines() { + for (n, line) in reader.lines().enumerate() { let lineorig: String = line.unwrap(); let linecopy = lineorig.clone(); - let pass_struc = User::new_from_string(linecopy).unwrap(); + let pass_struc = User::new_from_string(linecopy, n as u32).unwrap(); assert_eq!( // ignoring the numbers of `,` since the implementation does not (yet) reproduce a missing comment field. lineorig, diff --git a/src/user/shadow_fields.rs b/src/user/shadow_fields.rs index 423af98..6056315 100644 --- a/src/user/shadow_fields.rs +++ b/src/user/shadow_fields.rs @@ -85,15 +85,15 @@ impl NewFromString for Shadow { /// ``` /// use adduser::NewFromString; /// let shad = adduser::Shadow::new_from_string( - /// "test:!!$6$/RotIe4VZzzAun4W$7YUONvru1rDnllN5TvrnOMsWUD5wSDUPAD6t6/Xwsr/0QOuWF3HcfAhypRkGa8G1B9qqWV5kZSnCb8GKMN9N61:18260:0:99999:7:::".to_string() + /// "test:!!$6$/RotIe4VZzzAun4W$7YUONvru1rDnllN5TvrnOMsWUD5wSDUPAD6t6/Xwsr/0QOuWF3HcfAhypRkGa8G1B9qqWV5kZSnCb8GKMN9N61:18260:0:99999:7:::".to_string(), + /// 0, /// ).unwrap(); /// assert_eq!(shad.get_username(), "test"); /// ``` /// /// # Errors /// When parsing fails this function returns a `UserLibError::Message` containing some information as to why the function failed. - fn new_from_string(line: String) -> Result { - println!("{}", &line); + fn new_from_string(line: String, position: u32) -> Result { let elements: Vec = line.split(':').map(ToString::to_string).collect(); if elements.len() == 9 { let extra = elements.get(8).unwrap(); @@ -144,9 +144,7 @@ fn duration_for_days(days_source: &str) -> Option { #[test] fn test_parse_and_back_identity() { - println!("Test"); let line = "test:!!$6$/RotIe4VZzzAun4W$7YUONvru1rDnllN5TvrnOMsWUD5wSDUPAD6t6/Xwsr/0QOuWF3HcfAhypRkGa8G1B9qqWV5kZSnCb8GKMN9N61:18260:0:99999:7:::"; - let line2 = Shadow::new_from_string(line.to_owned()).unwrap(); - println!("{:#?}", line2); + let line2 = Shadow::new_from_string(line.to_owned(), 0).unwrap(); assert_eq!(format!("{}", line2), line); } diff --git a/src/userlib.rs b/src/userlib.rs index 1bf825c..2528cbf 100644 --- a/src/userlib.rs +++ b/src/userlib.rs @@ -145,7 +145,9 @@ impl UserDBWrite for UserDBLocal { use crate::api::UserDBRead; impl UserDBRead for UserDBLocal { fn get_all_users(&self) -> Vec<&crate::User> { - self.users.iter().map(|(_, x)| x).collect() + let mut res: Vec<&crate::User> = self.users.iter().map(|(_, x)| x).collect(); + res.sort(); + res } fn get_user_by_name(&self, name: &str) -> Option<&crate::User> { @@ -258,7 +260,7 @@ fn user_vec_to_hashmap(users: Vec) -> HashMap /// # Errors /// if the parsing failed a [`UserLibError::Message`](crate::userlib_error::UserLibError::Message) is returned containing a more detailed error message. pub trait NewFromString { - fn new_from_string(line: String) -> Result + fn new_from_string(line: String, position: u32) -> Result where Self: Sized; } @@ -270,10 +272,10 @@ where { source .lines() - .filter_map(|line| { + .enumerate() + .filter_map(|(n, line)| { if line.len() > 5 { - //println!("{}", line); - Some(T::new_from_string(line.to_owned()).expect("failed to read lines")) + Some(T::new_from_string(line.to_owned(), n as u32).expect("failed to read lines")) } else { None }