typewit/const_marker/
slice_const_markers.rs

1use crate::{
2    all_init_bytes::slice_as_bytes,
3    TypeEq,
4    TypeNe,
5};
6
7
8#[cfg(test)]
9mod tests;
10
11
12super::declare_const_param_type! {
13    /// # Example
14    /// 
15    /// Using this marker type to implement dispatching of fields by name.
16    /// 
17    /// ```rust
18    /// #![feature(adt_const_params)]
19    /// #![feature(unsized_const_params)]
20    /// 
21    /// use typewit::{const_marker::Str, MakeTypeWitness};
22    /// 
23    /// let value = Stuff {
24    ///     foo: 3,
25    ///     bar: "hello",
26    /// };
27    /// 
28    /// assert_eq!(value.get::<"foo">(), &3);
29    /// assert_eq!(value.get::<"bar">(), &"hello");
30    /// 
31    /// pub struct Stuff<'a> {
32    ///     foo: u32,
33    ///     bar: &'a str,
34    /// }
35    /// 
36    /// impl<'a> Stuff<'a> {
37    ///     const fn get<const S: &'static str>(&self) -> &<Self as Field<S>>::Type 
38    ///     where
39    ///         FieldWit<Str<S>>: MakeTypeWitness,
40    ///         Self: Field<S>,
41    ///     {
42    ///         let func = FnFieldTy::<Self>::NEW;
43    /// 
44    ///         match FieldWit::MAKE {
45    ///             FieldWit::Foo(te) => te.map(func).in_ref().to_left(&self.foo),
46    ///             FieldWit::Bar(te) => te.map(func).in_ref().to_left(&self.bar),
47    ///         }
48    ///     }
49    /// }
50    /// 
51    /// typewit::type_fn! {
52    ///     struct FnFieldTy<Struct>;
53    ///  
54    ///     impl<const S: &'static str> Str<S> => <Struct as Field<S>>::Type
55    ///     where Struct: Field<S>
56    /// }
57    /// 
58    /// trait Field<const S: &'static str> {
59    ///     type Type: ?Sized;
60    /// }
61    /// impl<'a> Field<"foo"> for Stuff<'a> {
62    ///     type Type = u32;
63    /// }
64    /// impl<'a> Field<"bar"> for Stuff<'a> {
65    ///     type Type = &'a str;
66    /// }
67    /// 
68    /// typewit::simple_type_witness! {
69    ///     // the #[non_exhaustive] is necessary to be able to add fields to Stuff
70    ///     #[non_exhaustive]
71    ///     pub enum FieldWit {
72    ///         Foo = Str<"foo">,
73    ///         Bar = Str<"bar">,
74    ///     }
75    /// }
76    /// 
77    /// ```
78    #[cfg_attr(feature = "docsrs", doc(cfg(feature = "adt_const_marker")))]
79    Str(&'static str)
80
81    fn equals(l, r) { u8_slice_eq(l.as_bytes(), r.as_bytes()) };
82}
83
84
85super::declare_const_param_type! {
86    StrSlice(&'static [&'static str])
87
88    #[cfg_attr(feature = "docsrs", doc(cfg(feature = "adt_const_marker")))]
89    fn equals(l, r) { str_slice_eq(l, r) };
90}
91
92
93super::declare_const_param_type! {
94    BoolSlice(&'static [bool])
95    fn equals(l, r) { u8_slice_eq(slice_as_bytes(l), slice_as_bytes(r)) };
96}
97super::declare_const_param_type! {
98    CharSlice(&'static [char])
99    fn equals(l, r) { u8_slice_eq(slice_as_bytes(l), slice_as_bytes(r)) };
100}
101super::declare_const_param_type! {
102    U8Slice(&'static [u8])
103    fn equals(l, r) { u8_slice_eq(slice_as_bytes(l), slice_as_bytes(r)) };
104}
105super::declare_const_param_type! {
106    U16Slice(&'static [u16])
107    fn equals(l, r) { u8_slice_eq(slice_as_bytes(l), slice_as_bytes(r)) };
108}
109super::declare_const_param_type! {
110    U32Slice(&'static [u32])
111    fn equals(l, r) { u8_slice_eq(slice_as_bytes(l), slice_as_bytes(r)) };
112}
113super::declare_const_param_type! {
114    U64Slice(&'static [u64])
115    fn equals(l, r) { u8_slice_eq(slice_as_bytes(l), slice_as_bytes(r)) };
116}
117super::declare_const_param_type! {
118    U128Slice(&'static [u128])
119    fn equals(l, r) { u8_slice_eq(slice_as_bytes(l), slice_as_bytes(r)) };
120}
121super::declare_const_param_type! {
122    UsizeSlice(&'static [usize])
123    fn equals(l, r) { u8_slice_eq(slice_as_bytes(l), slice_as_bytes(r)) };
124}
125super::declare_const_param_type! {
126    I8Slice(&'static [i8])
127    fn equals(l, r) { u8_slice_eq(slice_as_bytes(l), slice_as_bytes(r)) };
128}
129super::declare_const_param_type! {
130    I16Slice(&'static [i16])
131    fn equals(l, r) { u8_slice_eq(slice_as_bytes(l), slice_as_bytes(r)) };
132}
133super::declare_const_param_type! {
134    I32Slice(&'static [i32])
135    fn equals(l, r) { u8_slice_eq(slice_as_bytes(l), slice_as_bytes(r)) };
136}
137super::declare_const_param_type! {
138    I64Slice(&'static [i64])
139    fn equals(l, r) { u8_slice_eq(slice_as_bytes(l), slice_as_bytes(r)) };
140}
141super::declare_const_param_type! {
142    I128Slice(&'static [i128])
143    fn equals(l, r) { u8_slice_eq(slice_as_bytes(l), slice_as_bytes(r)) };
144}
145super::declare_const_param_type! {
146    IsizeSlice(&'static [isize])
147    fn equals(l, r) { u8_slice_eq(slice_as_bytes(l), slice_as_bytes(r)) };
148}
149
150macro_rules! cmp_slice_of {
151    ($left:ident, $right:ident, |$l:ident, $r:ident| $eq:expr) => {
152        if $left.len() != $right.len() {
153            false
154        } else {
155            let mut i = 0;
156            loop {
157                if i == $left.len() {
158                    break true;
159                } 
160
161                let $l = &$left[i];
162                let $r = &$right[i];
163                if !$eq {
164                    break false;
165                }
166
167                i += 1;
168            }
169        }
170    }
171}
172
173
174const fn str_slice_eq(left: &[&str], right: &[&str]) -> bool {
175    cmp_slice_of!{left, right, |l, r| u8_slice_eq(l.as_bytes(), r.as_bytes())}
176}
177
178const fn u8_slice_eq(left: &[u8], right: &[u8]) -> bool {
179    cmp_slice_of!{left, right, |l, r| *l == *r}
180}
181