use crate::NiceWrapper;
use std::num::NonZeroU16;
const SIZE: usize = 6;
const ZERO: [u8; SIZE] = [b'0', b'0', b',', b'0', b'0', b'0'];
pub type NiceU16 = NiceWrapper<SIZE>;
super::nice_default!(NiceU16, ZERO, SIZE);
super::nice_from_nz!(NiceU16, NonZeroU16);
impl From<u16> for NiceU16 {
#[allow(clippy::cast_possible_truncation)] #[allow(unsafe_code)]
fn from(num: u16) -> Self {
if 999 < num {
let mut inner = ZERO;
let ptr = inner.as_mut_ptr();
let (num, rem) = crate::div_mod(num, 1000);
unsafe { super::write_u8_3(ptr.add(3), rem); }
if 9 < num {
unsafe {
std::ptr::copy_nonoverlapping(
crate::double_ptr(num as usize),
ptr,
2
);
}
Self {
inner,
from: 0,
}
}
else {
unsafe { std::ptr::write(ptr.add(1), num as u8 + b'0'); }
Self {
inner,
from: 1,
}
}
}
else if 99 < num {
let mut inner = ZERO;
unsafe { super::write_u8_3(inner.as_mut_ptr().add(3), num); }
Self {
inner,
from: 3,
}
}
else {
let [a, b] = crate::double(num as usize);
Self {
inner: [b'0', b'0', b',', b'0', a, b],
from: if a == b'0' { 5 } else { 4 },
}
}
}
}
impl NiceU16 {
#[must_use]
pub fn with_separator(num: u16, sep: u8) -> Self {
assert!(sep.is_ascii(), "Invalid separator.");
let mut out = Self::from(num);
out.inner[2] = sep;
out
}
}
#[cfg(test)]
mod tests {
use super::*;
use num_format::{ToFormattedString, Locale};
#[test]
fn t_nice_u16() {
assert_eq!(NiceU16::default(), NiceU16::from(0_u16));
#[cfg(not(miri))]
for i in 0..=u16::MAX {
assert_eq!(
NiceU16::from(i).as_str(),
i.to_formatted_string(&Locale::en),
);
}
#[cfg(miri)]
{
let rng = fastrand::Rng::new();
for i in std::iter::repeat_with(|| rng.u16(..)).take(1000) {
assert_eq!(
NiceU16::from(i).as_str(),
i.to_formatted_string(&Locale::en),
);
}
}
assert_eq!(NiceU16::empty().as_bytes(), <&[u8]>::default());
assert_eq!(NiceU16::empty().as_str(), "");
let foo: Option<u16> = None;
assert_eq!(NiceU16::default(), NiceU16::from(foo));
let foo = Some(13_u16);
assert_eq!(NiceU16::from(13_u16), NiceU16::from(foo));
let one = NiceU16::from(10_u16);
let two = NiceU16::from(90_u16);
assert_eq!(one.cmp(&two), std::cmp::Ordering::Less);
assert_eq!(one.cmp(&one), std::cmp::Ordering::Equal);
assert_eq!(two.cmp(&one), std::cmp::Ordering::Greater);
}
#[test]
fn t_nice_nonzero_u16() {
assert_eq!(NiceU16::default(), NiceU16::from(NonZeroU16::new(0)));
assert_eq!(NiceU16::from(50_u16), NiceU16::from(NonZeroU16::new(50)));
assert_eq!(NiceU16::from(50_u16), NiceU16::from(NonZeroU16::new(50).unwrap()));
let foo: Option<NonZeroU16> = None;
assert_eq!(NiceU16::from(foo), NiceU16::default());
let foo = NonZeroU16::new(13);
assert_eq!(NiceU16::from(13_u16), NiceU16::from(foo));
}
#[test]
fn t_as() {
let num = NiceU16::from(1234_u16);
assert_eq!(num.as_str(), String::from(num));
assert_eq!(num.as_bytes(), Vec::<u8>::from(num));
}
}