feat: Replace panic! by Result

This commit is contained in:
Guilhem 2022-06-17 16:56:45 +02:00
parent ae61a25c05
commit 869286ef9b

View File

@ -26,21 +26,31 @@ pub struct Teeth {
} }
impl Teeth { impl Teeth {
pub fn new(number: u8, quadrant: QuadrantKind, permanent: bool) -> Teeth { pub fn new(number: u8, quadrant: QuadrantKind, permanent: bool) -> Result<Teeth, String> {
Teeth::check_teeth_number(number, permanent); if let Err(err) = Teeth::check_teeth_number(number, permanent) {
return Err(err);
}
Teeth { Ok(Teeth {
number, number,
quadrant, quadrant,
permanent, permanent,
} })
} }
fn check_teeth_number(number: u8, permanent: bool) { fn check_teeth_number(number: u8, permanent: bool) -> Result<(), String> {
if permanent && (number < 1 || number > 8) { if permanent && (number < 1 || number > 8) {
panic!("Permanent teeth {} should be in range [1; 8]", number) Err(format!(
"Permanent teeth {} should be in range [1; 8]",
number
))
} else if !permanent && (number < 1 || number > 5) { } else if !permanent && (number < 1 || number > 5) {
panic!("Primary teeth {} should be in range [1; 5]", number) Err(format!(
"Primary teeth {} should be in range [1; 5]",
number
))
} else {
Ok(())
} }
} }
@ -52,9 +62,9 @@ impl Teeth {
} }
} }
pub fn from_iso(value: &str) -> Self { pub fn from_iso(value: &str) -> Result<Self, String> {
if value.len() != 2 { if value.len() != 2 {
panic!("{} is not a valid ISO dental notation", value); return Err(format!("{} is not a valid ISO dental notation", value));
} }
let mut char_iter = value.chars(); let mut char_iter = value.chars();
let (quadrant, permanent) = match char_iter.next().unwrap() { let (quadrant, permanent) = match char_iter.next().unwrap() {
@ -66,22 +76,24 @@ impl Teeth {
'6' => (QuadrantKind::TopRight, false), '6' => (QuadrantKind::TopRight, false),
'7' => (QuadrantKind::BottomRight, false), '7' => (QuadrantKind::BottomRight, false),
'8' => (QuadrantKind::BottomLeft, false), '8' => (QuadrantKind::BottomLeft, false),
x => panic!("Quadrant value {} not included in range [1; 8]", x), x => return Err(format!("Quadrant value {} not included in range [1; 8]", x)),
}; };
let teeth_string = char_iter.next().unwrap(); let teeth_string = char_iter.next().unwrap();
let teeth_number_option = teeth_string.to_digit(10); let teeth_number_option = teeth_string.to_digit(10);
if teeth_number_option.is_none() { if teeth_number_option.is_none() {
panic!("{} is not a number", teeth_string) return Err(format!("{} is not a number", teeth_string));
} }
let number = teeth_number_option.unwrap() as u8; let number = teeth_number_option.unwrap() as u8;
Teeth::check_teeth_number(number, permanent); if let Err(err) = Teeth::check_teeth_number(number, permanent) {
Teeth { return Err(err);
}
Ok(Teeth {
quadrant, quadrant,
permanent, permanent,
number, number,
} })
} }
pub fn to_iso(&self) -> String { pub fn to_iso(&self) -> String {
@ -98,7 +110,7 @@ impl Teeth {
quadrant_number.to_string() + &self.number.to_string() quadrant_number.to_string() + &self.number.to_string()
} }
pub fn from_uns(value: &str) -> Self { pub fn from_uns(value: &str) -> Result<Self, String> {
let number_value_option = value.parse::<u8>(); let number_value_option = value.parse::<u8>();
let mut permanent = false; let mut permanent = false;
let uns = if number_value_option.is_ok() { let uns = if number_value_option.is_ok() {
@ -109,12 +121,12 @@ impl Teeth {
}; };
if permanent && (uns < 1 || uns > 32) { if permanent && (uns < 1 || uns > 32) {
panic!( return Err(format!(
"UNS permanent teeth has to be in range [1; 32] (currently {})", "UNS permanent teeth has to be in range [1; 32] (currently {})",
uns uns
); ));
} else if !permanent && (uns < 1 || uns > 20) { } else if !permanent && (uns < 1 || uns > 20) {
panic!("UNS primary teeth has to be in range [A; T]"); return Err(format!("UNS primary teeth has to be in range [A; T]"));
} }
let max = Teeth::quadrant_max(permanent); let max = Teeth::quadrant_max(permanent);
let quadrant = match ((uns - 1) / max) + 1 { let quadrant = match ((uns - 1) / max) + 1 {
@ -122,19 +134,21 @@ impl Teeth {
2 => QuadrantKind::TopRight, 2 => QuadrantKind::TopRight,
3 => QuadrantKind::BottomRight, 3 => QuadrantKind::BottomRight,
4 => QuadrantKind::BottomLeft, 4 => QuadrantKind::BottomLeft,
_ => panic!("UNS teeth value not in range"), _ => return Err(format!("UNS teeth value not in range")),
}; };
let number = if quadrant == QuadrantKind::TopRight || quadrant == QuadrantKind::BottomLeft { let number = if quadrant == QuadrantKind::TopRight || quadrant == QuadrantKind::BottomLeft {
((uns - 1) % max) + 1 ((uns - 1) % max) + 1
} else { } else {
max - ((uns - 1) % max) max - ((uns - 1) % max)
}; };
Teeth::check_teeth_number(number, permanent); if let Err(err) = Teeth::check_teeth_number(number, permanent) {
Teeth { return Err(err);
}
Ok(Teeth {
quadrant, quadrant,
number, number,
permanent, permanent,
} })
} }
pub fn to_uns(&self) -> String { pub fn to_uns(&self) -> String {
@ -153,19 +167,24 @@ impl Teeth {
} }
} }
pub fn from_alphanumeric(value: &str) -> Self { pub fn from_alphanumeric(value: &str) -> Result<Self, String> {
if value.len() != 3 { if value.len() != 3 {
panic!("{} is not a valid alphanumeric dental notation", value); return Err(format!(
"{} is not a valid alphanumeric dental notation",
value
));
} }
let quadrant = match &value[0..2] { let quadrant = match &value[0..2] {
"UL" => QuadrantKind::TopLeft, "UL" => QuadrantKind::TopLeft,
"UR" => QuadrantKind::TopRight, "UR" => QuadrantKind::TopRight,
"LR" => QuadrantKind::BottomRight, "LR" => QuadrantKind::BottomRight,
"LL" => QuadrantKind::BottomLeft, "LL" => QuadrantKind::BottomLeft,
x => panic!( x => {
"Quadrant value {} not a valid value (accepted: ['UL', 'UR', 'LR', 'LL'])", return Err(format!(
x "Quadrant value {} not a valid value (accepted: ['UL', 'UR', 'LR', 'LL'])",
), x
))
}
}; };
let teeth_string = &value[2..3]; let teeth_string = &value[2..3];
@ -184,17 +203,21 @@ impl Teeth {
"C" => (3, false), "C" => (3, false),
"D" => (4, false), "D" => (4, false),
"E" => (5, false), "E" => (5, false),
x => panic!( x => {
"Number value {} not a valid value (accepted: [1; 8] and ['A'; 'E'])", return Err(format!(
x "Number value {} not a valid value (accepted: [1; 8] and ['A'; 'E'])",
), x
))
}
}; };
Teeth::check_teeth_number(number, permanent); if let Err(err) = Teeth::check_teeth_number(number, permanent) {
Teeth { return Err(err);
}
Ok(Teeth {
quadrant, quadrant,
permanent, permanent,
number, number,
} })
} }
pub fn to_alphanumeric(&self) -> String { pub fn to_alphanumeric(&self) -> String {
@ -236,7 +259,8 @@ mod test {
($name:ident, $func:ident, $value:expr, $quadrant:expr,$number:expr, $permanent:expr) => { ($name:ident, $func:ident, $value:expr, $quadrant:expr,$number:expr, $permanent:expr) => {
#[test] #[test]
fn $name() { fn $name() {
let teeth = Teeth::$func($value); let teeth = Teeth::$func($value).unwrap();
assert_eq!(teeth.quadrant, $quadrant); assert_eq!(teeth.quadrant, $quadrant);
assert_eq!(teeth.number, $number); assert_eq!(teeth.number, $number);
assert_eq!(teeth.permanent, $permanent); assert_eq!(teeth.permanent, $permanent);
@ -247,9 +271,8 @@ mod test {
macro_rules! from_fail { macro_rules! from_fail {
($name:ident, $func:ident, $value:expr) => { ($name:ident, $func:ident, $value:expr) => {
#[test] #[test]
#[should_panic]
fn $name() { fn $name() {
Teeth::$func($value); assert!(Teeth::$func($value).is_err());
} }
}; };
} }