my_ecs/util/
mod.rs

1//! Utilities for the crate.
2
3pub(crate) mod macros;
4pub mod str;
5pub mod web;
6
7pub mod prelude {
8    pub use super::str as str_util;
9    #[cfg(target_arch = "wasm32")]
10    pub use super::web as web_util;
11    pub use super::{Or, PowerOfTwo, TakeRecur, With, WithResult};
12}
13
14use my_ecs_macros::repeat_macro;
15use std::{
16    fmt, hash,
17    ops::{Deref, DerefMut},
18    sync::{Arc, Condvar, Mutex},
19    thread,
20};
21
22/// A trait for taking inner value out.
23///
24/// Various types have methods like `take()` to take something out by consuming
25/// the type itself. If the taken value also can be unwrapped, then clients
26/// need to write code like `take().take()`. This trait helps to avoid something
27/// like that and replace it with just one call.
28///
29/// # Examples
30///
31/// ```
32/// use my_ecs::prelude::TakeRecur;
33///
34/// struct A(B);
35/// struct B(C);
36/// struct C(i32);
37///
38/// impl TakeRecur for A
39/// where
40///     B: TakeRecur
41/// {
42///     type Inner = <B as TakeRecur>::Inner;
43///     fn take_recur(self) -> Self::Inner { self.0.take_recur() }
44/// }
45///
46/// impl TakeRecur for B
47/// where
48///     C: TakeRecur,
49/// {
50///     type Inner = <C as TakeRecur>::Inner;
51///     fn take_recur(self) -> Self::Inner { self.0.take_recur() }
52/// }
53///
54/// impl TakeRecur for C {
55///     type Inner = i32;
56///     fn take_recur(self) -> Self::Inner { self.0 }
57/// }
58///
59/// let value = A(B(C(42)));
60/// assert_eq!(value.take_recur(), 42);
61/// ```
62pub trait TakeRecur {
63    type Inner;
64
65    /// Takes out inner value recursively then returns it.
66    ///
67    /// # Examples
68    ///
69    /// See [`TakeRecur`] documentation.
70    fn take_recur(self) -> Self::Inner;
71}
72
73/// Implements [`TakeRecur`] for (A0, A1), (A0, A1, A2), ...
74macro_rules! impl_take_recur_for_tuple {
75    ($n:expr, $($i:expr),*) => {const _: () = {
76        use paste::paste;
77
78        paste! {
79            impl<$([<A $i>]: TakeRecur),*> TakeRecur for ( $([<A $i>]),* ) {
80                type Inner = ( $([<A $i>]::Inner),* );
81
82                fn take_recur(self) -> Self::Inner {
83                    ( $( self.$i.take_recur(), )* )
84                }
85            }
86        }
87    };};
88}
89repeat_macro!(impl_take_recur_for_tuple, 2..=8);
90
91/// A type representing 2^k `usize`.
92///
93/// Zero is not 2^k though you can create [`PowerOfTwo`] by zero. In that case,
94/// zero is considered as `usize::MAX + 1` which is another 2^k.
95#[derive(Debug, Clone, Copy)]
96pub struct PowerOfTwo {
97    value: usize,
98    k: u32,
99    mask: usize,
100}
101
102impl PowerOfTwo {
103    /// Creates a new [`PowerOfTwo`] from the given value.
104    pub const fn new(value: usize) -> Option<Self> {
105        if value == 0 {
106            Some(Self {
107                value,
108                k: 0,
109                mask: 0,
110            })
111        } else if value.is_power_of_two() {
112            Some(Self {
113                value,
114                k: value.trailing_zeros(),
115                mask: usize::MAX,
116            })
117        } else {
118            None
119        }
120    }
121
122    /// Returns inner value.
123    pub const fn get(&self) -> usize {
124        self.value
125    }
126
127    /// Returns `numerator / self`.
128    ///
129    /// # Examples
130    ///
131    /// ```
132    /// use my_ecs::prelude::PowerOfTwo;
133    ///
134    /// let v = PowerOfTwo::new(4).unwrap();
135    /// assert_eq!(v.quotient(3), 0);
136    /// assert_eq!(v.quotient(4), 1);
137    /// assert_eq!(v.quotient(5), 1);
138    /// ```
139    pub const fn quotient(&self, numerator: usize) -> usize {
140        (numerator >> self.k) & self.mask
141    }
142
143    /// Returns `numerator % self`.
144    ///
145    /// # Examples
146    ///
147    /// ```
148    /// use my_ecs::prelude::PowerOfTwo;
149    ///
150    /// let v = PowerOfTwo::new(4).unwrap();
151    /// assert_eq!(v.remainder(3), 3);
152    /// assert_eq!(v.remainder(4), 0);
153    /// assert_eq!(v.remainder(5), 1);
154    /// ```
155    pub const fn remainder(&self, numerator: usize) -> usize {
156        numerator & self.value.wrapping_sub(1)
157    }
158}
159
160impl PartialEq for PowerOfTwo {
161    fn eq(&self, other: &Self) -> bool {
162        // It's sufficient to compare `value` only because others are determined
163        // by the value.
164        self.value == other.value
165    }
166}
167
168impl Eq for PowerOfTwo {}
169
170impl PartialOrd for PowerOfTwo {
171    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
172        Some(self.cmp(other))
173    }
174}
175
176impl Ord for PowerOfTwo {
177    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
178        // It's sufficient to compare `value` only because others are determined
179        // by the value.
180        self.value.cmp(&other.value)
181    }
182}
183
184impl hash::Hash for PowerOfTwo {
185    fn hash<H: hash::Hasher>(&self, state: &mut H) {
186        // It's sufficient to hash `value` only because others are determined
187        // by the value.
188        self.value.hash(state);
189    }
190}
191
192/// A type that either `A` or `B`.
193#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
194pub enum Or<A, B> {
195    A(A),
196    B(B),
197}
198
199impl<A, B> Or<A, B> {
200    /// Applies the given function to the value `A` then returns the result.
201    pub fn map_a<F, X>(self, op: F) -> Or<X, B>
202    where
203        F: FnOnce(A) -> X,
204    {
205        match self {
206            Or::A(a) => Or::A(op(a)),
207            Or::B(b) => Or::B(b),
208        }
209    }
210
211    /// Applies the given function to the value `B` then returns the result.
212    pub fn map_b<G, Y>(self, op: G) -> Or<A, Y>
213    where
214        G: FnOnce(B) -> Y,
215    {
216        match self {
217            Or::A(a) => Or::A(a),
218            Or::B(b) => Or::B(op(b)),
219        }
220    }
221
222    /// Applies the given functions to the value `A` and `B` respectively then
223    /// returns the result.
224    pub fn map_ab<F, G, X, Y>(self, op_a: F, op_b: G) -> Or<X, Y>
225    where
226        F: FnOnce(A) -> X,
227        G: FnOnce(B) -> Y,
228    {
229        match self {
230            Or::A(a) => Or::A(op_a(a)),
231            Or::B(b) => Or::B(op_b(b)),
232        }
233    }
234}
235
236impl<A: fmt::Debug, B: fmt::Debug> fmt::Debug for Or<A, B> {
237    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
238        match self {
239            Self::A(a) => a.fmt(f),
240            Self::B(b) => b.fmt(f),
241        }
242    }
243}
244
245/// A value with another value.
246///
247/// This type is almost the same as tuple `(T, U)` except how the type is
248/// displayed by [`Display`](fmt::Display). This type only prints first value
249/// only.
250#[derive(Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
251#[repr(C)]
252pub struct With<T, U> {
253    pub value: T,
254    pub with: U,
255}
256
257impl<T, U> fmt::Display for With<T, U>
258where
259    T: fmt::Display,
260{
261    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
262        self.value.fmt(f)
263    }
264}
265
266impl<T, U> With<T, U> {
267    /// Creates a new [`With`].
268    pub const fn new(value: T, with: U) -> Self {
269        Self { value, with }
270    }
271}
272
273/// A value with [`Result`].
274///
275/// This type implements [`Deref`] and [`DerefMut`] for the value, therefore it
276/// looks like value. But the type provides some `Result` methods as well.
277pub type WithResult<O, T, E> = With<O, Result<T, E>>;
278
279impl<O, T, E> WithResult<O, T, E> {
280    /// Converts [`WithResult`] into [`Result`] by unwraping self.
281    pub fn take(self) -> Result<T, E> {
282        self.with
283    }
284
285    /// See [`Result::is_ok`].
286    pub const fn is_ok(&self) -> bool {
287        self.with.is_ok()
288    }
289
290    /// See [`Result::is_ok_and`].
291    pub fn is_ok_and(self, f: impl FnOnce(T) -> bool) -> bool {
292        self.with.is_ok_and(f)
293    }
294
295    /// See [`Result::is_err`].
296    pub const fn is_err(&self) -> bool {
297        self.with.is_err()
298    }
299
300    /// See [`Result::is_err_and`].
301    pub fn is_err_and(self, f: impl FnOnce(E) -> bool) -> bool {
302        self.with.is_err_and(f)
303    }
304
305    /// See [`Result::ok`].
306    pub fn ok(self) -> Option<T> {
307        self.with.ok()
308    }
309
310    /// See [`Result::err`].
311    pub fn err(self) -> Option<E> {
312        self.with.err()
313    }
314
315    /// See [`Result::as_ref`].
316    pub const fn as_ref(&self) -> Result<&T, &E> {
317        self.with.as_ref()
318    }
319
320    /// See [`Result::as_mut`].
321    pub fn as_mut(&mut self) -> Result<&mut T, &mut E> {
322        self.with.as_mut()
323    }
324
325    /// Applies the given function to the result. See [`Result::map`].
326    pub fn map<F, U>(self, op: F) -> WithResult<O, U, E>
327    where
328        F: FnOnce(T) -> U,
329    {
330        WithResult::new(self.value, self.with.map(op))
331    }
332
333    /// Applies the given function to the result. See [`Result::map_err`].
334    pub fn map_err<F, D>(self, op: F) -> WithResult<O, T, D>
335    where
336        F: FnOnce(E) -> D,
337    {
338        WithResult::new(self.value, self.with.map_err(op))
339    }
340
341    /// See [`Result::expect`].
342    pub fn expect(self, msg: &str) -> T
343    where
344        E: fmt::Debug,
345    {
346        self.with.expect(msg)
347    }
348
349    /// See [`Result::unwrap`].
350    pub fn unwrap(self) -> T
351    where
352        E: fmt::Debug,
353    {
354        self.with.unwrap()
355    }
356}
357
358impl<O, T, E> Deref for WithResult<O, T, E>
359where
360    E: fmt::Debug,
361{
362    type Target = O;
363
364    fn deref(&self) -> &Self::Target {
365        if let Err(e) = &self.with {
366            panic!("{e:?}");
367        }
368        &self.value
369    }
370}
371
372impl<O, T, E> DerefMut for WithResult<O, T, E>
373where
374    E: fmt::Debug,
375{
376    fn deref_mut(&mut self) -> &mut Self::Target {
377        if let Err(e) = &self.with {
378            panic!("{e:?}");
379        }
380        &mut self.value
381    }
382}
383
384pub fn call_timeout<F>(mut f: F, name: &str, repeat: usize, mut timeout: std::time::Duration)
385where
386    F: FnMut() + Send + 'static,
387{
388    let pair = Arc::new((Mutex::new(false), Condvar::new()));
389    let pair2 = Arc::clone(&pair);
390
391    let _handle = thread::spawn(move || {
392        for _ in 0..repeat {
393            f();
394        }
395
396        let (lock, cvar) = &*pair2;
397        let mut fin = lock.lock().unwrap();
398        *fin = true;
399        cvar.notify_one();
400    });
401
402    let (lock, cvar) = &*pair;
403    let mut fin = lock.lock().unwrap();
404    while !*fin {
405        let start = std::time::Instant::now();
406
407        let res = cvar.wait_timeout(fin, timeout).unwrap();
408        fin = res.0;
409
410        let elapsed = start.elapsed();
411        if let Some(remain) = timeout.checked_sub(elapsed) {
412            timeout = remain;
413        } else {
414            #[cfg(unix)]
415            {
416                use std::os::unix::thread::JoinHandleExt;
417                unsafe { libc::pthread_cancel(_handle.into_pthread_t()) };
418                panic!("timed out: {name}");
419            }
420
421            #[cfg(not(unix))]
422            {
423                eprintln!("timed out: {name}");
424                std::process::exit(101); // Panic result.
425            }
426        }
427    }
428}
429
430#[cfg(test)]
431mod tests {
432    use super::*;
433
434    #[test]
435    fn test_power_of_two() {
436        // Test new method with valid powers of two
437        let v4 = PowerOfTwo::new(4).unwrap();
438        assert_eq!(v4.get(), 4);
439        assert_eq!(v4.quotient(3), 0);
440        assert_eq!(v4.quotient(4), 1);
441        assert_eq!(v4.quotient(5), 1);
442
443        // Test new method with invalid number
444        assert_eq!(PowerOfTwo::new(3), None);
445
446        // Test zero case
447        let v0 = PowerOfTwo::new(0).unwrap();
448        assert_eq!(v0.get(), 0);
449        assert_eq!(v0.quotient(0), 0);
450        assert_eq!(v0.quotient(42), 0);
451        assert_eq!(v0.remainder(0), 0);
452        assert_eq!(v0.remainder(1), 1);
453
454        // Test one case
455        let v1 = PowerOfTwo::new(1).unwrap();
456        assert_eq!(v1.get(), 1);
457        assert_eq!(v1.quotient(3), 3);
458        assert_eq!(v1.quotient(4), 4);
459        assert_eq!(v1.remainder(2), 0);
460    }
461}