#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(docsrs, feature(doc_cfg))]
extern crate alloc;
#[cfg(feature = "std")]
mod std_functions;
use core::{cmp::Ordering, str::Chars};
#[cfg(feature = "std")]
pub use std_functions::*;
pub fn compare_str<A: AsRef<str>, B: AsRef<str>>(a: A, b: B) -> Ordering {
let mut c1 = a.as_ref().chars();
let mut c2 = b.as_ref().chars();
let mut last_is_number = false;
let mut pre_answer = Ordering::Equal;
let mut v1: Option<char> = None;
let mut v2: Option<char> = None;
loop {
let mut ca = {
match v1.take() {
Some(c) => c,
None => match c1.next() {
Some(c) => c,
None => {
if v2.take().is_some() || c2.next().is_some() {
return Ordering::Less;
} else {
return pre_answer;
}
},
},
}
};
let mut cb = {
match v2.take() {
Some(c) => c,
None => match c2.next() {
Some(c) => c,
None => {
return Ordering::Greater;
},
},
}
};
if ca.is_ascii_digit() && cb.is_ascii_digit() {
let mut la = 1usize;
let mut lb = 1usize;
let mut lc = 0isize;
while ca == '0' {
lc += 1;
if let Some(c) = c1.next() {
if c.is_ascii_digit() {
ca = c;
} else {
v1 = Some(c);
la = 0;
break;
}
} else {
la = 0;
break;
}
}
while cb == '0' {
lc -= 1;
if let Some(c) = c2.next() {
if c.is_ascii_digit() {
cb = c;
} else {
v2 = Some(c);
lb = 0;
break;
}
} else {
lb = 0;
break;
}
}
let consume_ascii_digit = |chars: &mut Chars, store: &mut Option<char>| {
let mut counter = 0;
for c in chars.by_ref() {
if c.is_ascii_digit() {
counter += 1;
} else {
*store = Some(c);
break;
}
}
counter
};
let mut ordering = Ordering::Equal;
if la == 0 {
if lb == 0 {
} else {
return Ordering::Less;
}
} else if lb == 0 {
return Ordering::Greater;
} else {
loop {
ordering = ca.cmp(&cb);
if ordering == Ordering::Equal {
if let Some(c) = c1.next() {
if c.is_ascii_digit() {
if let Some(cc) = c2.next() {
if cc.is_ascii_digit() {
ca = c;
cb = cc;
} else {
return Ordering::Greater;
}
} else {
return Ordering::Greater;
}
} else {
let n = consume_ascii_digit(&mut c2, &mut v2);
v1 = Some(c);
if n > 0 {
return Ordering::Less;
}
break;
}
} else if c2.next().is_some() {
return Ordering::Less;
} else {
break;
}
} else {
la += consume_ascii_digit(&mut c1, &mut v1);
lb += consume_ascii_digit(&mut c2, &mut v2);
if la != lb {
ordering = la.cmp(&lb);
}
break;
}
}
}
if ordering == Ordering::Equal {
match lc.cmp(&0) {
Ordering::Equal => {
last_is_number = true;
},
Ordering::Greater => {
if pre_answer == Ordering::Equal {
pre_answer = Ordering::Greater;
} else {
}
},
Ordering::Less => {
if pre_answer == Ordering::Equal {
pre_answer = Ordering::Less;
} else {
}
},
}
} else {
return ordering;
}
} else {
match ca.cmp(&cb) {
Ordering::Equal => last_is_number = false,
Ordering::Greater => {
return if last_is_number && (ca > (255 as char)) ^ (cb > (255 as char)) {
Ordering::Less
} else {
Ordering::Greater
};
},
Ordering::Less => {
return if last_is_number && (ca > (255 as char)) ^ (cb > (255 as char)) {
Ordering::Greater
} else {
Ordering::Less
};
},
}
}
}
}
#[inline]
pub fn sort_slice_unstable_by_str_key<A, T: ?Sized + AsRef<str>, F: FnMut(&A) -> &T>(
slice: &mut [A],
mut f: F,
) {
slice.sort_unstable_by(|a, b| compare_str(f(a), f(b)));
}
#[inline]
pub fn sort_slice_by_str_key<A, T: ?Sized + AsRef<str>, F: FnMut(&A) -> &T>(
slice: &mut [A],
mut f: F,
) {
slice.sort_by(|a, b| compare_str(f(a), f(b)));
}
#[inline]
pub fn sort_slice_rev_unstable_by_str_key<A, T: ?Sized + AsRef<str>, F: FnMut(&A) -> &T>(
slice: &mut [A],
mut f: F,
) {
slice.sort_unstable_by(|a, b| compare_str(f(b), f(a)));
}
#[inline]
pub fn sort_slice_rev_by_str_key<A, T: ?Sized + AsRef<str>, F: FnMut(&A) -> &T>(
slice: &mut [A],
mut f: F,
) {
slice.sort_by(|a, b| compare_str(f(b), f(a)));
}
#[inline]
pub fn sort_str_slice<S: AsRef<str>>(slice: &mut [S]) {
slice.sort_unstable_by(|a, b| compare_str(a, b));
}
#[inline]
pub fn sort_str_slice_rev<S: AsRef<str>>(slice: &mut [S]) {
slice.sort_unstable_by(|a, b| compare_str(b, a));
}