diff --git a/src/commas/add_commas.rs b/src/commas/add_commas.rs index 99ea6a8..8000e5c 100644 --- a/src/commas/add_commas.rs +++ b/src/commas/add_commas.rs @@ -19,25 +19,27 @@ /// } /// ``` pub fn add_commas(number_str: impl AsRef) -> String { - let number_str = number_str.as_ref().replace(',', ""); // Remove existing commas - - let dot_index = number_str.find('.').unwrap_or(number_str.len()); + let number_str = number_str.as_ref(); + let comma_less = |c: &char| c != &','; - let result = number_str[..dot_index] - .chars() - .rev() - .enumerate() - .fold(String::new(), |mut acc, (i, digit)| { - if i > 0 && i % 3 == 0 { - acc.push(','); - } - acc.push(digit); - acc - }) + let mut end = number_str .chars() - .rev() - .collect::() - + &number_str[dot_index..]; + .filter(comma_less) + .position(|c| c == '.') + .unwrap_or_else(|| number_str.chars().filter(comma_less).count()); + + let mut result = String::new(); + for (i, ch) in number_str.chars().filter(comma_less).enumerate() { + if end == i { + end += number_str.chars().filter(|c| c == &',').count(); + result.push_str(&number_str[end..number_str.chars().count()]); + break; + } + if (end - i) % 3 == 0 && i != 0 { + result.push(',') + } + result.push(ch); + } result } @@ -52,21 +54,20 @@ pub fn add_commas(number_str: impl AsRef) -> String { /// add_commas_mut(&mut input); /// assert_eq!(input, "30,000,000"); /// ``` -pub fn add_commas_mut(str_mut: &mut String) { +pub fn add_commas_mut(number_str: &mut String) { let comma_less = |c: &char| c != &','; - - let mut end = str_mut + let mut end = number_str .chars() .filter(comma_less) .position(|c| c == '.') - .unwrap_or_else(|| str_mut.chars().filter(comma_less).count()); + .unwrap_or_else(|| number_str.chars().filter(comma_less).count()); let mut i = 0; while i < end { if (end - i) % 3 == 0 && i != 0 { - let c = str_mut.chars().nth(i).unwrap(); // TODO is this safe? + let c = number_str.chars().nth(i).unwrap(); // this is safe because i can be at maximum of string len if c != ',' { - str_mut.insert(i, ','); + number_str.insert(i, ','); } end += 1; i += 1; diff --git a/src/national_id/mod.rs b/src/national_id/mod.rs index 192e7ec..107ef68 100644 --- a/src/national_id/mod.rs +++ b/src/national_id/mod.rs @@ -113,15 +113,20 @@ pub fn verify_iranian_national_id(code: impl AsRef) -> Result<(), NationalI } let code_str = &("00".to_owned() + code_str)[length + 2 - 10..]; + + // this unrwap is safe because if the code_str length is not in the 8..=10 range , it would return NationalIdError::Length if code_str[3..9].parse::().unwrap() == 0 { return Err(NationalIdError::Invalid); } let mut sum = (0usize..9).fold(0, |sum, i| { - sum + code_str[i..i + 1].parse::().unwrap() * (10 - i) //TODO is this safe + // this unrwap is safe because if the code_str length is not in the 8..=10 range , it would return NationalIdError::Length + sum + code_str[i..i + 1].parse::().unwrap() * (10 - i) }); + sum %= 11; let last_number = (code_u64 % 10) as usize; + if (sum < 2 && last_number == sum) || (sum >= 2 && last_number == 11 - sum) { Ok(()) } else { diff --git a/src/number_plate/mod.rs b/src/number_plate/mod.rs index 4978241..a5a8d58 100644 --- a/src/number_plate/mod.rs +++ b/src/number_plate/mod.rs @@ -27,7 +27,9 @@ pub fn get_plate_info(plate: impl AsRef) -> Result } fn get_car_info(numbers: String, char: String) -> Result { - let province_code: u32 = numbers[5..7].parse().unwrap(); // TODO is this safe? + // The `unwrap()` call is safe because it's contingent upon a precondition: the `numbers` + // length argument must be exactly 7, ensuring the presence of a valid range to unwrap. + let province_code: u32 = numbers[5..7].parse().unwrap(); let plate_type = PlateTypes::Car; let template = format!( "{}{}{}ایران{}", @@ -68,7 +70,9 @@ fn get_car_info(numbers: String, char: String) -> Result Result { - let province_code: u32 = numbers[0..3].parse().unwrap(); // TODO is this safe? + // The `unwrap()` call is safe because it's contingent upon a precondition: the `numbers` + // length argument must be exactly 8, ensuring the presence of a valid range to unwrap. + let province_code: u32 = numbers[0..3].parse().unwrap(); let plate_type = PlateTypes::Motorcycle; let template = format!("{}-{}", &numbers[0..3], &numbers[3..]);