Santa found it a good opportunity to have a look to see what Blitzen has been doing all this time when he was tech lead.
Rolling up his sleeves, he ran a git diff
command and began scrolling through the commits. His candy-cane-themed monitor reflected the code as his eyes narrowed like a debugger catching a null pointer. Then he froze, staring at the parse_row
function.
"Blitzen," he barked, "what is this disaster? return &'static str
for errors? Seriously?!"
Blitzen shrugged, sipping his oat milk latte. "MVP, Santa. Move fast, y'know?"
Santa slammed his mug of hot coffee down, marshmallows flying. "MVP? Last time you were in charge, you tried to rewrite grep and cat in Rust because you were 'bored'! And now you're telling me you can't handle proper error types? It takes five minutes! Do you want runtime panics for Christmas?!"
Bernard leaned in. "What if we use an enum
? Variants for different errors, match on them later. Clean, ergonomic."
Santa's face lit up like Rudolph's nose. "Finally, a solution that doesn't make me want to refactor the North Pole. Bernard, you get an extra cookie ration this year. Blitzen? No oat lattes for a week."
Blitzen sighed. "Enum it is."
Create an enum
called ParseError
with a few variants:
NoName
NoGoodDeeds
NoBadDeeds
InvalidGoodDeeds
InvalidBadDeeds
When errors displayed, they should be human-readable:
ParseError::NoName
should display as "Name field is missing"
ParseError::NoGoodDeeds
should display as "Good deeds field is missing"
ParseError::NoBadDeeds
should display as "Bad deeds field is missing"
ParseError::InvalidGoodDeeds
should display as "Good deeds value is invalid"
ParseError::InvalidBadDeeds
should display as "Bad deeds value is invalid"
Implement the std::error::Error
trait for ParseError
.
Update the parse_row
function to return meaningful errors using the ParseError
enum.
Make sure you return the correct error variant for each error condition.
Handle the cases where an item in a row is missing. e.g. Alice,,3
in this case, you should return an error with the NoGoodDeeds
variant.
If you're stuck or need a starting point, here are some hints to help you along the way!
The Error
trait requires you to implement the Display
and Debug
traits for the custom error type.
Implement Debug
by using the derive
macro. e.g. #[derive(Debug)]
For Display
you must implement manually. e.g.
use std::fmt;
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
ParseError::NoName => write!(f, "No name found"),
// other variants...
}
}
}
Now that both traits are implemented, you can implement the Error
trait.
use std::error::Error;
impl Error for ParseError {}
// Import the necessary modulesuse std::fmt;#[derive(Debug)]pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}impl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ParseError::NoName => write!(f, "Name field is missing"), ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), } }}// 2. Implement the Error trait for ParseErrorimpl std::error::Error for ParseError {}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors println!("{}", csv_row); let mut fields = csv_row.split(','); let name = fields.next().filter(|f| !f.is_empty()).ok_or(ParseError::NoName)?.to_string(); let good_deeds = fields .next() .filter(|f| !f.is_empty()) .ok_or(ParseError::NoGoodDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .filter(|f| !f.is_empty()) .ok_or(ParseError::NoBadDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::error::Error;use std::fmt;#[derive(Debug)]pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}impl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ParseError::NoName => write!(f, "Name field is missing"), ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), } }}// 2. Implement the Error trait for ParseErrorimpl Error for ParseError {}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields .next() .filter(|a| !a.is_empty()) .ok_or(ParseError::NoName)? .to_string(); let good_deeds = fields .next() .filter(|a| !a.is_empty()) .ok_or(ParseError::NoGoodDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .filter(|a| !a.is_empty()) .ok_or(ParseError::NoBadDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::error::Error;use std::fmt::{Debug, Display};pub enum ParseError { NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}impl Error for ParseError {}impl Debug for ParseError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::NoName => write!(f, "NoName"), Self::NoGoodDeeds => write!(f, "NoGoodDeeds"), Self::NoBadDeeds => write!(f, "NoBadDeeds"), Self::InvalidGoodDeeds => write!(f, "InvalidGoodDeeds"), Self::InvalidBadDeeds => write!(f, "InvalidBadDeeds"), } }}impl Display for ParseError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::NoName => write!(f, "Name field is missing"), Self::NoGoodDeeds => write!(f, "Good deeds field is missing"), Self::NoBadDeeds => write!(f, "Bad deeds field is missing"), Self::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), Self::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), } }}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { let fields: Vec<&str> = csv_row.split(',').collect(); let name = fields.get(0).ok_or(ParseError::NoName)?.to_string(); if name.is_empty() || name.parse::<u32>().is_ok() { return Err(ParseError::NoName); } let good_deeds = fields.get(1).ok_or(ParseError::NoGoodDeeds)?; if good_deeds.is_empty() { return Err(ParseError::NoGoodDeeds); } let good_deeds = good_deeds .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields.get(2).ok_or(ParseError::NoBadDeeds)?; if bad_deeds.is_empty() { return Err(ParseError::NoBadDeeds); } let bad_deeds = bad_deeds .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
use std::error::Error;use std::fmt;// Import the necessary modules#[derive(Debug)]pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds}// 2. Implement the Error trait for ParseErrorimpl Error for ParseError {}impl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ParseError::NoName => write!(f, "Name field is missing"), ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid") } }}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields .next() .filter(|a| !a.is_empty()) .ok_or(ParseError::NoName)? .to_string(); let good_deeds = fields .next() .filter(|a| !a.is_empty()) .ok_or(ParseError::NoGoodDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .filter(|a| !a.is_empty()) .ok_or(ParseError::NoBadDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
#[derive(Debug)]pub enum ParseError { NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}impl std::fmt::Display for ParseError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { ParseError::NoName => write!(f, "Name field is missing"), ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), } }}impl std::error::Error for ParseError {}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { let mut row = csv_row.split(','); let name = row .next() .filter(|n| !n.is_empty()) .ok_or(ParseError::NoName)? .to_string(); let good_deeds = row .next() .filter(|g| !g.is_empty()) .ok_or(ParseError::NoGoodDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = row .next() .filter(|g| !g.is_empty()) .ok_or(ParseError::NoBadDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
use std::fmt;use std::error::Error;// Import the necessary modules#[derive(Debug)]pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, InvalidGoodDeeds, NoBadDeeds, InvalidBadDeeds}// 2. Implement the Error trait for ParseErrorimpl Error for ParseError{}impl fmt::Display for ParseError{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result{ match self{ ParseError::NoName => write!(f, "Name field is missing"), ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid") } }}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields .next() .filter(|n| !n.is_empty()) .ok_or(ParseError::NoName)?.to_string(); let good_deeds = fields .next() .filter(|n| !n.is_empty()) .ok_or(ParseError::NoGoodDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .filter(|n| !n.is_empty()) .ok_or(ParseError::NoBadDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::error::Error;use std::fmt::Display;use std::fmt::Formatter;#[derive(Debug)]pub enum ParseError { NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}// 2. Implement the Error trait for ParseErrorimpl Error for ParseError {}impl Display for ParseError { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { let s = match self { ParseError::NoName => "Name field is missing", ParseError::NoGoodDeeds => "Good deeds field is missing", ParseError::NoBadDeeds => "Bad deeds field is missing", ParseError::InvalidGoodDeeds => "Good deeds value is invalid", ParseError::InvalidBadDeeds => "Bad deeds value is invalid", }; write!(f, "{}", &s) }}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields.next() .filter(|n| !n.is_empty()) .ok_or(ParseError::NoName)?.to_string(); let good_deeds = fields .next() .filter(|n| !n.is_empty()) .ok_or(ParseError::NoGoodDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .filter(|n| !n.is_empty()) .ok_or(ParseError::NoBadDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::fmt::Display;use std::error::Error;use std::fmt::Formatter;#[derive(Debug)] pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}// 2. Implement the Error trait for ParseErrorimpl Display for ParseError { fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> { match self { Self::NoName => write!(f, "Name field is missing"), Self::NoGoodDeeds => write!(f, "Good deeds field is missing"), Self::NoBadDeeds => write!(f, "Bad deeds field is missing"), Self::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), Self::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), } }}impl Error for ParseError {}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields.next().filter(|x| !x.is_empty()).ok_or(ParseError::NoName)?.to_string(); let good_deeds = fields .next().filter(|x| !x.is_empty()) .ok_or(ParseError::NoGoodDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next().filter(|x| !x.is_empty()) .ok_or(ParseError::NoBadDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::fmt::Display;use std::error::Error;use std::fmt::Formatter;#[derive(Debug)] pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds}// 2. Implement the Error trait for ParseErrorimpl Display for ParseError { fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> { match self { ParseError::NoName => write!(f, "Name field is missing"), ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), } }}impl Error for ParseError {}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields.next().filter(|x| !x.is_empty()).ok_or(ParseError::NoName)?.to_string(); let good_deeds = fields .next().filter(|x| !x.is_empty()) .ok_or(ParseError::NoGoodDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next().filter(|x| !x.is_empty()) .ok_or(ParseError::NoBadDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::{error::Error, fmt::Display};#[derive(Debug)]pub enum ParseError { NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}// Implement the Display trait for ParseErrorimpl Display for ParseError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::NoName => write!(f, "Name field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), } }}// Implement the Error trait for ParseErrorimpl Error for ParseError {}// Define the Kid structpub struct Kid { pub name: String, pub niceness: Niceness,}// Implement methods for Kidimpl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // Split the row into fields let mut fields = csv_row.split(','); let name = fields .next() .filter(|name| !name.trim().is_empty()) .ok_or(ParseError::NoName)?; let good_deeds = fields .next() .filter(|field| !field.trim().is_empty()) .ok_or(ParseError::NoGoodDeeds)? .trim() .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .filter(|field| !field.trim().is_empty()) .ok_or(ParseError::NoBadDeeds)? .trim() .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name.to_string(), good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_score = good_deeds as f32 * GOOD_WEIGHT; let bad_score = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_score / (good_score + bad_score); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::{error::Error, fmt::Display};#[derive(Debug)]pub enum ParseError { NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}// Implement the Display trait for ParseErrorimpl Display for ParseError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::NoName => write!(f, "Name field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), } }}// Implement the Error trait for ParseErrorimpl Error for ParseError {}// Define the Kid structpub struct Kid { pub name: String, pub niceness: Niceness,}// Implement methods for Kidimpl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // Split the row into fields let mut fields = csv_row.split(','); let name = fields .next() .filter(|name| !name.trim().is_empty()) .ok_or(ParseError::NoName)?; let good_deeds = fields .next() .filter(|field| !field.trim().is_empty()) .ok_or(ParseError::NoGoodDeeds)? .trim() .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .filter(|field| !field.trim().is_empty()) .ok_or(ParseError::NoBadDeeds)? .trim() .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name.trim().to_string(), good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_score = good_deeds as f32 * GOOD_WEIGHT; let bad_score = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_score / (good_score + bad_score); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::{error::Error, fmt::Display};#[derive(Debug)]pub enum ParseError { NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}// Implement the Display trait for ParseErrorimpl Display for ParseError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::NoName => write!(f, "Name field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), } }}// Implement the Error trait for ParseErrorimpl Error for ParseError {}// Define the Kid structpub struct Kid { pub name: String, pub niceness: Niceness,}// Implement methods for Kidimpl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // Split the row into fields let mut fields = csv_row.split(','); // Parse the name field let name = fields.next().ok_or(ParseError::NoName)?.trim(); if name.is_empty() { return Err(ParseError::NoName); } // Parse the good deeds field let good_deeds_field = fields.next().ok_or(ParseError::NoGoodDeeds)?; if good_deeds_field.trim().is_empty() { return Err(ParseError::NoGoodDeeds); } let good_deeds = good_deeds_field .trim() .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; // Parse the bad deeds field let bad_deeds_field = fields.next().ok_or(ParseError::NoBadDeeds)?; if bad_deeds_field.trim().is_empty() { return Err(ParseError::NoBadDeeds); } let bad_deeds = bad_deeds_field .trim() .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; // Return the new Kid instance Ok(Kid::new(name.to_string(), good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_score = good_deeds as f32 * GOOD_WEIGHT; let bad_score = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_score / (good_score + bad_score); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::error::Error;use std::fmt;#[derive(Debug)]pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}impl Error for ParseError {}impl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let error_msg = match self { Self::NoName => "Name field is missing", Self::NoGoodDeeds => "Good deeds field is missing", Self::NoBadDeeds => "Bad deeds field is missing", Self::InvalidGoodDeeds => "Good deeds value is invalid", Self::InvalidBadDeeds => "Bad deeds value is invalid", }; write!(f, "{}", error_msg) }}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields .next() .filter(|s| !s.trim().is_empty()) .ok_or_else(|| ParseError::NoName)? .to_string(); let good_deeds = fields .next() .filter(|s| !s.trim().is_empty()) .ok_or_else(|| ParseError::NoGoodDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .filter(|s| !s.trim().is_empty()) .ok_or_else(|| ParseError::NoBadDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::error::Error;use std::fmt;#[derive(Debug)]pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}impl Error for ParseError {}impl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let error_msg = match self { Self::NoName => "Name field is missing", Self::NoGoodDeeds => "Good deeds field is missing", Self::NoBadDeeds => "Bad deeds field is missing", Self::InvalidGoodDeeds => "Good deeds value is invalid", Self::InvalidBadDeeds => "Bad deeds value is invalid", }; write!(f, "{}", error_msg) }}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields .next() .filter(|s| !s.trim().is_empty()) .ok_or_else(|| ParseError::NoName)? .to_string(); let good_deeds = fields .next() .filter(|s| !s.trim().is_empty()) .ok_or_else(|| ParseError::NoGoodDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .filter(|s| !s.trim().is_empty()) .ok_or_else(|| ParseError::NoBadDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::error::Error;use std::fmt;#[derive(Debug)]pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds}impl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { ParseError::NoName => write!(f, "Name field is missing"), ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid") } }}// 2. Implement the Error trait for ParseErrorimpl Error for ParseError {}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields .next() .filter(|n| !n.trim().is_empty()) .ok_or(ParseError::NoName)? .to_string(); let good_deeds = fields .next() .filter(|gd| !gd.trim().is_empty()) .ok_or(ParseError::NoGoodDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .filter(|bd| !bd.trim().is_empty()) .ok_or(ParseError::NoBadDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::fmt::{Display, Formatter};use std::error::Error;#[derive(Debug)]pub enum ParseError { NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}impl Display for ParseError { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { let message = match self { ParseError::NoName => "Name field is missing", ParseError::NoGoodDeeds => "Good deeds field is missing", ParseError::NoBadDeeds => "Bad deeds field is missing", ParseError::InvalidGoodDeeds => "Good deeds value is invalid", ParseError::InvalidBadDeeds => "Bad deeds value is invalid", }; write!(f, "{}", message) }}impl Error for ParseError { fn source(&self) -> Option<&(dyn Error + 'static)> { None }}// 2. Implement the Error trait for ParseErrorpub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields.next().filter(|s| ! s.trim().is_empty()).ok_or(ParseError::NoName)?.to_string(); let good_deeds = fields .next() .filter(|s| ! s.trim().is_empty()) .ok_or(ParseError::NoGoodDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .filter(|s| ! s.trim().is_empty()) .ok_or(ParseError::NoBadDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::{ error::Error, fmt::{ Display, Formatter, Result as FResult } };#[derive(Debug)]pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}impl Display for ParseError { fn fmt (&self, f: &mut Formatter<'_>) -> FResult { write!(f, "{}", match self { ParseError::NoName => "Name field is missing", ParseError::NoGoodDeeds => "Good deeds field is missing", ParseError::NoBadDeeds => "Bad deeds field is missing", ParseError::InvalidGoodDeeds => "Good deeds value is invalid", ParseError::InvalidBadDeeds => "Bad deeds value is invalid", }) }}impl Error for ParseError {}// 2. Implement the Error trait for ParseErrorpub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row (csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields.next().and_then(|n| if n.is_empty() { None } else { Some(n) }).ok_or(ParseError::NoName)?.to_string(); let good_deeds = fields .next() .and_then(|s| if s.len() > 0 { Some(s) } else { None }) .ok_or(ParseError::NoGoodDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .and_then(|s| if s.len() > 0 { Some(s) } else { None }) .ok_or(ParseError::NoBadDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
use std::error::Error;use std::fmt;#[derive(Debug)]pub enum ParseError { NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}// 2. Implement the Error trait for ParseErrorimpl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::NoName => write!(f, "Name field is missing"), Self::NoGoodDeeds => write!(f, "Good deeds field is missing"), Self::NoBadDeeds => write!(f, "Bad deeds field is missing"), Self::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), Self::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), } }}impl Error for ParseError {}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields.next() .filter(|x| !x.is_empty()) .ok_or(ParseError::NoName)?.to_string(); let good_deeds = fields .next() .filter(|x| !x.is_empty()) .ok_or(ParseError::NoGoodDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .filter(|x| !x.is_empty()) .ok_or(ParseError::NoBadDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
use std::{error::Error, fmt::Display};#[derive(Debug)]pub enum ParseError { NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}// 2. Implement the Error trait for ParseErrorimpl Display for ParseError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { ParseError::NoName => write!(f, "Name field is missing"), ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), } }}// Make it an error!impl Error for ParseError {}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields .next() .map(|name| name.trim()) .filter(|name| !name.is_empty()) .ok_or(ParseError::NoName)? .to_string(); let good_deeds = fields .next() .map(|field| field.trim()) .filter(|field| !field.is_empty()) .ok_or(ParseError::NoGoodDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .map(|field| field.trim()) .filter(|field| !field.is_empty()) .ok_or(ParseError::NoBadDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
use std::fmt;#[derive(Debug)]pub enum ParseError { NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}impl std::error::Error for ParseError {}impl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let message = match self { ParseError::NoName => "Name field is missing", ParseError::NoGoodDeeds => "Good deeds field is missing", ParseError::NoBadDeeds => "Bad deeds field is missing", ParseError::InvalidGoodDeeds => "Good deeds value is invalid", ParseError::InvalidBadDeeds => "Bad deeds value is invalid", }; write!(f, "{}", message) }}// 2. Implement the Error trait for ParseErrorpub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { let mut fields = csv_row.split(','); let name = fields.next() .map(|name| name.trim()) .filter(|name| !name.is_empty()) .ok_or(ParseError::NoName)? .to_string(); let good_deeds = fields .next() .map(|field| field.trim()) .filter(|field| !field.is_empty()) .ok_or(ParseError::NoGoodDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .map(|field| field.trim()) .filter(|field| !field.is_empty()) .ok_or(ParseError::NoBadDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::error::Error;use std::fmt;#[derive(Debug)]pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}// 2. Implement the Error trait for ParseErrorimpl Error for ParseError {}impl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::NoName => write!(f, "Name field is missing"), Self::NoGoodDeeds => write!(f, "Good deeds field is missing"), Self::NoBadDeeds => write!(f, "Bad deeds field is missing"), Self::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), Self::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), } }}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields.next().ok_or(ParseError::NoName)?.to_string(); if name.is_empty() { return Err(ParseError::NoName); } let good_deeds = fields .next() .ok_or(ParseError::NoGoodDeeds)?; if good_deeds.is_empty() { return Err(ParseError::NoGoodDeeds); } let good_deeds = good_deeds .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .ok_or(ParseError::NoBadDeeds)?; if bad_deeds.is_empty() { return Err(ParseError::NoBadDeeds); } let bad_deeds = bad_deeds .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::fmt;use std::error::Error;#[derive(Debug)]pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}// 2. Implement the Error trait for ParseErrorimpl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ParseError::NoName => write!(f, "Name field is missing"), ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), } }}impl Error for ParseError {}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields.next().ok_or(ParseError::NoName)?.to_string(); if name.trim().is_empty() { return Err(ParseError::NoName); } let good_deeds_field = fields .next() .ok_or(ParseError::NoGoodDeeds)?; if good_deeds_field.is_empty() { return Err(ParseError::NoGoodDeeds) }; let good_deeds = good_deeds_field .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds_field = fields .next() .ok_or(ParseError::NoBadDeeds)?; if bad_deeds_field.is_empty() { return Err(ParseError::NoBadDeeds) }; let bad_deeds = bad_deeds_field .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::error::Error;use std::fmt;#[derive(Debug)]pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}// 2. Implement the Error trait for ParseErrorimpl Error for ParseError {}impl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::NoName => write!(f, "Name field is missing"), Self::NoGoodDeeds => write!(f, "Good deeds field is missing"), Self::NoBadDeeds => write!(f, "Bad deeds field is missing"), Self::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), Self::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), } }}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields.next().ok_or(ParseError::NoName)?.to_string(); if name.is_empty() { return Err(ParseError::NoName); } let good_deeds = fields .next() .ok_or(ParseError::NoGoodDeeds)?; if good_deeds.is_empty() { return Err(ParseError::NoGoodDeeds); } let good_deeds = good_deeds .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .ok_or(ParseError::NoBadDeeds)?; if bad_deeds.is_empty() { return Err(ParseError::NoBadDeeds); } let bad_deeds = bad_deeds .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::{fmt,error::Error};#[derive(Debug)]pub enum ParseError { NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds, // 1. Add variants here (read description)}// 2. Implement the Error trait for ParseErrorimpl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ParseError::NoName => write!(f, "Name field is missing"), ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid") } } }impl Error for ParseError {}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields.next().ok_or(ParseError::NoName)?.to_string(); if name.is_empty(){ return Err(ParseError::NoName) } let good_deeds = fields .next() .ok_or(ParseError::NoGoodDeeds)?; if good_deeds.is_empty() { return Err(ParseError::NoGoodDeeds); } let good_deeds = good_deeds .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .ok_or(ParseError::NoBadDeeds)?; if bad_deeds.is_empty() { return Err(ParseError::NoBadDeeds); } let bad_deeds = bad_deeds .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::error::Error;use std::fmt::{Display, Formatter};#[derive(Debug)]pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds}impl Display for ParseError { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { let _ = match self { ParseError::NoName => write!(f, "Name field is missing"), ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), }; Ok(()) }}impl Error for ParseError {}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { let mut fields = csv_row.split(','); let name = fields.next(); if name.is_none() { return Err(ParseError::NoName); } let name_str = name.unwrap().to_string(); if name_str.len() == 0 { return Err(ParseError::NoName); } let good_deeds = fields.next(); if good_deeds.is_none() || good_deeds.unwrap().len() == 0 { return Err(ParseError::NoGoodDeeds); } let bad_deeds = fields.next(); if bad_deeds.is_none() || bad_deeds.unwrap().len() == 0{ return Err(ParseError::NoBadDeeds); } let good_deeds_int = good_deeds.unwrap().parse::<u32>(); if good_deeds_int.is_err() { return Err(ParseError::InvalidGoodDeeds); } let bad_deeds_int = bad_deeds.unwrap().parse::<u32>(); if bad_deeds_int.is_err() { return Err(ParseError::InvalidBadDeeds); } Ok(Kid::new(name_str, good_deeds_int.unwrap(), bad_deeds_int.unwrap())) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modules #[derive(Debug)]pub enum ParseError { NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}impl std::fmt::Display for ParseError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {match self { ParseError::NoName => write!(f, "Name field is missing"), ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), } }}impl std::error::Error for ParseError {}// 2. Implement the Error trait for ParseErrorpub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields.next().ok_or(ParseError::NoName)?.to_string(); if name.is_empty() { return Err(ParseError::NoName); } let good_deeds = fields .next() .ok_or(ParseError::NoGoodDeeds)?; if good_deeds.is_empty() { return Err(ParseError::NoGoodDeeds); } let good_deeds = good_deeds .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .ok_or(ParseError::NoBadDeeds)?; if bad_deeds.is_empty() { return Err(ParseError::NoBadDeeds); } let bad_deeds = bad_deeds .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::error::Error;use std::fmt;#[derive(Debug)]pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds}impl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ParseError::NoName => write!(f, "Name field is missing"), ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), } }}// 2. Implement the Error trait for ParseErrorimpl Error for ParseError {}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields.next().ok_or(ParseError::NoName)?.to_string(); if name.is_empty() { return Err(ParseError::NoName); } let good_deeds = fields .next() .ok_or(ParseError::NoGoodDeeds)?; if good_deeds.is_empty() { return Err(ParseError::NoGoodDeeds); } let good_deeds = good_deeds .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .ok_or(ParseError::NoBadDeeds)?; if bad_deeds.is_empty() { return Err(ParseError::NoBadDeeds); } let bad_deeds = bad_deeds .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
use std::error::Error;use std::fmt;use std::fmt::{Debug, Display, Formatter};use crate::ParseError::{InvalidBadDeeds, InvalidGoodDeeds, NoBadDeeds, NoGoodDeeds, NoName};// Import the necessary modulespub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}// 2. Implement the Error trait for ParseErrorimpl Debug for ParseError { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "{}", match self { ParseError::NoName => {"Name field is missing"} ParseError::NoGoodDeeds => {"Good deeds field is missing"} ParseError::NoBadDeeds => {"Bad deeds field is missing"} ParseError::InvalidGoodDeeds => {"Good deeds value is invalid"} ParseError::InvalidBadDeeds => {"Bad deeds value is invalid"} }) }}impl Display for ParseError { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fmt::Debug::fmt(self, f) }}impl Error for ParseError {}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields.next().ok_or(NoName)?.to_string(); if name == "" { return Err(NoName); } let good_deeds = fields.next().ok_or(NoGoodDeeds)?; if good_deeds == "" { return Err(NoGoodDeeds); } let good_deeds = good_deeds.parse::<u32>().map_err(|_| InvalidGoodDeeds)?; let bad_deeds = fields.next().ok_or(NoBadDeeds)?; if bad_deeds == "" { return Err(NoBadDeeds); } let bad_deeds = bad_deeds.parse::<u32>().map_err(|_| InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modules#[derive(Debug)]pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}impl std::fmt::Display for ParseError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let message = match self { ParseError::NoName => "Name field is missing", ParseError::NoGoodDeeds => "Good deeds field is missing", ParseError::NoBadDeeds => "Bad deeds field is missing", ParseError::InvalidGoodDeeds => "Good deeds value is invalid", ParseError::InvalidBadDeeds => "Bad deeds value is invalid", }; write!(f, "{}", message) }}// 2. Implement the Error trait for ParseErrorimpl std::error::Error for ParseError {}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields.next().ok_or(ParseError::NoName)?.to_string(); if name.is_empty() { return Err(ParseError::NoName) } let good_deeds = fields .next() .ok_or(ParseError::NoGoodDeeds)?; if good_deeds.is_empty() { return Err(ParseError::NoGoodDeeds) } let good_deeds = good_deeds .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .ok_or(ParseError::NoBadDeeds)?; if bad_deeds.is_empty() { return Err(ParseError::NoBadDeeds) } let bad_deeds = bad_deeds .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
use std::fmt;use std::error::Error;// Import the necessary modulespub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}impl fmt::Debug for ParseError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { write!(f, "{}", match self { ParseError::NoName => "Name field is missing", ParseError::NoGoodDeeds => "Good deeds field is missing", ParseError::NoBadDeeds => "Bad deeds field is missing", ParseError::InvalidGoodDeeds => "Good deeds value is invalid", ParseError::InvalidBadDeeds => "Bad deeds value is invalid", }) }}impl Error for ParseError {}impl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { fmt::Debug::fmt(self, f) }}// 2. Implement the Error trait for ParseErrorpub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields.next().ok_or(ParseError::NoName)?.to_string(); if name == "" { return Err(ParseError::NoName); } let good_deeds = fields .next() .ok_or(ParseError::NoGoodDeeds)?; if good_deeds == "" { return Err(ParseError::NoGoodDeeds) } let good_deeds = good_deeds.parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .ok_or(ParseError::NoBadDeeds)?; if bad_deeds == "" { return Err(ParseError::NoBadDeeds) } let bad_deeds = bad_deeds.parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
use std::error::Error;use std::fmt;use std::fmt::{Debug, Display, Formatter};use crate::ParseError::{InvalidBadDeeds, InvalidGoodDeeds, NoBadDeeds, NoGoodDeeds, NoName};// Import the necessary modulespub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}// 2. Implement the Error trait for ParseErrorimpl Debug for ParseError { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "{}", match self { ParseError::NoName => {"Name field is missing"} ParseError::NoGoodDeeds => {"Good deeds field is missing"} ParseError::NoBadDeeds => {"Bad deeds field is missing"} ParseError::InvalidGoodDeeds => {"Good deeds value is invalid"} ParseError::InvalidBadDeeds => {"Bad deeds value is invalid"} }) }}impl Display for ParseError { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fmt::Debug::fmt(self, f) }}impl Error for ParseError {}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields.next().ok_or(NoName)?.to_string(); if name == "" { return Err(NoName); } let good_deeds = fields.next().ok_or(NoGoodDeeds)?; if good_deeds == "" { return Err(NoGoodDeeds); } let good_deeds = good_deeds.parse::<u32>().map_err(|_| InvalidGoodDeeds)?; let bad_deeds = fields.next().ok_or(NoBadDeeds)?; if bad_deeds == "" { return Err(NoBadDeeds); } let bad_deeds = bad_deeds.parse::<u32>().map_err(|_| InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modules#[derive(Debug)]pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}// 2. Implement the Error trait for ParseErrorimpl std::error::Error for ParseError {}impl std::fmt::Display for ParseError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", match self { ParseError::NoName => "Name field is missing", ParseError::NoGoodDeeds => "Good deeds field is missing", ParseError::NoBadDeeds => "Bad deeds field is missing", ParseError::InvalidGoodDeeds => "Good deeds value is invalid", ParseError::InvalidBadDeeds => "Bad deeds value is invalid", } ) }}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields.next().ok_or(ParseError::NoName)?.to_string(); if name == "" { return Err(ParseError::NoName); } let good_deeds = fields .next() .ok_or(ParseError::NoGoodDeeds)?; if good_deeds == "" { return Err(ParseError::NoGoodDeeds); } let good_deeds = good_deeds .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .ok_or(ParseError::NoBadDeeds)?; if bad_deeds == "" { return Err(ParseError::NoBadDeeds); } let bad_deeds = bad_deeds .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
use std::error::Error;use std::fmt;#[derive(Debug)]pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}impl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ParseError::NoName => write!(f, "Name field is missing"), // other variants... ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), } }}// 2. Implement the Error trait for ParseErrorimpl Error for ParseError {}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields .next() .filter(|f| !f.trim().is_empty()) .ok_or(ParseError::NoName)? .to_string(); let good_deeds = fields .next() .filter(|f| !f.trim().is_empty()) .ok_or(ParseError::NoGoodDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .filter(|f| !f.trim().is_empty()) .ok_or(ParseError::NoBadDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
use std::error::Error;use std::fmt;#[derive(Debug)]pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}impl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ParseError::NoName => write!(f, "Name field is missing"), // other variants... ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), } }}// 2. Implement the Error trait for ParseErrorimpl Error for ParseError {}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields .next() .filter(|f| !f.trim().is_empty()) .ok_or(ParseError::NoName)? .to_string(); let good_deeds = fields .next() .filter(|f| !f.trim().is_empty()) .ok_or(ParseError::NoGoodDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .filter(|f| !f.trim().is_empty()) .ok_or(ParseError::NoBadDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modules#[derive(Debug)]pub enum ParseError { NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}impl std::fmt::Display for ParseError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { ParseError::NoName => write!(f, "Name field is missing"), ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), } }}// 2. Implement the Error trait for ParseErrorimpl std::error::Error for ParseError {}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields .next() .filter(|f| !f.trim().is_empty()) .ok_or(ParseError::NoName)? .to_string(); let good_deeds = fields .next() .filter(|f| !f.trim().is_empty()) .ok_or(ParseError::NoGoodDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .filter(|f| !f.trim().is_empty()) .ok_or(ParseError::NoBadDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modules#[derive(Debug)]pub enum ParseError { NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}impl std::fmt::Display for ParseError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { ParseError::NoName => write!(f, "Name field is missing"), ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), } }}// 2. Implement the Error trait for ParseErrorimpl std::error::Error for ParseError {}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors dbg!(csv_row); let mut fields = csv_row.split(','); let name = fields .next() .filter(|f| !f.trim().is_empty()) .ok_or(ParseError::NoName)? .to_string(); let good_deeds = fields .next() .filter(|f| !f.trim().is_empty()) .ok_or(ParseError::NoGoodDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .filter(|f| !f.trim().is_empty()) .ok_or(ParseError::NoBadDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::fmt;use std::error::Error;#[derive(Debug)]pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}// 2. Implement the Error trait for ParseErrorimpl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ParseError::NoName => write!(f, "Name field is missing"), ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), } }}impl Error for ParseError {}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields.next().filter(|x| !x.trim().is_empty()).ok_or(ParseError::NoName)?.to_string(); let good_deeds = fields .next() .filter(|x| !x.trim().is_empty()) .ok_or(ParseError::NoGoodDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .filter(|x| !x.trim().is_empty()) .ok_or(ParseError::NoBadDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::fmt;use std::error::Error;#[derive(Debug)]pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}// 2. Implement the Error trait for ParseErrorimpl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ParseError::NoName => write!(f, "Name field is missing"), ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), } }}impl Error for ParseError {}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields.next().filter(|x| !x.trim().is_empty()).ok_or(ParseError::NoName)?.to_string(); let good_deeds = fields .next() .filter(|x| !x.trim().is_empty()) .ok_or(ParseError::NoGoodDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .filter(|x| !x.trim().is_empty()) .ok_or(ParseError::NoBadDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
use std::fmt;// Import the necessary modules#[derive(Debug)]pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds}// 2. Implement the Error trait for ParseErrorimpl std::error::Error for ParseError {}impl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { ParseError::NoName => write!(f, "Name field is missing"), ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid") } }}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields.next().ok_or(ParseError::NoName)?.trim().to_string(); if name.is_empty() { return Err(ParseError::NoName); } let good_deeds = fields .next() .ok_or(ParseError::NoGoodDeeds)? .trim(); if good_deeds.is_empty() { return Err(ParseError::NoGoodDeeds); } let good_deeds = good_deeds .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .ok_or(ParseError::NoBadDeeds)? .trim(); if bad_deeds.is_empty() { return Err(ParseError::NoBadDeeds); } let bad_deeds = bad_deeds .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::fmt;use std::error::Error;#[derive(Debug)]pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}impl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { ParseError::NoName => write!(f, "Name field is missing"), ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), } }}// 2. Implement the Error trait for ParseErrorimpl Error for ParseError {}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields .next() .filter(|s| {!s.trim().is_empty()}) .ok_or(ParseError::NoName)?.to_string(); let good_deeds = fields .next() .filter(|s| {!s.trim().is_empty()}) .ok_or(ParseError::NoGoodDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .filter(|s| {!s.trim().is_empty()}) .ok_or(ParseError::NoBadDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::error::Error;use std::fmt;#[derive(Debug)]pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}// 2. Implement the Error trait for ParseErrorimpl Error for ParseError {}impl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ParseError::NoName => write!(f, "Name field is missing"), ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), } }}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields .next() .filter(|s| {!s.trim().is_empty()}) .ok_or(ParseError::NoName)?.to_string(); let good_deeds = fields .next() .filter(|s| {!s.trim().is_empty()}) .ok_or(ParseError::NoGoodDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .filter(|s| {!s.trim().is_empty()}) .ok_or(ParseError::NoBadDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::error::Error;use std::fmt;#[derive(Debug)]pub enum ParseError { NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}impl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let error_message = match self { ParseError::NoName => "Name field is missing", ParseError::NoGoodDeeds => "Good deeds field is missing", ParseError::NoBadDeeds => "Bad deeds field is missing", ParseError::InvalidGoodDeeds => "Good deeds value is invalid", ParseError::InvalidBadDeeds => "Bad deeds value is invalid", }; write!(f, "{}", error_message) }}impl Error for ParseError {}// 2. Implement the Error trait for ParseErrorpub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields.next().ok_or(ParseError::NoName)?.to_string(); if name.trim().len() == 0 { return Err(ParseError::NoName); } let mut good_deeds = fields .next() .ok_or(ParseError::NoGoodDeeds)?; if good_deeds.len() == 0 { return Err(ParseError::NoGoodDeeds); } let good_deeds = good_deeds.parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .ok_or(ParseError::NoBadDeeds)?; if bad_deeds.len() == 0 { return Err(ParseError::NoBadDeeds); } let bad_deeds = bad_deeds.parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::error::Error;use std::fmt;#[derive(Debug)]pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}// 2. Implement the Error trait for ParseErrorimpl Error for ParseError {}impl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ParseError::NoName => write!(f, "Name field is missing"), ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), } }}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields .next() .filter(|s| {!s.trim().is_empty()}) .ok_or(ParseError::NoName)?.to_string(); let good_deeds = fields .next() .filter(|s| {!s.trim().is_empty()}) .ok_or(ParseError::NoGoodDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .filter(|s| {!s.trim().is_empty()}) .ok_or(ParseError::NoBadDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::error::Error;use std::fmt::{Display, Formatter};#[derive(Debug)]pub enum ParseError { NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}impl Display for ParseError { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { Self::NoName => write!(f, "Name field is missing"), Self::NoGoodDeeds => write!(f, "Good deeds field is missing"), Self::NoBadDeeds => write!(f, "Bad deeds field is missing"), Self::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), Self::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), } }}// 2. Implement the Error trait for ParseErrorimpl Error for ParseError {}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields .next() .filter(|s| !s.trim().is_empty()) .ok_or(ParseError::NoName)? .to_string(); let good_deeds = fields .next() .filter(|s| !s.trim().is_empty()) .ok_or(ParseError::NoGoodDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .filter(|s| !s.trim().is_empty()) .ok_or(ParseError::NoBadDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::fmt;use std::error::Error;use::std::fmt::{Display, Formatter};#[derive(Debug)]pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}// 2. Implement the Error trait for ParseErrorimpl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ParseError::NoName => write!(f, "Name field is missing"), ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), } }}impl Error for ParseError {}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields.next() .filter(|s| !s.trim().is_empty()) .ok_or(ParseError::NoName)?.to_string(); let good_deeds = fields .next() .filter(|s| !s.trim().is_empty()) .ok_or(ParseError::NoGoodDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .filter(|s| !s.trim().is_empty()) .ok_or(ParseError::NoBadDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse::std::{error::Error, fmt::{Display, Formatter}};#[derive(Debug)]pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}// 2. Implement the Error trait for ParseErrorimpl Display for ParseError { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { use ParseError::*; match self { NoName => write!(f, "Name field is missing"), NoGoodDeeds => write!(f, "Good deeds field is missing"), NoBadDeeds => write!(f, "Bad deeds field is missing"), InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), } }}impl Error for ParseError {}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields .next() .filter(|s| !s.trim().is_empty()) .ok_or(ParseError::NoName)?.to_string(); let good_deeds = fields .next() .filter(|s| !s.trim().is_empty()) .ok_or(ParseError::NoGoodDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .filter(|s| !s.trim().is_empty()) .ok_or(ParseError::NoBadDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::fmt;use std::error::Error;#[derive(Debug)]pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}// 2. Implement the Error trait for ParseErrorimpl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ParseError::NoName => write!(f, "Name field is missing"), ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), } }}impl Error for ParseError {}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields.next().ok_or(ParseError::NoName)?.to_string(); if name.is_empty() { return Err(ParseError::NoName); } let good_deeds = fields.next(); if let Some("") = good_deeds { return Err(ParseError::NoGoodDeeds) } let good_deeds = good_deeds .ok_or(ParseError::NoGoodDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields.next(); if let Some("") = bad_deeds { return Err(ParseError::NoBadDeeds) } let bad_deeds = bad_deeds .ok_or(ParseError::NoBadDeeds)? .parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::fmt;use std::error;#[derive(Debug)]pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}impl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { ParseError::NoName => write!(f, "Name field is missing"), ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), } }}// 2. Implement the Error trait for ParseErrorimpl error::Error for ParseError {}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields .next() .filter(|s| !s.trim().is_empty()) .ok_or(ParseError::NoName)? .to_string(); let good_deeds = fields .next() .filter(|s| !s.trim().is_empty()) .ok_or(ParseError::NoGoodDeeds)? .parse::<u32>().map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .filter(|s| !s.trim().is_empty()) .ok_or(ParseError::NoBadDeeds)? .parse::<u32>().map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::error::Error;use std::fmt;#[derive(Debug)]pub enum ParseError { // 1. Add variants here (read description) NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds,}// 2. Implement the Error trait for ParseErrorimpl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ParseError::NoName => write!(f, "Name field is missing"), ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid"), } }}impl Error for ParseError {}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = match fields.next().ok_or(ParseError::NoName) { Ok(r) => { if r.trim().len() == 0 { return Err(ParseError::NoName); } r.to_string() } Err(e) => return Err(e), }; let good_deeds = match fields .next() .ok_or(ParseError::NoGoodDeeds) { Ok(r) => { if r.trim().len() == 0 { return Err(ParseError::NoGoodDeeds); } r.parse::<u32>() .map_err(|_| ParseError::InvalidGoodDeeds)? } Err(e) => return Err(e), }; let bad_deeds = match fields .next() .ok_or(ParseError::NoBadDeeds) { Ok(r) => { if r.trim().len() == 0 { return Err(ParseError::NoBadDeeds); } r.parse::<u32>() .map_err(|_| ParseError::InvalidBadDeeds)? } Err(e) => return Err(e), }; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}
// Import the necessary modulesuse std::fmt;use std::error::Error;// creates ParseError enum for error handling#[derive(Debug)]pub enum ParseError { NoName, NoGoodDeeds, NoBadDeeds, InvalidGoodDeeds, InvalidBadDeeds}// implements Display trait for ParseErrorimpl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ParseError::NoName => write!(f, "Name field is missing"), ParseError::NoGoodDeeds => write!(f, "Good deeds field is missing"), ParseError::NoBadDeeds => write!(f, "Bad deeds field is missing"), ParseError::InvalidGoodDeeds => write!(f, "Good deeds value is invalid"), ParseError::InvalidBadDeeds => write!(f, "Bad deeds value is invalid") } }}// 2. Implement the Error trait for ParseErrorimpl Error for ParseError {}pub struct Kid { pub name: String, pub niceness: Niceness,}impl Kid { pub fn new(name: String, good_deeds: u32, bad_deeds: u32) -> Kid { let niceness = if Self::is_nice(good_deeds, bad_deeds) { Niceness::Nice(good_deeds) } else { Niceness::Naughty }; Kid { name, niceness } } // .filter(|a| !a.trim().is_empty()) pub fn parse_row(csv_row: &str) -> Result<Kid, ParseError> { // 3. Update the code to return meaningful errors let mut fields = csv_row.split(','); let name = fields .next() .filter(|a| !a.trim().is_empty()) .ok_or(ParseError::NoName)? .to_string(); let good_deeds = fields .next() .filter(|a| !a.trim().is_empty()) .ok_or(ParseError::NoGoodDeeds)? .parse::<u32>().map_err(|_| ParseError::InvalidGoodDeeds)?; let bad_deeds = fields .next() .filter(|a| !a.trim().is_empty()) .ok_or(ParseError::NoBadDeeds)? .parse::<u32>().map_err(|_| ParseError::InvalidBadDeeds)?; Ok(Kid::new(name, good_deeds, bad_deeds)) } pub fn is_nice(good_deeds: u32, bad_deeds: u32) -> bool { if good_deeds == 0 && bad_deeds == 0 { return false; } let good_deeds = good_deeds as f32 * GOOD_WEIGHT; let bad_deeds = bad_deeds as f32 * BAD_WEIGHT; let ratio = good_deeds / (good_deeds + bad_deeds); ratio >= 0.75 }}pub const GOOD_WEIGHT: f32 = 1.0;pub const BAD_WEIGHT: f32 = 2.0;#[derive(Debug, PartialEq)]pub enum Niceness { Nice(u32), Naughty,}