use crate::asciibyte::AsciiByte;
#[repr(transparent)]
pub struct Aligned4(u32);
impl Aligned4 {
#[inline]
pub const fn from_bytes<const N: usize>(src: &[u8; N]) -> Self {
let mut bytes = [0; 4];
let mut i = 0;
#[allow(clippy::indexing_slicing)]
while i < N {
bytes[i] = src[i];
i += 1;
}
Self(u32::from_ne_bytes(bytes))
}
#[inline]
pub const fn from_ascii_bytes<const N: usize>(src: &[AsciiByte; N]) -> Self {
Self::from_bytes::<N>(unsafe { core::mem::transmute::<&[AsciiByte; N], &[u8; N]>(src) })
}
#[inline]
pub const fn to_bytes(&self) -> [u8; 4] {
self.0.to_ne_bytes()
}
#[inline]
pub const fn to_ascii_bytes(&self) -> [AsciiByte; 4] {
unsafe { core::mem::transmute(self.to_bytes()) }
}
pub const fn len(&self) -> usize {
let word = self.0;
#[cfg(target_endian = "little")]
let len = (4 - word.leading_zeros() / 8) as usize;
#[cfg(target_endian = "big")]
let len = (4 - word.trailing_zeros() / 8) as usize;
len
}
pub const fn is_ascii_alphabetic(&self) -> bool {
let word = self.0;
let mask = (word + 0x7f7f_7f7f) & 0x8080_8080;
let lower = word | 0x2020_2020;
let alpha = !(lower + 0x1f1f_1f1f) | (lower + 0x0505_0505);
(alpha & mask) == 0
}
pub const fn is_ascii_alphanumeric(&self) -> bool {
let word = self.0;
let mask = (word + 0x7f7f_7f7f) & 0x8080_8080;
let numeric = !(word + 0x5050_5050) | (word + 0x4646_4646);
let lower = word | 0x2020_2020;
let alpha = !(lower + 0x1f1f_1f1f) | (lower + 0x0505_0505);
(alpha & numeric & mask) == 0
}
pub const fn is_ascii_numeric(&self) -> bool {
let word = self.0;
let mask = (word + 0x7f7f_7f7f) & 0x8080_8080;
let numeric = !(word + 0x5050_5050) | (word + 0x4646_4646);
(numeric & mask) == 0
}
pub const fn is_ascii_lowercase(&self) -> bool {
let word = self.0;
let invalid_case = !(word + 0x3f3f_3f3f) | (word + 0x2525_2525);
(invalid_case & 0x8080_8080) == 0x8080_8080
}
pub const fn is_ascii_titlecase(&self) -> bool {
let word = self.0;
let invalid_case = if cfg!(target_endian = "little") {
!(word + 0x3f3f_3f1f) | (word + 0x2525_2505)
} else {
!(word + 0x1f3f_3f3f) | (word + 0x0525_2525)
};
(invalid_case & 0x8080_8080) == 0x8080_8080
}
pub const fn is_ascii_uppercase(&self) -> bool {
let word = self.0;
let invalid_case = !(word + 0x1f1f_1f1f) | (word + 0x0505_0505);
(invalid_case & 0x8080_8080) == 0x8080_8080
}
pub const fn is_ascii_alphabetic_lowercase(&self) -> bool {
let word = self.0;
let mask = (word + 0x7f7f_7f7f) & 0x8080_8080;
let lower_alpha = !(word + 0x1f1f_1f1f) | (word + 0x0505_0505);
(lower_alpha & mask) == 0
}
pub const fn is_ascii_alphabetic_titlecase(&self) -> bool {
let word = self.0;
let mask = (word + 0x7f7f_7f7f) & 0x8080_8080;
let title_case = if cfg!(target_endian = "little") {
!(word + 0x1f1f_1f3f) | (word + 0x0505_0525)
} else {
!(word + 0x3f1f_1f1f) | (word + 0x2505_0505)
};
(title_case & mask) == 0
}
pub const fn is_ascii_alphabetic_uppercase(&self) -> bool {
let word = self.0;
let mask = (word + 0x7f7f_7f7f) & 0x8080_8080;
let upper_alpha = !(word + 0x3f3f_3f3f) | (word + 0x2525_2525);
(upper_alpha & mask) == 0
}
pub const fn to_ascii_lowercase(&self) -> Self {
let word = self.0;
let result = word | (((word + 0x3f3f_3f3f) & !(word + 0x2525_2525) & 0x8080_8080) >> 2);
Self(result)
}
pub const fn to_ascii_titlecase(&self) -> Self {
let word = self.0.to_le();
let mask = ((word + 0x3f3f_3f1f) & !(word + 0x2525_2505) & 0x8080_8080) >> 2;
let result = (word | mask) & !(0x20 & mask);
Self(u32::from_le(result))
}
pub const fn to_ascii_uppercase(&self) -> Self {
let word = self.0;
let result = word & !(((word + 0x1f1f_1f1f) & !(word + 0x0505_0505) & 0x8080_8080) >> 2);
Self(result)
}
}
#[repr(transparent)]
pub struct Aligned8(u64);
impl Aligned8 {
#[inline]
pub const fn from_bytes<const N: usize>(src: &[u8; N]) -> Self {
let mut bytes = [0; 8];
let mut i = 0;
#[allow(clippy::indexing_slicing)]
while i < N {
bytes[i] = src[i];
i += 1;
}
Self(u64::from_ne_bytes(bytes))
}
#[inline]
pub const fn from_ascii_bytes<const N: usize>(src: &[AsciiByte; N]) -> Self {
Self::from_bytes::<N>(unsafe { core::mem::transmute::<&[AsciiByte; N], &[u8; N]>(src) })
}
#[inline]
pub const fn to_bytes(&self) -> [u8; 8] {
self.0.to_ne_bytes()
}
#[inline]
pub const fn to_ascii_bytes(&self) -> [AsciiByte; 8] {
unsafe { core::mem::transmute(self.to_bytes()) }
}
pub const fn len(&self) -> usize {
let word = self.0;
#[cfg(target_endian = "little")]
let len = (8 - word.leading_zeros() / 8) as usize;
#[cfg(target_endian = "big")]
let len = (8 - word.trailing_zeros() / 8) as usize;
len
}
pub const fn is_ascii_alphabetic(&self) -> bool {
let word = self.0;
let mask = (word + 0x7f7f_7f7f_7f7f_7f7f) & 0x8080_8080_8080_8080;
let lower = word | 0x2020_2020_2020_2020;
let alpha = !(lower + 0x1f1f_1f1f_1f1f_1f1f) | (lower + 0x0505_0505_0505_0505);
(alpha & mask) == 0
}
pub const fn is_ascii_alphanumeric(&self) -> bool {
let word = self.0;
let mask = (word + 0x7f7f_7f7f_7f7f_7f7f) & 0x8080_8080_8080_8080;
let numeric = !(word + 0x5050_5050_5050_5050) | (word + 0x4646_4646_4646_4646);
let lower = word | 0x2020_2020_2020_2020;
let alpha = !(lower + 0x1f1f_1f1f_1f1f_1f1f) | (lower + 0x0505_0505_0505_0505);
(alpha & numeric & mask) == 0
}
pub const fn is_ascii_numeric(&self) -> bool {
let word = self.0;
let mask = (word + 0x7f7f_7f7f_7f7f_7f7f) & 0x8080_8080_8080_8080;
let numeric = !(word + 0x5050_5050_5050_5050) | (word + 0x4646_4646_4646_4646);
(numeric & mask) == 0
}
pub const fn is_ascii_lowercase(&self) -> bool {
let word = self.0;
let invalid_case = !(word + 0x3f3f_3f3f_3f3f_3f3f) | (word + 0x2525_2525_2525_2525);
(invalid_case & 0x8080_8080_8080_8080) == 0x8080_8080_8080_8080
}
pub const fn is_ascii_titlecase(&self) -> bool {
let word = self.0;
let invalid_case = if cfg!(target_endian = "little") {
!(word + 0x3f3f_3f3f_3f3f_3f1f) | (word + 0x2525_2525_2525_2505)
} else {
!(word + 0x1f3f_3f3f_3f3f_3f3f) | (word + 0x0525_2525_2525_2525)
};
(invalid_case & 0x8080_8080_8080_8080) == 0x8080_8080_8080_8080
}
pub const fn is_ascii_uppercase(&self) -> bool {
let word = self.0;
let invalid_case = !(word + 0x1f1f_1f1f_1f1f_1f1f) | (word + 0x0505_0505_0505_0505);
(invalid_case & 0x8080_8080_8080_8080) == 0x8080_8080_8080_8080
}
pub const fn is_ascii_alphabetic_lowercase(&self) -> bool {
let word = self.0;
let mask = (word + 0x7f7f_7f7f_7f7f_7f7f) & 0x8080_8080_8080_8080;
let lower_alpha = !(word + 0x1f1f_1f1f_1f1f_1f1f) | (word + 0x0505_0505_0505_0505);
(lower_alpha & mask) == 0
}
pub const fn is_ascii_alphabetic_titlecase(&self) -> bool {
let word = self.0;
let mask = (word + 0x7f7f_7f7f_7f7f_7f7f) & 0x8080_8080_8080_8080;
let title_case = if cfg!(target_endian = "little") {
!(word + 0x1f1f_1f1f_1f1f_1f3f) | (word + 0x0505_0505_0505_0525)
} else {
!(word + 0x3f1f_1f1f_1f1f_1f1f) | (word + 0x2505_0505_0505_0505)
};
(title_case & mask) == 0
}
pub const fn is_ascii_alphabetic_uppercase(&self) -> bool {
let word = self.0;
let mask = (word + 0x7f7f_7f7f_7f7f_7f7f) & 0x8080_8080_8080_8080;
let upper_alpha = !(word + 0x3f3f_3f3f_3f3f_3f3f) | (word + 0x2525_2525_2525_2525);
(upper_alpha & mask) == 0
}
pub const fn to_ascii_lowercase(&self) -> Self {
let word = self.0;
let result = word
| (((word + 0x3f3f_3f3f_3f3f_3f3f)
& !(word + 0x2525_2525_2525_2525)
& 0x8080_8080_8080_8080)
>> 2);
Self(result)
}
pub const fn to_ascii_titlecase(&self) -> Self {
let word = self.0.to_le();
let mask = ((word + 0x3f3f_3f3f_3f3f_3f1f)
& !(word + 0x2525_2525_2525_2505)
& 0x8080_8080_8080_8080)
>> 2;
let result = (word | mask) & !(0x20 & mask);
Self(u64::from_le(result))
}
pub const fn to_ascii_uppercase(&self) -> Self {
let word = self.0;
let result = word
& !(((word + 0x1f1f_1f1f_1f1f_1f1f)
& !(word + 0x0505_0505_0505_0505)
& 0x8080_8080_8080_8080)
>> 2);
Self(result)
}
}