1pub mod fat;
4
5#[macro_use]
6mod macros;
7mod bitset;
8mod deferred;
9mod duration;
10mod hash;
11mod pico;
12mod round;
13mod scalar;
14
15pub use self::bitset::{BitSet, SmallBitSet};
16pub use self::deferred::Deferred;
17pub use self::duration::format_duration;
18pub use self::hash::{LazyHash, ManuallyHash};
19pub use self::pico::{PicoStr, ResolvedPicoStr};
20pub use self::round::{round_int_with_precision, round_with_precision};
21pub use self::scalar::Scalar;
22
23#[doc(hidden)]
24pub use once_cell;
25
26use std::fmt::{Debug, Formatter};
27use std::hash::Hash;
28use std::iter::{Chain, Flatten, Rev};
29use std::num::NonZeroUsize;
30use std::ops::{Add, Deref, Div, Mul, Neg, Sub};
31use std::sync::Arc;
32
33use siphasher::sip128::{Hasher128, SipHasher13};
34use unicode_math_class::MathClass;
35
36pub fn debug<F>(f: F) -> impl Debug
38where
39 F: Fn(&mut Formatter) -> std::fmt::Result,
40{
41 struct Wrapper<F>(F);
42
43 impl<F> Debug for Wrapper<F>
44 where
45 F: Fn(&mut Formatter) -> std::fmt::Result,
46 {
47 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
48 self.0(f)
49 }
50 }
51
52 Wrapper(f)
53}
54
55pub fn hash128<T: Hash + ?Sized>(value: &T) -> u128 {
57 let mut state = SipHasher13::new();
58 value.hash(&mut state);
59 state.finish128().as_u128()
60}
61
62pub trait NonZeroExt {
64 const ONE: Self;
66}
67
68impl NonZeroExt for NonZeroUsize {
69 const ONE: Self = match Self::new(1) {
70 Some(v) => v,
71 None => unreachable!(),
72 };
73}
74
75pub trait ArcExt<T> {
77 fn take(self) -> T;
80}
81
82impl<T: Clone> ArcExt<T> for Arc<T> {
83 fn take(self) -> T {
84 match Arc::try_unwrap(self) {
85 Ok(v) => v,
86 Err(rc) => (*rc).clone(),
87 }
88 }
89}
90
91pub trait OptionExt<T> {
93 fn map_or_default<U: Default, F>(self, f: F) -> U
96 where
97 F: FnOnce(T) -> U;
98}
99
100impl<T> OptionExt<T> for Option<T> {
101 fn map_or_default<U: Default, F>(self, f: F) -> U
102 where
103 F: FnOnce(T) -> U,
104 {
105 match self {
106 Some(x) => f(x),
107 None => U::default(),
108 }
109 }
110}
111
112pub trait SliceExt<T> {
114 fn trim_start_matches<F>(&self, f: F) -> &[T]
117 where
118 F: FnMut(&T) -> bool;
119
120 fn trim_end_matches<F>(&self, f: F) -> &[T]
123 where
124 F: FnMut(&T) -> bool;
125
126 fn group_by_key<K, F>(&self, f: F) -> GroupByKey<'_, T, F>
129 where
130 F: FnMut(&T) -> K,
131 K: PartialEq;
132
133 fn split_prefix_suffix<F>(&self, f: F) -> (usize, usize)
144 where
145 F: FnMut(&T) -> bool;
146}
147
148impl<T> SliceExt<T> for [T] {
149 fn trim_start_matches<F>(&self, mut f: F) -> &[T]
150 where
151 F: FnMut(&T) -> bool,
152 {
153 let len = self.len();
154 let mut i = 0;
155 while i < len && f(&self[i]) {
156 i += 1;
157 }
158 &self[i..]
159 }
160
161 fn trim_end_matches<F>(&self, mut f: F) -> &[T]
162 where
163 F: FnMut(&T) -> bool,
164 {
165 let mut i = self.len();
166 while i > 0 && f(&self[i - 1]) {
167 i -= 1;
168 }
169 &self[..i]
170 }
171
172 fn group_by_key<K, F>(&self, f: F) -> GroupByKey<'_, T, F> {
173 GroupByKey { slice: self, f }
174 }
175
176 fn split_prefix_suffix<F>(&self, mut f: F) -> (usize, usize)
177 where
178 F: FnMut(&T) -> bool,
179 {
180 let start = self.iter().position(|v| !f(v)).unwrap_or(self.len());
181 let end = self
182 .iter()
183 .skip(start)
184 .rposition(|v| !f(v))
185 .map_or(start, |i| start + i + 1);
186 (start, end)
187 }
188}
189
190pub struct GroupByKey<'a, T, F> {
192 slice: &'a [T],
193 f: F,
194}
195
196impl<'a, T, K, F> Iterator for GroupByKey<'a, T, F>
197where
198 F: FnMut(&T) -> K,
199 K: PartialEq,
200{
201 type Item = (K, &'a [T]);
202
203 fn next(&mut self) -> Option<Self::Item> {
204 let mut iter = self.slice.iter();
205 let key = (self.f)(iter.next()?);
206 let count = 1 + iter.take_while(|t| (self.f)(t) == key).count();
207 let (head, tail) = self.slice.split_at(count);
208 self.slice = tail;
209 Some((key, head))
210 }
211}
212
213pub trait MaybeReverseIter {
215 type RevIfIter;
216
217 fn rev_if(self, condition: bool) -> Self::RevIfIter
219 where
220 Self: Sized;
221}
222
223impl<I: Iterator + DoubleEndedIterator> MaybeReverseIter for I {
224 type RevIfIter =
225 Chain<Flatten<std::option::IntoIter<I>>, Flatten<std::option::IntoIter<Rev<I>>>>;
226
227 fn rev_if(self, condition: bool) -> Self::RevIfIter
228 where
229 Self: Sized,
230 {
231 let (maybe_self_iter, maybe_rev_iter) =
232 if condition { (None, Some(self.rev())) } else { (Some(self), None) };
233
234 maybe_self_iter
235 .into_iter()
236 .flatten()
237 .chain(maybe_rev_iter.into_iter().flatten())
238 }
239}
240
241pub fn option_eq<L, R>(left: Option<L>, other: R) -> bool
243where
244 L: PartialEq<R>,
245{
246 left.is_some_and(|v| v == other)
247}
248
249#[derive(Debug)]
251pub struct Static<T: 'static>(pub &'static T);
252
253impl<T> Deref for Static<T> {
254 type Target = T;
255
256 fn deref(&self) -> &Self::Target {
257 self.0
258 }
259}
260
261impl<T> Copy for Static<T> {}
262
263impl<T> Clone for Static<T> {
264 fn clone(&self) -> Self {
265 *self
266 }
267}
268
269impl<T> Eq for Static<T> {}
270
271impl<T> PartialEq for Static<T> {
272 fn eq(&self, other: &Self) -> bool {
273 std::ptr::eq(self.0, other.0)
274 }
275}
276
277impl<T> Hash for Static<T> {
278 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
279 state.write_usize(self.0 as *const _ as _);
280 }
281}
282
283pub trait Get<Index> {
285 type Component;
287
288 fn get_ref(&self, index: Index) -> &Self::Component;
290
291 fn get_mut(&mut self, index: Index) -> &mut Self::Component;
293
294 fn get(self, index: Index) -> Self::Component
296 where
297 Self: Sized,
298 Self::Component: Copy,
299 {
300 *self.get_ref(index)
301 }
302
303 fn set(&mut self, index: Index, component: Self::Component) {
305 *self.get_mut(index) = component;
306 }
307
308 fn with(mut self, index: Index, component: Self::Component) -> Self
310 where
311 Self: Sized,
312 {
313 self.set(index, component);
314 self
315 }
316}
317
318pub trait Numeric:
320 Sized
321 + Debug
322 + Copy
323 + PartialEq
324 + Neg<Output = Self>
325 + Add<Output = Self>
326 + Sub<Output = Self>
327 + Mul<f64, Output = Self>
328 + Div<f64, Output = Self>
329{
330 fn zero() -> Self;
332
333 fn is_zero(self) -> bool {
335 self == Self::zero()
336 }
337
338 fn is_finite(self) -> bool;
340}
341
342pub fn default_math_class(c: char) -> Option<MathClass> {
346 match c {
347 ':' => Some(MathClass::Relation),
350
351 '⋯' | '⋱' | '⋰' | '⋮' => Some(MathClass::Normal),
354
355 '.' | '/' => Some(MathClass::Normal),
358
359 '\u{22A5}' => Some(MathClass::Normal),
362
363 c => unicode_math_class::class(c),
364 }
365}