any_trait/
typeidconst.rs

1//! Internal implementation of a const-comparable TypeId
2//!
3//! You should not be here. go away.
4
5/// TypeId, but const-comparable, sortable
6///
7/// uses `::core::any::type_name::<T>()` underneath
8#[derive(Copy, Clone)]
9pub struct TypeIdConst {
10    // I wanted to use ::core::any::TypeId
11    // turns out I can't because it does not implement Ord
12    // and I can't put it into an union and compare raw bytes, either.
13    s: &'static str,
14}
15
16impl TypeIdConst {
17    pub const fn of<T: ?Sized + 'static>() -> TypeIdConst {
18        return TypeIdConst {
19            s: ::core::any::type_name::<T>(),
20        };
21    }
22    pub const fn cmp(&self, other: Self) -> ::core::cmp::Ordering {
23        let self_bytes = self.s.as_bytes();
24        let other_bytes = other.s.as_bytes();
25        let mut i: usize = 0;
26        while i < self_bytes.len() {
27            if other_bytes.len() < i {
28                return ::core::cmp::Ordering::Greater;
29            }
30            if self_bytes[i] < other_bytes[i] {
31                return ::core::cmp::Ordering::Less;
32            }
33            if self_bytes[i] > other_bytes[i] {
34                return ::core::cmp::Ordering::Greater;
35            }
36            i = i + 1;
37        }
38        if self_bytes.len() > i {
39            return ::core::cmp::Ordering::Less;
40        }
41        return ::core::cmp::Ordering::Equal;
42    }
43}
44impl ::core::cmp::PartialEq for TypeIdConst {
45    fn eq(&self, other: &Self) -> bool {
46        self.cmp(*other).is_eq()
47    }
48}
49impl ::core::cmp::Eq for TypeIdConst {}
50
51impl ::core::cmp::PartialOrd for TypeIdConst {
52    fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> {
53        Some(self.cmp(*other))
54    }
55}
56impl ::core::cmp::Ord for TypeIdConst {
57    fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
58        self.cmp(*other)
59    }
60}
61
62/// const sort with insertionsort.
63pub const fn sort_array<const N: usize>(
64    array: [TypeIdConst; N],
65) -> [TypeIdConst; N] {
66    // come and tell me this is not performant
67    // and I'll implement random_sort
68    // joking, but I'm not wasting time on this
69    let mut i: usize = 0;
70    let mut j: usize = 0;
71    let mut out: [TypeIdConst; N] = array;
72    while i < N {
73        let mut min: usize = i;
74        while j < N {
75            if array[j].cmp(array[i]).is_lt() {
76                min = j;
77            }
78            j = j + 1
79        }
80        if min != i {
81            let old = out[i];
82            out[i] = out[j];
83            out[j] = old;
84        }
85        i = i + 1;
86    }
87    out
88}
89
90/// get `[TypeIdConst;N]` in input and return `[TypeIdConst;N + 2]`
91///
92/// we add the first two elements, and they always are:
93/// * `TypeIdConst::of::<dyn AnyTrait>`
94/// * `TypeIdConst::of::<T>`
95pub const fn append_array<T: 'static, const N: usize, const M: usize>(
96    array: [TypeIdConst; N],
97) -> [TypeIdConst; M] {
98    assert!(N + 2 == M, "M needs to be N + 2");
99    let mut out: [TypeIdConst; M] = [TypeIdConst::of::<T>(); M];
100    out[0] = TypeIdConst::of::<dyn super::AnyTrait>();
101    let mut i: usize = 2;
102    while i < M {
103        out[i] = array[i - 2];
104        i = i + 1;
105    }
106
107    out
108}
109
110/// const-find the `TypeIdConst` of `T` inside the given array.
111/// return its index or panic
112pub const fn find_in<T: ?Sized + 'static, const N: usize>(
113    array: [TypeIdConst; N],
114) -> usize {
115    let mut i: usize = 0;
116    while i < N {
117        if array[i].cmp(TypeIdConst::of::<T>()).is_eq() {
118            return i;
119        }
120        i = i + 1;
121    }
122    panic!("TypeIDConst find_in: called with non-member");
123}