#![allow(dead_code)]
use az::CheckedCast;
pub trait AsOrPanic {
fn as_or_panic<Dst>(self) -> Dst
where
Self: CheckedCast<Dst>;
}
impl<T> AsOrPanic for T {
#[inline]
fn as_or_panic<Dst>(self) -> Dst
where
Self: CheckedCast<Dst>,
{
self.checked_cast().expect("overflow")
}
}
pub trait NegAbs {
type Abs;
fn neg_abs(self) -> (bool, Self::Abs);
}
macro_rules! neg_abs {
($I:ty; $U:ty) => {
impl NegAbs for $I {
type Abs = $U;
#[inline]
fn neg_abs(self) -> (bool, $U) {
if self < 0 {
(true, self.wrapping_neg() as $U)
} else {
(false, self as $U)
}
}
}
impl NegAbs for $U {
type Abs = $U;
#[inline]
fn neg_abs(self) -> (bool, $U) {
(false, self)
}
}
};
}
neg_abs! { i8; u8 }
neg_abs! { i16; u16 }
neg_abs! { i32; u32 }
neg_abs! { i64; u64 }
neg_abs! { i128; u128 }
neg_abs! { isize; usize }
pub fn trunc_f64_to_f32(f: f64) -> f32 {
if !f.is_nan() {
let u = f.to_bits();
let trunc_u = u & (!0 << 29);
let trunc_f = f64::from_bits(trunc_u);
trunc_f as f32
} else {
f as f32
}
}
fn lcase(byte: u8) -> u8 {
match byte {
b'A'..=b'Z' => byte - b'A' + b'a',
_ => byte,
}
}
pub fn trim_start(bytes: &[u8]) -> &[u8] {
for (start, &b) in bytes.iter().enumerate() {
match b {
b' ' | b'\t' | b'\n' | 0x0b | 0x0c | 0x0d => {}
_ => return &bytes[start..],
}
}
&[]
}
pub fn trim_end(bytes: &[u8]) -> &[u8] {
for (end, &b) in bytes.iter().enumerate().rev() {
match b {
b' ' | b'\t' | b'\n' | 0x0b | 0x0c | 0x0d => {}
_ => return &bytes[..=end],
}
}
&[]
}
pub fn skip_lcase_match<'a>(bytes: &'a [u8], patterns: &[&[u8]]) -> Option<&'a [u8]> {
'next_pattern: for pattern in patterns {
if bytes.len() < pattern.len() {
continue 'next_pattern;
}
for (&b, &p) in bytes.iter().zip(pattern.iter()) {
if lcase(b) != p {
continue 'next_pattern;
}
}
return Some(&bytes[pattern.len()..]);
}
None
}
pub fn matched_brackets(bytes: &[u8]) -> Option<(&[u8], &[u8])> {
let mut iter = bytes.iter().enumerate();
match iter.next() {
Some((_, &b'(')) => {}
_ => return None,
}
let mut level = 1;
for (i, &b) in iter {
match b {
b'(' => level += 1,
b')' => {
level -= 1;
if level == 0 {
return Some((&bytes[1..i], &bytes[i + 1..]));
}
}
_ => {}
}
}
None
}
pub fn find_outside_brackets(bytes: &[u8], pattern: u8) -> Option<usize> {
let mut level = 0;
for (i, &b) in bytes.iter().enumerate() {
match b {
b'(' => level += 1,
b')' if level > 0 => level -= 1,
_ if level == 0 && b == pattern => return Some(i),
_ => {}
}
}
None
}
pub fn find_space_outside_brackets(bytes: &[u8]) -> Option<usize> {
let mut level = 0;
for (i, &b) in bytes.iter().enumerate() {
match b {
b'(' => level += 1,
b')' if level > 0 => level -= 1,
b' ' | b'\t' | b'\n' | 0x0b | 0x0c | 0x0d if level == 0 => {
return Some(i);
}
_ => {}
}
}
None
}