Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add safety unwrap comments #60

Merged
merged 1 commit into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 24 additions & 23 deletions src/commas/add_commas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,27 @@
/// }
/// ```
pub fn add_commas(number_str: impl AsRef<str>) -> 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::<String>()
+ &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
}
Expand All @@ -52,21 +54,20 @@ pub fn add_commas(number_str: impl AsRef<str>) -> 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;
Expand Down
7 changes: 6 additions & 1 deletion src/national_id/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,15 +113,20 @@ pub fn verify_iranian_national_id(code: impl AsRef<str>) -> 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::<u64>().unwrap() == 0 {
return Err(NationalIdError::Invalid);
}

let mut sum = (0usize..9).fold(0, |sum, i| {
sum + code_str[i..i + 1].parse::<usize>().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::<usize>().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 {
Expand Down
8 changes: 6 additions & 2 deletions src/number_plate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ pub fn get_plate_info(plate: impl AsRef<str>) -> Result<Plate, PlateNumberError>
}

fn get_car_info(numbers: String, char: String) -> Result<Plate, PlateNumberError> {
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!(
"{}{}{}ایران{}",
Expand Down Expand Up @@ -68,7 +70,9 @@ fn get_car_info(numbers: String, char: String) -> Result<Plate, PlateNumberError
}

fn get_motorcycle_info(numbers: String) -> Result<Plate, PlateNumberError> {
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..]);

Expand Down