1use crate::NHSNumber;
2use crate::parse_error::ParseError;
3use std::str::FromStr;
4
5impl FromStr for NHSNumber {
27 type Err = ParseError;
28 fn from_str(s: &str) -> Result<Self, Self::Err> {
29 let chars: Vec<char> = s.chars().collect();
30 match chars.len() {
31 10 => {
32 let mut digits: [i8; 10] = [0; 10];
33 for i in 0..10 {
34 digits[i] = chars[i].to_digit(10).ok_or(ParseError)? as i8
35 }
36 Ok(NHSNumber { digits: digits })
37 }
38 12 => {
39 if chars[3] != ' ' || chars[7] != ' ' {
40 return Err(ParseError);
41 }
42 let mut digits: [i8; 10] = [0; 10];
43 for i in 0..3 {
44 digits[i] = chars[i].to_digit(10).ok_or(ParseError)? as i8
45 }
46 for i in 0..3 {
47 digits[i + 3] = chars[i + 4].to_digit(10).ok_or(ParseError)? as i8
48 }
49 for i in 0..4 {
50 digits[i + 6] = chars[i + 8].to_digit(10).ok_or(ParseError)? as i8
51 }
52 Ok(NHSNumber { digits: digits })
53 }
54 _ => {
55 return Err(ParseError);
56 }
57 }
58 }
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64
65 #[test]
66 fn test_from_str_with_length_10_without_spaces() {
67 let s = String::from("0123456789");
68 let actual: NHSNumber = NHSNumber::from_str(&s).unwrap();
69 let expect: NHSNumber = NHSNumber::new([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
70 assert_eq!(actual, expect);
71 }
72
73 #[test]
74 fn test_from_str_with_length_12_with_spaces() {
75 let s = String::from("012 345 6789");
76 let actual: NHSNumber = NHSNumber::from_str(&s).unwrap();
77 let expect: NHSNumber = NHSNumber::new([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
78 assert_eq!(actual, expect);
79 }
80
81 #[test]
82 fn test_from_str_with_wrong_characters() {
83 let s = String::from("012-345-6789");
84 let result: Result<NHSNumber, ParseError> = NHSNumber::from_str(&s);
85 assert!(result.is_err());
86 }
87
88 #[test]
89 fn test_from_str_with_wrong_leading_space() {
90 let s = String::from(" 012 345 6789");
91 let result: Result<NHSNumber, ParseError> = NHSNumber::from_str(&s);
92 assert!(result.is_err());
93 }
94
95 #[test]
96 fn test_from_str_with_first_space_without_last_space() {
97 let s = String::from("012 3456789");
98 let result: Result<NHSNumber, ParseError> = NHSNumber::from_str(&s);
99 assert!(result.is_err());
100 }
101
102 #[test]
103 fn test_from_str_without_first_space_with_last_space() {
104 let s = String::from("012345 6789");
105 let result: Result<NHSNumber, ParseError> = NHSNumber::from_str(&s);
106 assert!(result.is_err());
107 }
108
109 #[test]
110 fn test_from_str_with_wrong_inner_space() {
111 let s = String::from("012 345 6789");
112 let result: Result<NHSNumber, ParseError> = NHSNumber::from_str(&s);
113 assert!(result.is_err());
114 }
115
116 #[test]
117 fn test_from_str_with_wrong_trailing_space() {
118 let s = String::from("012 345 6789 ");
119 let result: Result<NHSNumber, ParseError> = NHSNumber::from_str(&s);
120 assert!(result.is_err());
121 }
122
123 #[test]
124 fn test_from_str_with_wrong_length() {
125 let s = String::from("012");
126 let result: Result<NHSNumber, ParseError> = NHSNumber::from_str(&s);
127 assert!(result.is_err());
128 }
129}