1 | #![allow (clippy::wrong_self_convention)] |
2 | |
3 | use crate::{ |
4 | char_encoding::FmtChar, |
5 | formatting::{Formatting, FormattingFlags}, |
6 | wrapper_types::PWrapper, |
7 | }; |
8 | |
9 | #[doc (hidden)] |
10 | /// The uniform representation for every argument of the concatcp macro. |
11 | pub struct PArgument { |
12 | pub elem: PVariant, |
13 | pub fmt_len: usize, |
14 | pub fmt: Formatting, |
15 | pub fmt_flags: FormattingFlags, |
16 | } |
17 | |
18 | impl PArgument { |
19 | /// Calculates the length of the string after adding up all the PArguments |
20 | pub const fn calc_len(mut args: &[PArgument]) -> usize { |
21 | let mut sum: usize = 0; |
22 | |
23 | while let [curr: &PArgument, rem: &[PArgument] @ ..] = args { |
24 | args = rem; |
25 | sum += curr.fmt_len; |
26 | } |
27 | |
28 | sum |
29 | } |
30 | } |
31 | |
32 | #[doc (hidden)] |
33 | pub enum PVariant { |
34 | Str(&'static str), |
35 | Int(Integer), |
36 | Char(FmtChar), |
37 | } |
38 | |
39 | #[derive (Debug, Copy, Clone)] |
40 | pub struct Integer { |
41 | pub is_negative: bool, |
42 | pub unsigned: u128, |
43 | pub mask: &'static u128, // A mask which disables the bits that weren't in the original number |
44 | } |
45 | |
46 | #[doc (hidden)] |
47 | pub struct PConvWrapper<T>(pub T); |
48 | |
49 | macro_rules! pconvwrapper_impls { |
50 | ( $( ($Signed:ty, $Unsigned:ty) )* ) => ( |
51 | pconvwrapper_impls!{ |
52 | @inner to_pargument_display, compute_display_len, Formatting::Display; |
53 | $(($Signed, $Unsigned))* |
54 | } |
55 | pconvwrapper_impls!{ |
56 | @inner to_pargument_debug, compute_debug_len, Formatting::Debug; |
57 | $(($Signed, $Unsigned))* |
58 | } |
59 | |
60 | $( |
61 | #[doc(hidden)] |
62 | impl PConvWrapper<$Signed>{ |
63 | pub const fn to_integer(self)->Integer{ |
64 | Integer{ |
65 | is_negative: self.0 < 0, |
66 | unsigned: PWrapper(self.0).unsigned_abs() as u128, |
67 | mask: &(((!(0 as $Signed)) as $Unsigned) as u128), |
68 | } |
69 | } |
70 | } |
71 | |
72 | #[doc(hidden)] |
73 | impl PConvWrapper<$Unsigned>{ |
74 | pub const fn to_integer(self)->Integer{ |
75 | Integer{ |
76 | is_negative: false, |
77 | unsigned: self.0 as u128, |
78 | mask: &((!(0 as $Unsigned)) as u128), |
79 | } |
80 | } |
81 | } |
82 | )* |
83 | ); |
84 | (@inner |
85 | $method:ident, |
86 | $called:ident, |
87 | $formatting:expr; |
88 | $( ($Signed:ty, $Unsigned:ty) )* |
89 | ) => ( |
90 | $( |
91 | #[doc(hidden)] |
92 | impl PConvWrapper<$Signed> { |
93 | pub const fn $method(self, fmt_flags: FormattingFlags)->PArgument{ |
94 | PArgument { |
95 | fmt_len: $crate::pmr::PWrapper(self.0).$called(fmt_flags), |
96 | fmt: $formatting, |
97 | fmt_flags, |
98 | elem: PVariant::Int(self.to_integer()), |
99 | } |
100 | } |
101 | } |
102 | |
103 | #[doc(hidden)] |
104 | impl PConvWrapper<$Unsigned> { |
105 | pub const fn $method(self, fmt_flags: FormattingFlags)->PArgument{ |
106 | PArgument { |
107 | fmt_len: $crate::pmr::PWrapper(self.0).$called(fmt_flags), |
108 | fmt: $formatting, |
109 | fmt_flags, |
110 | elem: PVariant::Int(self.to_integer()), |
111 | } |
112 | } |
113 | } |
114 | )* |
115 | ); |
116 | } |
117 | |
118 | pconvwrapper_impls! { |
119 | (i8, u8) |
120 | (i16, u16) |
121 | (i32, u32) |
122 | (i64, u64) |
123 | (i128, u128) |
124 | (isize, usize) |
125 | } |
126 | |
127 | #[doc (hidden)] |
128 | impl PConvWrapper<PArgument> { |
129 | #[inline ] |
130 | pub const fn to_pargument_display(self, _: FormattingFlags) -> PArgument { |
131 | self.0 |
132 | } |
133 | #[inline ] |
134 | pub const fn to_pargument_debug(self, _: FormattingFlags) -> PArgument { |
135 | self.0 |
136 | } |
137 | } |
138 | |
139 | #[doc (hidden)] |
140 | impl PConvWrapper<bool> { |
141 | #[inline ] |
142 | pub const fn to_pargument_display(self, _: FormattingFlags) -> PArgument { |
143 | PConvWrapper(if self.0 { "true" } else { "false" }) |
144 | .to_pargument_display(fmt_flags:FormattingFlags::DEFAULT) |
145 | } |
146 | #[inline ] |
147 | pub const fn to_pargument_debug(self, fmt_flags: FormattingFlags) -> PArgument { |
148 | self.to_pargument_display(fmt_flags) |
149 | } |
150 | } |
151 | |
152 | #[doc (hidden)] |
153 | impl PConvWrapper<char> { |
154 | #[inline ] |
155 | pub const fn to_pargument_display(self, fmt_flags: FormattingFlags) -> PArgument { |
156 | let elem: FmtChar = crate::char_encoding::char_to_display(self.0); |
157 | PArgument { |
158 | fmt_len: elem.len(), |
159 | fmt_flags, |
160 | fmt: Formatting::Display, |
161 | elem: PVariant::Char(elem), |
162 | } |
163 | } |
164 | #[inline ] |
165 | pub const fn to_pargument_debug(self, fmt_flags: FormattingFlags) -> PArgument { |
166 | let elem: FmtChar = crate::char_encoding::char_to_debug(self.0); |
167 | PArgument { |
168 | fmt_len: elem.len(), |
169 | fmt_flags, |
170 | fmt: Formatting::Debug, |
171 | elem: PVariant::Char(elem), |
172 | } |
173 | } |
174 | } |
175 | |
176 | #[doc (hidden)] |
177 | impl PConvWrapper<&'static str> { |
178 | #[inline ] |
179 | pub const fn to_pargument_display(self, fmt_flags: FormattingFlags) -> PArgument { |
180 | PArgument { |
181 | fmt_len: PWrapper(self.0).compute_display_len(fmt_flags), |
182 | fmt_flags, |
183 | fmt: Formatting::Display, |
184 | elem: PVariant::Str(self.0), |
185 | } |
186 | } |
187 | #[inline ] |
188 | pub const fn to_pargument_debug(self, fmt_flags: FormattingFlags) -> PArgument { |
189 | PArgument { |
190 | fmt_len: PWrapper(self.0).compute_debug_len(fmt_flags), |
191 | fmt_flags, |
192 | fmt: Formatting::Debug, |
193 | elem: PVariant::Str(self.0), |
194 | } |
195 | } |
196 | } |
197 | |