mod iter_pair;
use iter_pair::IterPair;
use std::{cmp::Ordering, iter::Peekable, str::Chars};
pub fn sort(arr: &mut [&str]) {
arr.sort_by(|a, b| compare(a, b));
}
pub fn compare(s1: &str, s2: &str) -> Ordering {
compare_chars_iters(s1.chars(), s2.chars()).unwrap_or(s1.cmp(s2))
}
pub fn compare_chars_iters<'a>(c1: Chars<'a>, c2: Chars<'a>) -> Result<Ordering, ()> {
let mut iters = IterPair::from(c1, c2);
while let [Some(x), Some(y)] = iters.peek() {
if x == y {
iters.next();
} else if x.is_numeric() && y.is_numeric() {
match take_numeric(&mut iters.fst).cmp(&take_numeric(&mut iters.lst)) {
Ordering::Equal => iters.next(),
ref a => return Ok(*a),
};
} else {
return Ok(x.cmp(y));
}
}
Err(())
}
fn take_numeric(iter: &mut Peekable<Chars>) -> u32 {
let mut sum = 0;
while let Some(p) = iter.peek() {
match p.to_string().parse::<u32>() {
Ok(n) => {
sum = sum * 10 + n;
iter.next();
}
_ => break,
}
}
sum
}