[go: up one dir, main page]

standback 0.3.3

New standard library, old compiler.
Documentation
#[cfg(feature = "alloc")]
use alloc::rc::Rc;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use core::cmp::Ordering;
#[cfg(feature = "std")]
use core::mem::transmute;
use core::num::FpCategory;
#[cfg(feature = "alloc")]
use core::ops;
use core::time::Duration;
use core::{mem, u64};
#[cfg(feature = "std")]
use std::ffi::{OsStr, OsString};

use crate::traits::{Float, Integer, Sealed};

pub trait Ordering_v1_53: Sealed<Ordering> {
    fn is_eq(self) -> bool;
    fn is_ne(self) -> bool;
    fn is_lt(self) -> bool;
    fn is_gt(self) -> bool;
    fn is_le(self) -> bool;
    fn is_ge(self) -> bool;
}

impl Ordering_v1_53 for Ordering {
    #[must_use]
    fn is_eq(self) -> bool {
        self == Ordering::Equal
    }
    #[must_use]
    fn is_ne(self) -> bool {
        self != Ordering::Equal
    }
    #[must_use]
    fn is_lt(self) -> bool {
        self == Ordering::Less
    }
    #[must_use]
    fn is_gt(self) -> bool {
        self == Ordering::Greater
    }
    #[must_use]
    fn is_le(self) -> bool {
        self != Ordering::Greater
    }
    #[must_use]
    fn is_ge(self) -> bool {
        self != Ordering::Less
    }
}

pub trait Option_v1_53<T>: Sealed<Option<T>> {
    fn insert(&mut self, value: T) -> &mut T;
}

impl<T> Option_v1_53<T> for Option<T> {
    fn insert(&mut self, value: T) -> &mut T {
        *self = Some(value);

        match self {
            Some(v) => v,
            None => unsafe { core::hint::unreachable_unchecked() },
        }
    }
}

pub trait Float_v1_53: Float {
    fn is_subnormal(self) -> bool;
}

impl Float_v1_53 for f32 {
    fn is_subnormal(self) -> bool {
        self.classify() == FpCategory::Subnormal
    }
}

impl Float_v1_53 for f64 {
    fn is_subnormal(self) -> bool {
        self.classify() == FpCategory::Subnormal
    }
}

pub trait Duration_v1_53: Sealed<Duration> {
    const ZERO: Self;
    fn is_zero(&self) -> bool;
    fn saturating_add(self, rhs: Self) -> Self;
    fn saturating_sub(self, rhs: Self) -> Self;
    fn saturating_mul(self, rhs: u32) -> Self;
}

impl Duration_v1_53 for Duration {
    const ZERO: Self = Self::from_nanos(0);

    fn is_zero(&self) -> bool {
        *self == Self::ZERO
    }
    fn saturating_add(self, rhs: Self) -> Self {
        match self.checked_add(rhs) {
            Some(res) => res,
            None => Duration::from_secs(u64::MAX) + Duration::from_nanos(999_999_999),
        }
    }
    fn saturating_sub(self, rhs: Self) -> Self {
        match self.checked_sub(rhs) {
            Some(res) => res,
            None => Self::ZERO,
        }
    }
    fn saturating_mul(self, rhs: u32) -> Self {
        match self.checked_mul(rhs) {
            Some(res) => res,
            None => Duration::from_secs(u64::MAX) + Duration::from_nanos(999_999_999),
        }
    }
}

pub trait Integer_v1_53: Integer {
    const BITS: u32;
}

macro_rules! impl_integer {
    ($($t:ty)+) => {$(
        impl Integer_v1_53 for $t {
            const BITS: u32 = mem::size_of::<$t>() as u32 * 8;
        }
    )+};
}

impl_integer![u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize];

#[cfg(feature = "alloc")]
pub trait Rc_v1_53<T>: Sealed<Rc<T>> {
    unsafe fn increment_strong_count(ptr: *const T);
    unsafe fn decrement_strong_count(ptr: *const T);
}

#[cfg(feature = "alloc")]
impl<T> Rc_v1_53<T> for Rc<T> {
    unsafe fn increment_strong_count(ptr: *const T) {
        let rc = mem::ManuallyDrop::new(Rc::<T>::from_raw(ptr));
        let _rc_clone = rc.clone();
    }
    unsafe fn decrement_strong_count(ptr: *const T) {
        drop(Rc::from_raw(ptr));
    }
}

#[cfg(feature = "std")]
pub trait OsStr_v1_53: Sealed<OsStr> {
    fn make_ascii_lowercase(&mut self);
    fn make_ascii_uppercase(&mut self);
    fn to_ascii_lowercase(&self) -> OsString;
    fn to_ascii_uppercase(&self) -> OsString;
    fn is_ascii(&self) -> bool;
    fn eq_ignore_ascii_case<S: AsRef<OsStr>>(&self, other: S) -> bool;
}

#[cfg(feature = "std")]
impl OsStr_v1_53 for OsStr {
    fn make_ascii_lowercase(&mut self) {
        unsafe { transmute::<_, &mut [u8]>(self).make_ascii_lowercase() }
    }
    fn make_ascii_uppercase(&mut self) {
        unsafe { transmute::<_, &mut [u8]>(self).make_ascii_uppercase() }
    }
    fn to_ascii_lowercase(&self) -> OsString {
        unsafe { transmute(transmute::<_, &[u8]>(self).to_ascii_lowercase()) }
    }
    fn to_ascii_uppercase(&self) -> OsString {
        unsafe { transmute(transmute::<_, &[u8]>(self).to_ascii_uppercase()) }
    }
    fn is_ascii(&self) -> bool {
        unsafe { transmute::<_, &[u8]>(self).is_ascii() }
    }
    fn eq_ignore_ascii_case<S: AsRef<OsStr>>(&self, other: S) -> bool {
        unsafe { transmute::<_, &[u8]>(self).eq_ignore_ascii_case(transmute(other.as_ref())) }
    }
}

#[cfg(feature = "alloc")]
pub trait Vec_v1_53<T>: Sealed<Vec<T>> {
    fn extend_from_within<R: ops::RangeBounds<usize> + core::slice::SliceIndex<[T], Output = [T]>>(
        &mut self,
        src: R,
    );
}

#[cfg(feature = "alloc")]
impl<T: Clone> Vec_v1_53<T> for Vec<T> {
    fn extend_from_within<
        R: ops::RangeBounds<usize> + core::slice::SliceIndex<[T], Output = [T]>,
    >(
        &mut self,
        src: R,
    ) {
        let start = match src.start_bound() {
            ops::Bound::Included(&start) => start,
            ops::Bound::Excluded(start) => start
                .checked_add(1)
                .expect("attempted to index slice from after maximum usize"),
            ops::Bound::Unbounded => 0,
        };
        let end = match src.end_bound() {
            ops::Bound::Included(end) => end
                .checked_add(1)
                .expect("attempted to index slice up to maximum usize"),
            ops::Bound::Excluded(&end) => end,
            ops::Bound::Unbounded => self.len(),
        };
        if start > end {
            panic!("slice index starts at {} but ends at {}", start, end);
        }
        if end > self.len() {
            panic!(
                "range end index {} out of range for slice of length {}",
                end,
                self.len()
            );
        }
        self.reserve(end - start);

        let ptr = self.as_mut_ptr();
        let spare_ptr = unsafe { ptr.add(self.len()) } as _;

        let this = unsafe { core::slice::from_raw_parts_mut(ptr, self.len()) };
        let spare =
            unsafe { core::slice::from_raw_parts_mut(spare_ptr, self.capacity() - self.len()) };

        unsafe { this.get_unchecked(src) }
            .iter()
            .cloned()
            .zip(spare.iter_mut())
            .map(|(src, dst)| *dst = core::mem::MaybeUninit::new(src))
            .for_each(|_| unsafe { self.set_len(self.len() + 1) });
    }
}

pub(crate) mod array {
    pub fn from_ref<T>(s: &T) -> &[T; 1] {
        unsafe { &*(s as *const T as *const [T; 1]) }
    }
    pub fn from_mut<T>(s: &mut T) -> &mut [T; 1] {
        unsafe { &mut *(s as *mut T as *mut [T; 1]) }
    }
}

pub(crate) mod cmp {
    use super::*;

    #[must_use]
    pub fn min_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T {
        match compare(&v1, &v2) {
            Ordering::Less | Ordering::Equal => v1,
            Ordering::Greater => v2,
        }
    }
    #[must_use]
    pub fn min_by_key<T, F: FnMut(&T) -> K, K: Ord>(v1: T, v2: T, mut f: F) -> T {
        min_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2)))
    }
    #[must_use]
    pub fn max_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T {
        match compare(&v1, &v2) {
            Ordering::Less | Ordering::Equal => v2,
            Ordering::Greater => v1,
        }
    }
    #[must_use]
    pub fn max_by_key<T, F: FnMut(&T) -> K, K: Ord>(v1: T, v2: T, mut f: F) -> T {
        max_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2)))
    }
}