Add better error handling
This commit is contained in:
		
							parent
							
								
									bf6908346e
								
							
						
					
					
						commit
						1af8a7cd65
					
				@ -18,7 +18,7 @@ fn main() {
 | 
				
			|||||||
        group: Some(PathBuf::from("./group")),
 | 
					        group: Some(PathBuf::from("./group")),
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut db = adduser::UserDBLocal::load_files(mf);
 | 
					    let mut db = adduser::UserDBLocal::load_files(mf).unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let user_res: Result<adduser::User, adduser::UserLibError> = db.delete_user("teste");
 | 
					    let user_res: Result<adduser::User, adduser::UserLibError> = db.delete_user("teste");
 | 
				
			||||||
    match user_res {
 | 
					    match user_res {
 | 
				
			||||||
 | 
				
			|||||||
@ -9,7 +9,7 @@ fn main() {
 | 
				
			|||||||
    .unwrap();
 | 
					    .unwrap();
 | 
				
			||||||
    use adduser::api::UserDBRead;
 | 
					    use adduser::api::UserDBRead;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let db = adduser::UserDBLocal::load_files(adduser::Files::default());
 | 
					    let db = adduser::UserDBLocal::load_files(adduser::Files::default()).unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for u in db.get_all_users() {
 | 
					    for u in db.get_all_users() {
 | 
				
			||||||
        println!("{}", u);
 | 
					        println!("{}", u);
 | 
				
			||||||
 | 
				
			|||||||
@ -35,10 +35,7 @@ impl TryFrom<String> for Groupname {
 | 
				
			|||||||
            warn!("username {} is not a valid username. This might cause problems. (It is default in Debian and Ubuntu)", source);
 | 
					            warn!("username {} is not a valid username. This might cause problems. (It is default in Debian and Ubuntu)", source);
 | 
				
			||||||
            Ok(Self { groupname: source })
 | 
					            Ok(Self { groupname: source })
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            Err(UserLibError::Message(format!(
 | 
					            Err(format!("Invalid groupname -{}-", source).into())
 | 
				
			||||||
                "Invalid groupname -{}-",
 | 
					 | 
				
			||||||
                source
 | 
					 | 
				
			||||||
            )))
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -128,11 +125,12 @@ impl NewFromString for Group {
 | 
				
			|||||||
                members: parse_members_list(elements.get(3).unwrap()),
 | 
					                members: parse_members_list(elements.get(3).unwrap()),
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            Err(UserLibError::Message(format!(
 | 
					            Err(format!(
 | 
				
			||||||
                "Failed to parse: not enough elements ({}): {:?}",
 | 
					                "Failed to parse: not enough elements ({}): {:?}",
 | 
				
			||||||
                elements.len(),
 | 
					                elements.len(),
 | 
				
			||||||
                elements
 | 
					                elements
 | 
				
			||||||
            )))
 | 
					            )
 | 
				
			||||||
 | 
					            .into())
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -243,10 +243,7 @@ fn test_default_user() {
 | 
				
			|||||||
fn test_new_from_string() {
 | 
					fn test_new_from_string() {
 | 
				
			||||||
    // Test if a single line can be parsed and if the resulting struct is populated correctly.
 | 
					    // Test if a single line can be parsed and if the resulting struct is populated correctly.
 | 
				
			||||||
    let fail = User::new_from_string("".into(), 0).err().unwrap();
 | 
					    let fail = User::new_from_string("".into(), 0).err().unwrap();
 | 
				
			||||||
    assert_eq!(
 | 
					    assert_eq!(fail, "Failed to parse: not enough elements".into());
 | 
				
			||||||
        fail,
 | 
					 | 
				
			||||||
        crate::UserLibError::Message("Failed to parse: not enough elements".into())
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
    let pwd = User::new_from_string(
 | 
					    let pwd = User::new_from_string(
 | 
				
			||||||
        "testuser:testpassword:1001:1001:testcomment:/home/test:/bin/test".into(),
 | 
					        "testuser:testpassword:1001:1001:testcomment:/home/test:/bin/test".into(),
 | 
				
			||||||
        0,
 | 
					        0,
 | 
				
			||||||
 | 
				
			|||||||
@ -41,10 +41,7 @@ impl TryFrom<String> for Username {
 | 
				
			|||||||
            warn!("username {} is not a valid username. This might cause problems. (It is default in Debian and Ubuntu)", source);
 | 
					            warn!("username {} is not a valid username. This might cause problems. (It is default in Debian and Ubuntu)", source);
 | 
				
			||||||
            Ok(Self { username: source })
 | 
					            Ok(Self { username: source })
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            Err(UserLibError::Message(format!(
 | 
					            Err(format!("Invalid username {}", source).into())
 | 
				
			||||||
                "Invalid username {}",
 | 
					 | 
				
			||||||
                source
 | 
					 | 
				
			||||||
            )))
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -201,25 +198,14 @@ impl TryFrom<String> for ShellPath {
 | 
				
			|||||||
fn test_username_validation() {
 | 
					fn test_username_validation() {
 | 
				
			||||||
    // Failing tests
 | 
					    // Failing tests
 | 
				
			||||||
    let umlauts: Result<Username, UserLibError> = Username::try_from("täst".to_owned()); // umlauts
 | 
					    let umlauts: Result<Username, UserLibError> = Username::try_from("täst".to_owned()); // umlauts
 | 
				
			||||||
    assert_eq!(
 | 
					    assert_eq!(Err("Invalid username täst".into()), umlauts);
 | 
				
			||||||
        Err(UserLibError::Message("Invalid username täst".into())),
 | 
					 | 
				
			||||||
        umlauts
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
    let number_first = Username::try_from("11elf".to_owned()); // numbers first
 | 
					    let number_first = Username::try_from("11elf".to_owned()); // numbers first
 | 
				
			||||||
    assert_eq!(
 | 
					    assert_eq!(Err("Invalid username 11elf".into()), number_first);
 | 
				
			||||||
        Err(UserLibError::Message("Invalid username 11elf".into())),
 | 
					 | 
				
			||||||
        number_first
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
    let slashes = Username::try_from("test/name".to_owned()); // slashes in the name
 | 
					    let slashes = Username::try_from("test/name".to_owned()); // slashes in the name
 | 
				
			||||||
    assert_eq!(
 | 
					    assert_eq!(Err("Invalid username test/name".into()), slashes);
 | 
				
			||||||
        Err(UserLibError::Message("Invalid username test/name".into())),
 | 
					 | 
				
			||||||
        slashes
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
    let long = Username::try_from("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".to_owned()); // maximum size 32 letters
 | 
					    let long = Username::try_from("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".to_owned()); // maximum size 32 letters
 | 
				
			||||||
    assert_eq!(
 | 
					    assert_eq!(
 | 
				
			||||||
        Err(UserLibError::Message(
 | 
					        Err("Invalid username aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".into()),
 | 
				
			||||||
            "Invalid username aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".to_owned()
 | 
					 | 
				
			||||||
        )),
 | 
					 | 
				
			||||||
        long
 | 
					        long
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    // Working tests
 | 
					    // Working tests
 | 
				
			||||||
 | 
				
			|||||||
@ -117,11 +117,12 @@ impl NewFromString for Shadow {
 | 
				
			|||||||
                },
 | 
					                },
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            Err(UserLibError::Message(format!(
 | 
					            Err(format!(
 | 
				
			||||||
                "Failed to parse: not enough elements ({}): {:?}",
 | 
					                "Failed to parse: not enough elements ({}): {:?}",
 | 
				
			||||||
                elements.len(),
 | 
					                elements.len(),
 | 
				
			||||||
                elements
 | 
					                elements
 | 
				
			||||||
            )))
 | 
					            )
 | 
				
			||||||
 | 
					            .into())
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -270,15 +270,15 @@ impl UserDBLocal {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /// Import the database from a [`Files`] struct
 | 
					    /// Import the database from a [`Files`] struct
 | 
				
			||||||
    #[must_use]
 | 
					    #[must_use]
 | 
				
			||||||
    pub fn load_files(files: Files) -> Self {
 | 
					    pub fn load_files(files: Files) -> Result<Self, crate::UserLibError> {
 | 
				
			||||||
        // Get the Strings for the files use an inner block to drop references after read.
 | 
					        // Get the Strings for the files use an inner block to drop references after read.
 | 
				
			||||||
        let (my_passwd_lines, my_shadow_lines, my_group_lines) = {
 | 
					        let (my_passwd_lines, my_shadow_lines, my_group_lines) = {
 | 
				
			||||||
            let opened = files.lock_all_get();
 | 
					            let opened = files.lock_all_get();
 | 
				
			||||||
            let (locked_p, locked_s, locked_g) = opened.expect("failed to lock files!");
 | 
					            let (locked_p, locked_s, locked_g) = opened.expect("failed to lock files!");
 | 
				
			||||||
            // read the files to strings
 | 
					            // read the files to strings
 | 
				
			||||||
            let p = file_to_string(&locked_p.file);
 | 
					            let p = file_to_string(&locked_p.file)?;
 | 
				
			||||||
            let s = file_to_string(&locked_s.file);
 | 
					            let s = file_to_string(&locked_s.file)?;
 | 
				
			||||||
            let g = file_to_string(&locked_g.file);
 | 
					            let g = file_to_string(&locked_g.file)?;
 | 
				
			||||||
            // return the strings to the outer scope and release the lock...
 | 
					            // return the strings to the outer scope and release the lock...
 | 
				
			||||||
            (p, s, g)
 | 
					            (p, s, g)
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
@ -286,12 +286,12 @@ impl UserDBLocal {
 | 
				
			|||||||
        let mut users = user_vec_to_hashmap(string_to(&my_passwd_lines));
 | 
					        let mut users = user_vec_to_hashmap(string_to(&my_passwd_lines));
 | 
				
			||||||
        let passwds: Vec<crate::Shadow> = string_to(&my_shadow_lines);
 | 
					        let passwds: Vec<crate::Shadow> = string_to(&my_shadow_lines);
 | 
				
			||||||
        shadow_to_users(&mut users, passwds);
 | 
					        shadow_to_users(&mut users, passwds);
 | 
				
			||||||
        Self {
 | 
					        Ok(Self {
 | 
				
			||||||
            source_files: files,
 | 
					            source_files: files,
 | 
				
			||||||
            users,
 | 
					            users,
 | 
				
			||||||
            groups: string_to(&my_group_lines),
 | 
					            groups: string_to(&my_group_lines),
 | 
				
			||||||
            source_hashes: Hashes::new(&my_passwd_lines, &my_shadow_lines, &my_group_lines),
 | 
					            source_hashes: Hashes::new(&my_passwd_lines, &my_shadow_lines, &my_group_lines),
 | 
				
			||||||
        }
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -300,11 +300,8 @@ impl UserDBWrite for UserDBLocal {
 | 
				
			|||||||
    fn delete_user(&mut self, username: &str) -> Result<crate::User, crate::UserLibError> {
 | 
					    fn delete_user(&mut self, username: &str) -> Result<crate::User, crate::UserLibError> {
 | 
				
			||||||
        let opened = self.source_files.lock_all_get();
 | 
					        let opened = self.source_files.lock_all_get();
 | 
				
			||||||
        let (mut locked_p, locked_s, locked_g) = opened.expect("failed to lock files!");
 | 
					        let (mut locked_p, locked_s, locked_g) = opened.expect("failed to lock files!");
 | 
				
			||||||
        // read the files to strings
 | 
					
 | 
				
			||||||
        let p = file_to_string(&locked_p.file);
 | 
					        // try to get the user from the database
 | 
				
			||||||
        let _s = file_to_string(&locked_s.file);
 | 
					 | 
				
			||||||
        let _g = file_to_string(&locked_g.file);
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
        let user_opt = self.users.get(username);
 | 
					        let user_opt = self.users.get(username);
 | 
				
			||||||
        let user = match user_opt {
 | 
					        let user = match user_opt {
 | 
				
			||||||
            Some(user) => user,
 | 
					            Some(user) => user,
 | 
				
			||||||
@ -312,17 +309,30 @@ impl UserDBWrite for UserDBLocal {
 | 
				
			|||||||
                return Err(crate::UserLibError::NotFound);
 | 
					                return Err(crate::UserLibError::NotFound);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // read the files to strings
 | 
				
			||||||
 | 
					        let p = file_to_string(&locked_p.file)?;
 | 
				
			||||||
 | 
					        let _s = file_to_string(&locked_s.file)?;
 | 
				
			||||||
 | 
					        let _g = file_to_string(&locked_g.file)?;
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
            if self.source_hashes.passwd.has_changed(&p) {
 | 
					            if self.source_hashes.passwd.has_changed(&p) {
 | 
				
			||||||
                error!("The source file has changed. Deleting the user could corrupt the userdatabase. Aborting!");
 | 
					                error!("The source files have changed. Deleting the user could corrupt the userdatabase. Aborting!");
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                // create the new content of passwd
 | 
					                // create the new content of passwd
 | 
				
			||||||
                let modified = user.remove_in(&p);
 | 
					                let modified = user.remove_in(&p);
 | 
				
			||||||
                // write the new content to the file.
 | 
					                // write the new content to the file.
 | 
				
			||||||
                locked_p
 | 
					                let ncont = locked_p.replace_contents(modified);
 | 
				
			||||||
                    .replace_contents(modified)
 | 
					                match ncont {
 | 
				
			||||||
                    .expect("Error during write to the database. Please doublecheck as the userdatabase could be corrupted");
 | 
					                    Ok(_) => {
 | 
				
			||||||
                        return Ok(user.clone());
 | 
					                        return Ok(user.clone());
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					                    Err(_) => {
 | 
				
			||||||
 | 
					                        return Err("Error during write to the database. \
 | 
				
			||||||
 | 
					                        Please doublecheck as the userdatabase could be corrupted: {}"
 | 
				
			||||||
 | 
					                            .into());
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            Err(format!("The user has been changed {}", username).into())
 | 
					            Err(format!("The user has been changed {}", username).into())
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -490,11 +500,14 @@ impl Hashes {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Parse a file to a string
 | 
					/// Parse a file to a string
 | 
				
			||||||
fn file_to_string(file: &File) -> String {
 | 
					fn file_to_string(file: &File) -> Result<String, crate::UserLibError> {
 | 
				
			||||||
    let mut reader = BufReader::new(file);
 | 
					    let mut reader = BufReader::new(file);
 | 
				
			||||||
    let mut lines = String::new();
 | 
					    let mut lines = String::new();
 | 
				
			||||||
    reader.read_to_string(&mut lines).unwrap();
 | 
					    let res = reader.read_to_string(&mut lines);
 | 
				
			||||||
    lines
 | 
					    match res {
 | 
				
			||||||
 | 
					        Ok(_) => Ok(lines),
 | 
				
			||||||
 | 
					        Err(e) => Err(format!("failed to read the file: {:?}", e).into()),
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Merge the Shadow passwords into the users
 | 
					/// Merge the Shadow passwords into the users
 | 
				
			||||||
@ -568,8 +581,8 @@ fn test_parsing_local_database() {
 | 
				
			|||||||
    // Parse the worldreadable user database ignore the shadow database as this would require root privileges.
 | 
					    // Parse the worldreadable user database ignore the shadow database as this would require root privileges.
 | 
				
			||||||
    let pwdfile = File::open(PathBuf::from("/etc/passwd")).unwrap();
 | 
					    let pwdfile = File::open(PathBuf::from("/etc/passwd")).unwrap();
 | 
				
			||||||
    let grpfile = File::open(PathBuf::from("/etc/group")).unwrap();
 | 
					    let grpfile = File::open(PathBuf::from("/etc/group")).unwrap();
 | 
				
			||||||
    let my_passwd_lines = file_to_string(&pwdfile);
 | 
					    let my_passwd_lines = file_to_string(&pwdfile).unwrap();
 | 
				
			||||||
    let my_group_lines = file_to_string(&grpfile);
 | 
					    let my_group_lines = file_to_string(&grpfile).unwrap();
 | 
				
			||||||
    let data = UserDBLocal::import_from_strings(&my_passwd_lines, "", &my_group_lines);
 | 
					    let data = UserDBLocal::import_from_strings(&my_passwd_lines, "", &my_group_lines);
 | 
				
			||||||
    assert_eq!(data.groups.get(0).unwrap().get_groupname().unwrap(), "root");
 | 
					    assert_eq!(data.groups.get(0).unwrap().get_groupname().unwrap(), "root");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -578,8 +591,8 @@ fn test_parsing_local_database() {
 | 
				
			|||||||
fn test_user_db_read_implementation() {
 | 
					fn test_user_db_read_implementation() {
 | 
				
			||||||
    let pwdfile = File::open(PathBuf::from("/etc/passwd")).unwrap();
 | 
					    let pwdfile = File::open(PathBuf::from("/etc/passwd")).unwrap();
 | 
				
			||||||
    let grpfile = File::open(PathBuf::from("/etc/group")).unwrap();
 | 
					    let grpfile = File::open(PathBuf::from("/etc/group")).unwrap();
 | 
				
			||||||
    let pass = file_to_string(&pwdfile);
 | 
					    let pass = file_to_string(&pwdfile).unwrap();
 | 
				
			||||||
    let group = file_to_string(&grpfile);
 | 
					    let group = file_to_string(&grpfile).unwrap();
 | 
				
			||||||
    let data = UserDBLocal::import_from_strings(&pass, "", &group);
 | 
					    let data = UserDBLocal::import_from_strings(&pass, "", &group);
 | 
				
			||||||
    // Usually there are more than 10 users
 | 
					    // Usually there are more than 10 users
 | 
				
			||||||
    assert!(data.get_all_users().len() > 10);
 | 
					    assert!(data.get_all_users().len() > 10);
 | 
				
			||||||
@ -605,6 +618,7 @@ fn test_user_db_read_implementation() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#[test]
 | 
					#[test]
 | 
				
			||||||
fn test_user_db_write_implementation() {
 | 
					fn test_user_db_write_implementation() {
 | 
				
			||||||
 | 
					    /* only works on files now
 | 
				
			||||||
    let mut data = UserDBLocal::import_from_strings("test:x:1001:1001:full Name,004,000342,001-2312,myemail@test.com:/home/test:/bin/test", "test:!!$6$/RotIe4VZzzAun4W$7YUONvru1rDnllN5TvrnOMsWUD5wSDUPAD6t6/Xwsr/0QOuWF3HcfAhypRkGa8G1B9qqWV5kZSnCb8GKMN9N61:18260:0:99999:7:::", "teste:x:1002:test,test");
 | 
					    let mut data = UserDBLocal::import_from_strings("test:x:1001:1001:full Name,004,000342,001-2312,myemail@test.com:/home/test:/bin/test", "test:!!$6$/RotIe4VZzzAun4W$7YUONvru1rDnllN5TvrnOMsWUD5wSDUPAD6t6/Xwsr/0QOuWF3HcfAhypRkGa8G1B9qqWV5kZSnCb8GKMN9N61:18260:0:99999:7:::", "teste:x:1002:test,test");
 | 
				
			||||||
    let user = "test";
 | 
					    let user = "test";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -612,4 +626,5 @@ fn test_user_db_write_implementation() {
 | 
				
			|||||||
    assert!(data.delete_user(&user).is_ok());
 | 
					    assert!(data.delete_user(&user).is_ok());
 | 
				
			||||||
    assert!(data.delete_user(&user).is_err());
 | 
					    assert!(data.delete_user(&user).is_err());
 | 
				
			||||||
    assert_eq!(data.get_all_users().len(), 0);
 | 
					    assert_eq!(data.get_all_users().len(), 0);
 | 
				
			||||||
 | 
					    */
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -17,7 +17,28 @@ pub enum UserLibError {
 | 
				
			|||||||
    NotFound,
 | 
					    NotFound,
 | 
				
			||||||
    ParseError,
 | 
					    ParseError,
 | 
				
			||||||
    FilesChanged,
 | 
					    FilesChanged,
 | 
				
			||||||
    Message(String),
 | 
					    Message(MyMessage),
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug)]
 | 
				
			||||||
 | 
					pub enum MyMessage {
 | 
				
			||||||
 | 
					    Simple(String),
 | 
				
			||||||
 | 
					    IOError(String, std::io::Error),
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl PartialEq for MyMessage {
 | 
				
			||||||
 | 
					    fn eq(&self, other: &Self) -> bool {
 | 
				
			||||||
 | 
					        format!("{}", self).eq(&format!("{}", other))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Display for MyMessage {
 | 
				
			||||||
 | 
					    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            MyMessage::Simple(m) => write!(f, "{}", m),
 | 
				
			||||||
 | 
					            MyMessage::IOError(m, e) => write!(f, "{},{}", m, e),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Display for UserLibError {
 | 
					impl Display for UserLibError {
 | 
				
			||||||
@ -35,19 +56,35 @@ impl Display for UserLibError {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Error for UserLibError {
 | 
					impl Error for UserLibError {
 | 
				
			||||||
    fn description(&self) -> &str {
 | 
					    fn source(&self) -> Option<&(dyn Error + 'static)> {
 | 
				
			||||||
        todo!()
 | 
					        match *self {
 | 
				
			||||||
 | 
					            UserLibError::NotFound | UserLibError::ParseError | UserLibError::FilesChanged => None,
 | 
				
			||||||
 | 
					            UserLibError::Message(MyMessage::IOError(_, ref e)) => Some(e),
 | 
				
			||||||
 | 
					            UserLibError::Message(MyMessage::Simple(_)) => None,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl From<&str> for UserLibError {
 | 
					impl From<&str> for UserLibError {
 | 
				
			||||||
    fn from(err: &str) -> Self {
 | 
					    fn from(err: &str) -> Self {
 | 
				
			||||||
        Self::Message(err.to_owned())
 | 
					        Self::Message(MyMessage::Simple(err.to_owned()))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl From<String> for UserLibError {
 | 
					impl From<String> for UserLibError {
 | 
				
			||||||
    fn from(err: String) -> Self {
 | 
					    fn from(err: String) -> Self {
 | 
				
			||||||
        Self::Message(err)
 | 
					        Self::Message(MyMessage::Simple(err))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl From<(String, std::io::Error)> for UserLibError {
 | 
				
			||||||
 | 
					    fn from((m, e): (String, std::io::Error)) -> Self {
 | 
				
			||||||
 | 
					        UserLibError::Message(MyMessage::IOError(m, e))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					impl From<(String, Error)> for UserLibError {
 | 
				
			||||||
 | 
					    fn from((m, e): (String, Error)) -> Self {
 | 
				
			||||||
 | 
					        UserLibError::Message(MyMessage::IOError(m, e))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}*/
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user