1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
#![no_std] use core::{cmp::*, ops::*, slice}; mod private { pub trait OptionExtSealed {} pub trait SliceExtSealed {} } use private::*; pub trait OptionExt: OptionExtSealed { type Inner; fn try_get_or_insert_with<E, F: FnOnce() -> Result<Self::Inner, E>>(&mut self, f: F) -> Result<&mut Self::Inner, E>; } impl<A> OptionExtSealed for Option<A> {} impl<A> OptionExt for Option<A> { type Inner = A; #[inline] fn try_get_or_insert_with<E, F: FnOnce() -> Result<A, E>>(&mut self, f: F) -> Result<&mut A, E> { unsafe { if let None = self { *self = Some(f()?) } match self { Some(a) => Ok(a), _ => ::core::hint::unreachable_unchecked(), } } } } pub trait SliceExt: SliceExtSealed { type Inner; fn is_sorted(&self) -> bool where Self::Inner: Ord { self.is_sorted_by(Ord::cmp) } fn is_sorted_by<F: FnMut(&Self::Inner, &Self::Inner) -> Ordering>(&self, f: F) -> bool; fn is_sorted_by_key<F: FnMut(&Self::Inner) -> K, K: Ord>(&self, mut f: F) -> bool { self.is_sorted_by(|a, b| Ord::cmp(&f(a), &f(b))) } fn try_split_at(&self, k: usize) -> Option<(&Self, &Self)>; fn try_split_at_mut(&mut self, k: usize) -> Option<(&mut Self, &mut Self)>; unsafe fn split_at_unchecked(&self, k: usize) -> (&Self, &Self); unsafe fn split_at_unchecked_mut(&mut self, k: usize) -> (&mut Self, &mut Self); } impl<A> SliceExtSealed for [A] {} impl<A> SliceExt for [A] { type Inner = A; #[inline] fn is_sorted_by<F: FnMut(&A, &A) -> Ordering>(&self, mut f: F) -> bool { (1..self.len()).all(|k| Ordering::Less != f(&self[k], &self[k-1])) } #[inline] fn try_split_at(&self, k: usize) -> Option<(&Self, &Self)> { if k > self.len() { None } else { Some(unsafe { self.split_at_unchecked(k) }) } } #[inline] fn try_split_at_mut(&mut self, k: usize) -> Option<(&mut Self, &mut Self)> { if k > self.len() { None } else { Some(unsafe { self.split_at_unchecked_mut(k) }) } } #[inline(always)] unsafe fn split_at_unchecked(&self, k: usize) -> (&Self, &Self) { (slice::from_raw_parts(self.as_ptr(), k), slice::from_raw_parts(self.as_ptr().add(k), self.len() - k)) } #[inline(always)] unsafe fn split_at_unchecked_mut(&mut self, k: usize) -> (&mut Self, &mut Self) { (slice::from_raw_parts_mut(self.as_mut_ptr(), k), slice::from_raw_parts_mut(self.as_mut_ptr().add(k), self.len() - k)) } } #[inline] pub fn checked_sub<A: PartialOrd<B> + Sub<B>, B>(a: A, b: B) -> Option<<A as Sub<B>>::Output> { if a >= b { Some(a - b) } else { None } } #[inline] pub fn zip_opt<A, B>(x: Option<A>, y: Option<B>) -> Option<(A, B)> { match (x, y) { (Some(x), Some(y)) => Some((x, y)), _ => None, } }