konst/slice/
bytes_pattern.rs

1use crate::{
2    chr,
3    polymorphism::{HasTypeWitness, MakeTypeWitness, TypeEq, TypeWitnessTypeArg},
4};
5
6/// A byte slice pattern.
7///
8/// Types that implement this trait can be used to search into a byte slice.
9///
10/// This trait can only be implemented in the `konst` crate.
11///
12pub trait BytesPattern<const N: usize>: HasTypeWitness<BytesPatternInput<N, Self>> {
13    #[doc(hidden)]
14    type __Normalized: ?Sized;
15}
16
17#[non_exhaustive]
18pub enum BytesPatternInput<const N: usize, P: ?Sized + BytesPattern<N>> {
19    Str(TypeEq<P, str>, TypeEq<*const P::__Normalized, *const [u8]>),
20    Bytes(TypeEq<P, [u8]>, TypeEq<*const P::__Normalized, *const [u8]>),
21    Array(
22        TypeEq<P, [u8; N]>,
23        TypeEq<*const P::__Normalized, *const [u8]>,
24    ),
25    Char(
26        TypeEq<P, char>,
27        TypeEq<*const P::__Normalized, *const chr::Utf8Encoded>,
28    ),
29}
30
31impl<const N: usize, Arg> TypeWitnessTypeArg for BytesPatternInput<N, Arg>
32where
33    Arg: ?Sized + BytesPattern<N>,
34{
35    type Arg = Arg;
36}
37
38impl MakeTypeWitness for BytesPatternInput<0, str> {
39    const MAKE: Self = BytesPatternInput::Str(TypeEq::NEW, TypeEq::NEW);
40}
41impl BytesPattern<0> for str {
42    #[doc(hidden)]
43    type __Normalized = [u8];
44}
45
46impl MakeTypeWitness for BytesPatternInput<0, [u8]> {
47    const MAKE: Self = BytesPatternInput::Bytes(TypeEq::NEW, TypeEq::NEW);
48}
49impl BytesPattern<0> for [u8] {
50    #[doc(hidden)]
51    type __Normalized = [u8];
52}
53
54impl<const N: usize> MakeTypeWitness for BytesPatternInput<N, [u8; N]> {
55    const MAKE: Self = BytesPatternInput::Array(TypeEq::NEW, TypeEq::NEW);
56}
57impl<const N: usize> BytesPattern<N> for [u8; N] {
58    #[doc(hidden)]
59    type __Normalized = [u8];
60}
61
62impl MakeTypeWitness for BytesPatternInput<0, char> {
63    const MAKE: Self = BytesPatternInput::Char(TypeEq::NEW, TypeEq::NEW);
64}
65impl BytesPattern<0> for char {
66    #[doc(hidden)]
67    type __Normalized = chr::Utf8Encoded;
68}
69
70#[derive(Copy, Clone)]
71pub(crate) enum PatternNorm<'a, const N: usize, P>
72where
73    P: ?Sized + BytesPattern<N>,
74{
75    Bytes {
76        val: &'a [u8],
77        ten: TypeEq<*const P::__Normalized, *const [u8]>,
78    },
79    Char {
80        val: chr::Utf8Encoded,
81        ten: TypeEq<*const P::__Normalized, *const chr::Utf8Encoded>,
82    },
83}
84
85impl<'a, const N: usize, P> PatternNorm<'a, N, P>
86where
87    P: ?Sized + BytesPattern<N>,
88{
89    pub(crate) const fn new(pattern: &'a P) -> Self {
90        match P::WITNESS {
91            BytesPatternInput::Str(te, ten) => {
92                let val: &'a [u8] = te.in_ref().to_right(pattern).as_bytes();
93                PatternNorm::Bytes { val, ten }
94            }
95            BytesPatternInput::Bytes(te, ten) => {
96                let val: &'a [u8] = te.in_ref().to_right(pattern);
97                PatternNorm::Bytes { val, ten }
98            }
99            BytesPatternInput::Array(te, ten) => {
100                let val: &'a [u8] = te.in_ref().to_right(pattern);
101                PatternNorm::Bytes { val, ten }
102            }
103            BytesPatternInput::Char(te, ten) => {
104                let val: &'a char = te.in_ref().to_right(pattern);
105                let val = chr::encode_utf8(*val);
106                PatternNorm::Char { val, ten }
107            }
108        }
109    }
110
111    pub(crate) const fn as_bytes(&self) -> &[u8] {
112        match self {
113            PatternNorm::Bytes { val, ten } => ten.reachability_hint(val),
114            PatternNorm::Char { val, ten } => ten.reachability_hint(val.as_bytes()),
115        }
116    }
117}