1pub(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
22pub trait TakeRecur {
63 type Inner;
64
65 fn take_recur(self) -> Self::Inner;
71}
72
73macro_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#[derive(Debug, Clone, Copy)]
96pub struct PowerOfTwo {
97 value: usize,
98 k: u32,
99 mask: usize,
100}
101
102impl PowerOfTwo {
103 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 pub const fn get(&self) -> usize {
124 self.value
125 }
126
127 pub const fn quotient(&self, numerator: usize) -> usize {
140 (numerator >> self.k) & self.mask
141 }
142
143 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 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 self.value.cmp(&other.value)
181 }
182}
183
184impl hash::Hash for PowerOfTwo {
185 fn hash<H: hash::Hasher>(&self, state: &mut H) {
186 self.value.hash(state);
189 }
190}
191
192#[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 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 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 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#[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 pub const fn new(value: T, with: U) -> Self {
269 Self { value, with }
270 }
271}
272
273pub type WithResult<O, T, E> = With<O, Result<T, E>>;
278
279impl<O, T, E> WithResult<O, T, E> {
280 pub fn take(self) -> Result<T, E> {
282 self.with
283 }
284
285 pub const fn is_ok(&self) -> bool {
287 self.with.is_ok()
288 }
289
290 pub fn is_ok_and(self, f: impl FnOnce(T) -> bool) -> bool {
292 self.with.is_ok_and(f)
293 }
294
295 pub const fn is_err(&self) -> bool {
297 self.with.is_err()
298 }
299
300 pub fn is_err_and(self, f: impl FnOnce(E) -> bool) -> bool {
302 self.with.is_err_and(f)
303 }
304
305 pub fn ok(self) -> Option<T> {
307 self.with.ok()
308 }
309
310 pub fn err(self) -> Option<E> {
312 self.with.err()
313 }
314
315 pub const fn as_ref(&self) -> Result<&T, &E> {
317 self.with.as_ref()
318 }
319
320 pub fn as_mut(&mut self) -> Result<&mut T, &mut E> {
322 self.with.as_mut()
323 }
324
325 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 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 pub fn expect(self, msg: &str) -> T
343 where
344 E: fmt::Debug,
345 {
346 self.with.expect(msg)
347 }
348
349 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); }
426 }
427 }
428}
429
430#[cfg(test)]
431mod tests {
432 use super::*;
433
434 #[test]
435 fn test_power_of_two() {
436 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 assert_eq!(PowerOfTwo::new(3), None);
445
446 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 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}