const_panic/
slice_stuff.rs

1use crate::{
2    fmt::{FmtArg, PackedFmtArg, PanicFmt},
3    panic_val::{PanicVal, PanicVariant},
4    utils::Packed,
5    StdWrapper,
6};
7
8macro_rules! impl_panicfmt_array {
9    ($(($variant:ident, $panicval_ctor:ident, $ty:ty)),* $(,)*) => {
10
11        #[derive(Copy, Clone)]
12        #[repr(packed)]
13        pub(crate) struct Slice<'s> {
14            pub(crate) fmtarg: PackedFmtArg,
15            pub(crate) vari: SliceV<'s>,
16        }
17
18        #[repr(u8)]
19        #[derive(Copy, Clone)]
20        pub(crate) enum SliceV<'s> {
21            $(
22                $variant(Packed<&'s [$ty]>),
23            )*
24        }
25
26
27        impl<'s> Slice<'s> {
28            // length in elements
29            pub(crate) const fn arr_len(self) -> usize {
30                match self.vari {
31                    $(
32                        SliceV::$variant(Packed(arr)) => arr.len(),
33                    )*
34                }
35            }
36        }
37
38        impl<'s> SliceV<'s> {
39            const fn get(self, index: usize, fmtarg: FmtArg) -> PanicVal<'s> {
40                match self {
41                    $(
42                        SliceV::$variant(Packed(arr)) => {
43                            let elem: &'s <$ty as PanicFmt>::This = &arr[index];
44                            StdWrapper(elem).to_panicval(fmtarg)
45                        },
46                    )*
47                }
48            }
49        }
50
51        #[cfg_attr(feature = "docsrs", doc(cfg(feature = "non_basic")))]
52        impl<'s> PanicVal<'s> {
53            $(
54                /// Constructs a `PanicVal` from a slice.
55                pub const fn $panicval_ctor(this: &'s [$ty], mut fmtarg: FmtArg) -> PanicVal<'s> {
56                    fmtarg = fmtarg.indent();
57                    if this.is_empty() {
58                        fmtarg = fmtarg.set_alternate(false);
59                    }
60                    PanicVal::__new(
61                        PanicVariant::Slice(Slice{
62                            fmtarg: fmtarg.pack(),
63                            vari: SliceV::$variant(Packed(this)),
64                        })
65                    )
66                }
67            )*
68        }
69
70        $(
71            impl<'s> PanicFmt for [$ty] {
72                type This = Self;
73                type Kind = crate::fmt::IsStdType;
74                const PV_COUNT: usize = 1;
75            }
76            impl<'s, const LEN: usize> PanicFmt for [$ty; LEN] {
77                type This = Self;
78                type Kind = crate::fmt::IsStdType;
79                const PV_COUNT: usize = 1;
80            }
81
82            #[cfg_attr(feature = "docsrs", doc(cfg(feature = "non_basic")))]
83            impl<'s> StdWrapper<&'s [$ty]> {
84                /// Converts the slice to a single-element `PanicVal` array.
85                pub const fn to_panicvals(self: Self, f:FmtArg) -> [PanicVal<'s>;1] {
86                    [PanicVal::$panicval_ctor(self.0, f)]
87                }
88                /// Converts the slice to a `PanicVal`.
89                pub const fn to_panicval(self: Self, f:FmtArg) -> PanicVal<'s> {
90                    PanicVal::$panicval_ctor(self.0, f)
91                }
92            }
93
94            #[cfg_attr(feature = "docsrs", doc(cfg(feature = "non_basic")))]
95            impl<'s, const LEN: usize> StdWrapper<&'s [$ty; LEN]> {
96                /// Converts the array to a single-element `PanicVal` array.
97                pub const fn to_panicvals(self: Self, f:FmtArg) -> [PanicVal<'s>;1] {
98                    [PanicVal::$panicval_ctor(self.0, f)]
99                }
100                /// Converts the array to a `PanicVal`.
101                pub const fn to_panicval(self: Self, f:FmtArg) -> PanicVal<'s> {
102                    PanicVal::$panicval_ctor(self.0, f)
103                }
104            }
105        )*
106
107    };
108}
109
110impl_panicfmt_array! {
111    (U8, from_slice_u8, u8),
112    (U16, from_slice_u16, u16),
113    (U32, from_slice_u32, u32),
114    (U64, from_slice_u64, u64),
115    (U128, from_slice_u128, u128),
116    (Usize, from_slice_usize, usize),
117    (I8, from_slice_i8, i8),
118    (I16, from_slice_i16, i16),
119    (I32, from_slice_i32, i32),
120    (I64, from_slice_i64, i64),
121    (I128, from_slice_i128, i128),
122    (Isize, from_slice_isize, isize),
123    (Bool, from_slice_bool, bool),
124    (Char, from_slice_char, char),
125    (Str, from_slice_str, &'s str),
126}
127
128#[derive(Copy, Clone)]
129pub(crate) struct SliceIter<'s> {
130    slice: SliceV<'s>,
131    fmtarg: FmtArg,
132    state: IterState,
133    arr_len: u32,
134}
135
136#[derive(Copy, Clone, PartialEq, Eq)]
137struct IterState(u32);
138
139#[allow(non_upper_case_globals)]
140impl IterState {
141    const Start: Self = Self(u32::MAX - 1);
142    const End: Self = Self(u32::MAX);
143}
144
145impl<'s> Slice<'s> {
146    pub(crate) const fn iter<'b>(&'b self) -> SliceIter<'s> {
147        SliceIter {
148            slice: self.vari,
149            fmtarg: self.fmtarg.unpack(),
150            state: IterState::Start,
151            arr_len: self.arr_len() as u32,
152        }
153    }
154}
155
156impl<'s> SliceIter<'s> {
157    pub(crate) const fn next(mut self) -> ([PanicVal<'s>; 2], Option<Self>) {
158        let fmtarg = self.fmtarg;
159
160        let ret = match self.state {
161            IterState::Start => {
162                self.state = if self.arr_len == 0 {
163                    IterState::End
164                } else {
165                    IterState(0)
166                };
167
168                [crate::fmt::OpenBracket.to_panicval(fmtarg), PanicVal::EMPTY]
169            }
170            IterState::End => {
171                let close_brace = crate::fmt::CloseBracket.to_panicval(fmtarg.unindent());
172                return ([close_brace, PanicVal::EMPTY], None);
173            }
174            IterState(x) => {
175                let comma = if x + 1 == self.arr_len {
176                    self.state = IterState::End;
177                    crate::fmt::COMMA_TERM
178                } else {
179                    self.state = IterState(x + 1);
180                    crate::fmt::COMMA_SEP
181                }
182                .to_panicval(fmtarg);
183
184                [self.slice.get(x as usize, fmtarg), comma]
185            }
186        };
187
188        (ret, Some(self))
189    }
190}