1use crate::{
2 chr,
3 polymorphism::{HasTypeWitness, MakeTypeWitness, TypeEq, TypeWitnessTypeArg},
4};
5
6pub 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}