konst/string/
pattern.rs

1use crate::{
2    chr,
3    polymorphism::{HasTypeWitness, MakeTypeWitness, TypeEq, TypeWitnessTypeArg},
4};
5
6/// A string pattern.
7///
8/// Types that implement this trait can be used to search into a string.
9///
10/// This trait can only be implemented in the `konst` crate.
11///
12pub trait Pattern<'a>: HasTypeWitness<PatternInput<'a, Self>> + Copy + Sized {}
13
14macro_rules! declare_patterns {
15    ($((
16        $variant:ident, $ty:ty, $normalized:ty, $index:expr,
17        |$param:tt| $normalizer:expr
18    ),)*) => (
19        pub struct PatternInput<'a, P: Pattern<'a>>(PatternInputInner<'a, P>);
20
21        enum PatternInputInner<'a, P: Pattern<'a>> {
22            $(
23                $variant {te: TypeEq<P, $ty>},
24            )*
25        }
26
27        impl<'a, Arg> TypeWitnessTypeArg for PatternInput<'a, Arg>
28        where
29            Arg: Pattern<'a>
30        {
31            type Arg = Arg;
32        }
33
34        $(
35            impl<'a> MakeTypeWitness for PatternInput<'a, $ty> {
36                const MAKE: Self =
37                    PatternInput(PatternInputInner::$variant{
38                        te: TypeEq::NEW,
39                    });
40            }
41
42            impl<'a> Pattern<'a> for $ty {}
43        )*
44
45        #[derive(Copy, Clone)]
46        pub(crate) enum PatternNorm<'a, P: Pattern<'a>> {
47            $(
48                $variant{
49                    val: $normalized,
50                    te: TypeEq<P, $ty>,
51                },
52            )*
53        }
54
55        impl<'a, P: Pattern<'a>> PatternNorm<'a, P> {
56            pub(crate) const fn new(pattern: P) -> Self
57            where
58                P: Pattern<'a>
59            {
60                match P::WITNESS.0 {
61                    $(
62                        PatternInputInner::$variant{te} => {
63                            let $param = te.to_right(pattern);
64                            PatternNorm::$variant{val: $normalizer, te}
65                        }
66                    )*
67                }
68            }
69
70            pub(crate) const fn as_str(&self) -> &str {
71                match self {
72                    PatternNorm::Str{val, te} => te.reachability_hint(*val),
73                    PatternNorm::Char{val, te} => te.reachability_hint(val.as_str()),
74                }
75            }
76
77            pub(crate) const fn as_bytes(&self) -> &[u8] {
78                match self {
79                    PatternNorm::Str{val, te} => te.reachability_hint(val.as_bytes()),
80                    PatternNorm::Char{val, te} => te.reachability_hint(val.as_bytes()),
81                }
82            }
83        }
84    )
85}
86
87declare_patterns! {
88    (Str, &'a str, &'a str, 0, |x| x),
89    (Char, char, chr::Utf8Encoded, 1, |char| chr::encode_utf8(char)),
90}