ferroui_dynamic_data/cache/internal/
key_value_comparer.rs1use std::any::Any;
4use std::cmp::Ordering;
5use std::fmt;
6use std::hash::{DefaultHasher, Hash, Hasher};
7use std::marker::PhantomData;
8use std::rc::Rc;
9
10pub(crate) type Comparer<T> = Rc<dyn Fn(&T, &T) -> Ordering>;
12
13pub struct KeyValueComparer<T, K> {
17 comparer: Option<Comparer<T>>,
18 _key: PhantomData<fn(&K)>,
19}
20
21impl<T, K> Clone for KeyValueComparer<T, K> {
22 fn clone(&self) -> Self {
23 Self { comparer: self.comparer.clone(), _key: PhantomData }
24 }
25}
26
27impl<T, K> Default for KeyValueComparer<T, K> {
28 fn default() -> Self {
30 Self::new(None)
31 }
32}
33
34impl<T, K> fmt::Debug for KeyValueComparer<T, K> {
35 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36 f.debug_struct("KeyValueComparer").field("has_comparer", &self.comparer.is_some()).finish()
37 }
38}
39
40impl<T, K> KeyValueComparer<T, K> {
41 pub fn new(comparer: Option<Rc<dyn Fn(&T, &T) -> Ordering>>) -> Self {
43 Self { comparer, _key: PhantomData }
44 }
45
46 pub fn item_comparer(&self) -> Option<&Rc<dyn Fn(&T, &T) -> Ordering>> {
48 self.comparer.as_ref()
49 }
50}
51
52impl<T: 'static, K: Hash + 'static> KeyValueComparer<T, K> {
53 pub fn compare(&self, x: &(K, T), y: &(K, T)) -> Ordering {
55 if let Some(comparer) = &self.comparer {
56 let result = comparer(&x.1, &y.1);
57 if result != Ordering::Equal {
58 return result;
59 }
60 }
61 compare_keys(&x.0, &y.0)
62 }
63
64 pub fn to_fn(&self) -> Rc<dyn Fn(&(K, T), &(K, T)) -> Ordering> {
66 let comparer = self.clone();
67 Rc::new(move |x: &(K, T), y: &(K, T)| comparer.compare(x, y))
68 }
69}
70
71pub(crate) fn compare_keys<K: Hash + 'static>(x: &K, y: &K) -> Ordering {
81 macro_rules! compare_as {
82 ($($ty:ty),* $(,)?) => {
83 $(
84 if let (Some(x), Some(y)) = ((x as &dyn Any).downcast_ref::<$ty>(), (y as &dyn Any).downcast_ref::<$ty>()) {
85 return x.cmp(y);
86 }
87 )*
88 };
89 }
90 compare_as!(String, &'static str, Rc<str>, i32, i64, u32, u64, usize, isize, i8, i16, i128, u8, u16, u128, char, bool);
91 hash_code(x).cmp(&hash_code(y))
92}
93
94fn hash_code<K: Hash>(key: &K) -> u64 {
95 let mut hasher = DefaultHasher::new();
96 key.hash(&mut hasher);
97 hasher.finish()
98}