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

fix: division by zero on 32-bit platform (#107, #118) #239

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
51 changes: 30 additions & 21 deletions src/util/animalnumbers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,48 +6,57 @@ const ANIMAL_NAMES: &[&str] = &[
"deer", "horse", "rat", "wasp", "dog", "jaguar", "raven", "whale", "dove", "koala", "seal",
"wolf", "duck", "lion", "shark", "worm", "eagle", "lizard", "sheep", "zebra",
];
const ANIMAL_COUNT: u64 = ANIMAL_NAMES.len() as u64;

pub fn to_animal_names(mut number: u64) -> String {
pub fn to_animal_names(number: u64) -> String {
let mut result: Vec<&str> = Vec::new();

if number == 0 {
return ANIMAL_NAMES[0].parse().unwrap();
}

let mut power = 6;

loop {
let digit = number / ANIMAL_NAMES.len().pow(power) as u64;
if !(result.is_empty() && digit == 0) {
result.push(ANIMAL_NAMES[digit as usize]);
}
number -= digit * ANIMAL_NAMES.len().pow(power) as u64;
if power > 0 {
power -= 1;
} else if power == 0 || number == 0 {
break;
}
let mut value = number;
while value != 0 {
let digit = (value % ANIMAL_COUNT) as usize;
value /= ANIMAL_COUNT;
result.push(ANIMAL_NAMES[digit]);
}

// We calculated the numbers in Little-Endian,
// now convert to Big-Endian for backwards compatibility with old data.
result.reverse();

result.join("-")
}

#[test]
fn test_to_animal_names() {
assert_eq!(to_animal_names(0), "ant");
assert_eq!(to_animal_names(1), "eel");
assert_eq!(to_animal_names(64), "eel-ant");
assert_eq!(to_animal_names(12345), "sloth-ant-lion");
}

pub fn to_u64(animal_names: &str) -> Result<u64, &str> {
let mut result: u64 = 0;

let animals: Vec<&str> = animal_names.split('-').collect();

let mut pow = animals.len();
for animal in animals {
pow -= 1;
for animal in animal_names.split('-') {
let animal_index = ANIMAL_NAMES.iter().position(|&r| r == animal);
match animal_index {
None => return Err("Failed to convert animal name to u64!"),
Some(_) => {
result += (animal_index.unwrap() * ANIMAL_NAMES.len().pow(pow as u32)) as u64
Some(idx) => {
result = result * ANIMAL_COUNT + (idx as u64);
}
}
}

Ok(result)
}

#[test]
fn test_animal_name_to_u64() {
assert_eq!(to_u64("ant"), Ok(0));
assert_eq!(to_u64("eel"), Ok(1));
assert_eq!(to_u64("eel-ant"), Ok(64));
assert_eq!(to_u64("sloth-ant-lion"), Ok(12345));
}