use std::future::Future; use std::ops::RangeBounds; use num_traits::One; use pin_project::pin_project; use crate::Number; pub fn usize_delta(minuend: N, subtrahend: N) -> usize { try_usize_delta(minuend, subtrahend) .unwrap_or_else(|| panic!("Out of usize range: {}", minuend - subtrahend)) } pub fn try_usize_delta(minuend: N, subtrahend: N) -> Option { assert!(minuend >= subtrahend); std::convert::TryInto::::try_into(minuend - subtrahend).ok() } pub fn usize_remainder(dividend: N, divisor: N) -> usize { try_usize_remainder(dividend, divisor) .unwrap_or_else(|| panic!("Out of usize range: {}", dividend % divisor)) } pub fn try_usize_remainder(dividend: N, divisor: N) -> Option { std::convert::TryInto::::try_into(dividend % divisor).ok() } pub fn from_usize(n: usize, quantity: &str) -> N { N::try_from(n).unwrap_or_else(|_| panic!("{quantity} out of range")) } #[pin_project] pub struct Race where A: Future, B: Future, { #[pin] first: A, #[pin] second: B, } impl Race where A: Future, B: Future, { pub fn between(first: A, second: B) -> Self { Race { first, second } } } impl Future for Race where A: Future, B: Future, { type Output = T; fn poll( self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>, ) -> std::task::Poll { let this = self.project(); match this.first.poll(cx) { std::task::Poll::Pending => this.second.poll(cx), ready => ready, } } } #[derive(Copy, Debug)] pub struct PhantomSend(std::marker::PhantomData); unsafe impl Send for PhantomSend {} impl PhantomSend { pub fn new() -> Self { Self(std::marker::PhantomData) } } impl Default for PhantomSend { fn default() -> Self { Self(Default::default()) } } impl Clone for PhantomSend { fn clone(&self) -> Self { Self(self.0) } } pub struct NumberIter { next: Option, last: N, } impl NumberIter { pub fn from_range>(range: R) -> Self { let next = match range.start_bound() { std::ops::Bound::Included(n) => Some(*n), std::ops::Bound::Excluded(n) => { if *n == N::min_value() { None } else { Some(*n - One::one()) } } std::ops::Bound::Unbounded => Some(N::min_value()), }; let last = match range.end_bound() { std::ops::Bound::Included(n) => Some(*n), std::ops::Bound::Excluded(n) => { if *n == N::min_value() { None } else { Some(*n - One::one()) } } std::ops::Bound::Unbounded => Some(N::max_value()), }; match (next, last) { (Some(n), Some(last)) if n <= last => NumberIter { next, last }, _ => NumberIter { next: None, last: N::min_value(), }, } } } impl std::iter::Iterator for NumberIter { type Item = N; fn next(&mut self) -> Option { if let Some(n) = self.next { if n == self.last { self.next = None; } else { self.next = Some(n + One::one()); } Some(n) } else { None } } }