1use proc_macro2::TokenStream;
2use quote::{format_ident, quote, ToTokens};
3use syn::parse_quote;
4
5use crate::{
6 common_impl::{
7 define_guard, impl_binary_op, impl_conversions, impl_deref, impl_other_compare,
8 impl_other_eq, impl_self_cmp, impl_self_eq,
9 },
10 params::{NumberValueRange, Params},
11};
12
13pub fn define_mod(params: &Params, ranges: &Vec<NumberValueRange>) -> syn::Result<TokenStream> {
14 let integer = ¶ms.integer;
15
16 let vis = ¶ms.vis;
17 let ident = ¶ms.ident;
18 let mod_ident = params.mod_ident();
19
20 let implementations = TokenStream::from_iter(vec![
21 impl_deref(ident, params),
22 impl_conversions(ident, params),
23 impl_self_eq(ident),
24 impl_self_cmp(ident),
25 impl_other_eq(ident, params),
26 impl_other_compare(ident, params),
27 impl_binary_op(
28 ident,
29 params,
30 format_ident!("Add"),
31 format_ident!("add"),
32 ¶ms.behavior,
33 None,
34 ),
35 impl_binary_op(
36 ident,
37 params,
38 format_ident!("Sub"),
39 format_ident!("sub"),
40 ¶ms.behavior,
41 None,
42 ),
43 impl_binary_op(
44 ident,
45 params,
46 format_ident!("Mul"),
47 format_ident!("mul"),
48 ¶ms.behavior,
49 None,
50 ),
51 impl_binary_op(
52 ident,
53 params,
54 format_ident!("Div"),
55 format_ident!("div"),
56 ¶ms.behavior,
57 None,
58 ),
59 impl_binary_op(
60 ident,
61 params,
62 format_ident!("Rem"),
63 format_ident!("rem"),
64 ¶ms.behavior,
65 None,
66 ),
67 impl_binary_op(
68 ident,
69 params,
70 format_ident!("BitAnd"),
71 format_ident!("bitand"),
72 ¶ms.behavior,
73 None,
74 ),
75 impl_binary_op(
76 ident,
77 params,
78 format_ident!("BitOr"),
79 format_ident!("bitor"),
80 ¶ms.behavior,
81 None,
82 ),
83 impl_binary_op(
84 ident,
85 params,
86 format_ident!("BitXor"),
87 format_ident!("bitxor"),
88 ¶ms.behavior,
89 None,
90 ),
91 ]);
92
93 let behavior = ¶ms.behavior;
94 let lower_limit = params.lower_limit_token();
95 let upper_limit = params.upper_limit_token();
96 let default_val = params.default_val_token();
97
98 let guard_ident = params.guard_ident();
99 let def_guard = define_guard(ident, &guard_ident, params);
100
101 let mut traits = params
102 .derived_traits
103 .as_ref()
104 .map(|x| {
105 let mut traits = Vec::with_capacity(x.traits.len());
106
107 traits.extend(
108 x.traits
109 .iter()
110 .filter(|ty| {
111 let ty = ty
112 .path
113 .segments
114 .last()
115 .unwrap()
116 .to_token_stream()
117 .to_string();
118
119 match ty.as_str() {
120 "Clone" | "Copy" => false,
121 _ => true,
122 }
123 })
124 .cloned(),
125 );
126
127 traits
128 })
129 .unwrap_or(Vec::with_capacity(2));
130
131 traits.extend(vec![parse_quote!(Clone), parse_quote!(Copy)]);
132
133 let clamp_trait_impl = {
134 let mut valid_ranges = Vec::with_capacity(ranges.len());
135
136 for value_range in ranges {
137 let first_val = value_range.first_val();
138 let last_val = value_range.last_val();
139
140 valid_ranges.push(quote! {
141 ValueRangeInclusive(#first_val..=#last_val),
142 });
143 }
144
145 quote! {
146 unsafe impl RangeValues<#integer> for #ident {
147 const VALID_RANGES: &'static [ValueRangeInclusive<#integer>] = &[
148 #(#valid_ranges)*
149 ];
150 }
151
152 unsafe impl HardClamp<#integer> for #ident {}
153 }
154 };
155
156 Ok(quote! {
157 #vis mod #mod_ident {
158 use super::*;
159
160 #[derive(#(#traits),*)]
161 pub struct #ident(#integer);
162
163 impl #ident {
164 #[inline(always)]
166 pub fn new(val: #integer) -> Option<Self> {
167 match #ident::validate(val) {
168 Ok(v) => Some(Self(v)),
169 Err(..) => None,
170 }
171 }
172
173 #[inline(always)]
174 pub const unsafe fn new_unchecked(val: #integer) -> Self {
175 Self(val)
176 }
177
178 #[inline(always)]
179 pub(self) fn op_behavior_params(&self) -> OpBehaviorParams<#integer> {
180 let ranges = <#ident as RangeValues<#integer>>::VALID_RANGES;
181
182 if ranges.len() == 1 {
183 let range = &ranges[0];
184
185 OpBehaviorParams::Simple {
186 min: range.first_val(),
187 max: range.last_val(),
188 }
189 } else {
190 let min = ranges.first().unwrap().first_val();
191 let max = ranges.last().unwrap().last_val();
192
193 OpBehaviorParams::RangesOnly(ranges)
194 }
195 }
196
197 #[inline(always)]
198 pub fn rand() -> Self {
199 loop {
200 if let Ok(v) = Self::from_primitive(rand::random::<#integer>()) {
201 return v;
202 }
203 }
204 }
205
206 #[inline(always)]
207 pub fn validate(val: #integer) -> ::anyhow::Result<#integer, ClampError<#integer>> {
208 let ranges = <#ident as RangeValues<#integer>>::VALID_RANGES;
209
210 if ranges.len() == 1 {
211 let range = &ranges[0];
212 let min = range.first_val();
213 let max = range.last_val();
214
215 if val < min {
216 Err(ClampError::TooSmall { val, min })
217 } else if val > max {
218 Err(ClampError::TooLarge { val, max })
219 } else {
220 Ok(val)
221 }
222 } else {
223 for (i, range) in ranges.iter().enumerate() {
224 if range.contains(val) {
225 return Ok(val);
226 }
227
228 let min = range.first_val();
229
230 if i == 0 && val < min {
231 return Err(ClampError::TooSmall { val, min });
232 }
233
234 if i == ranges.len() - 1 {
235 let max = range.last_val();
236 return Err(ClampError::TooLarge { val, max });
237 }
238
239 let left_range = range;
240 let right_range = &ranges[i + 1];
241
242 let left_max = left_range.last_val();
243 let right_min = right_range.first_val();
244
245 if val > left_max && val < right_min {
246 return Err(ClampError::OutOfBounds {
247 val,
248 left_min: left_range.first_val(),
249 left_max,
250 right_min,
251 right_max: right_range.last_val(),
252 });
253 }
254 }
255
256 unreachable!("all error cases should be covered by loop");
257 }
258 }
259
260 #[inline(always)]
261 pub fn set(&mut self, value: #integer) -> ::anyhow::Result<(), ClampError<#integer>> {
262 self.0 = Self::validate(value)?;
263 Ok(())
264 }
265
266 #[inline(always)]
267 pub unsafe fn set_unchecked(&mut self, value: #integer) {
268 self.0 = value;
269 }
270
271 #[inline(always)]
272 pub fn get(&self) -> &#integer {
273 &self.0
274 }
275
276 #[inline(always)]
277 pub unsafe fn get_mut(&mut self) -> &mut #integer {
278 &mut self.0
279 }
280
281 #[inline(always)]
282 pub fn modify<'a>(&'a mut self) -> #guard_ident<'a> {
283 #guard_ident::new(self)
284 }
285 }
286
287 impl InherentLimits<#integer> for #ident {
288 const MIN_INT: #integer = #lower_limit;
289 const MAX_INT: #integer = #upper_limit;
290 const MIN: Self = Self(Self::MIN_INT);
291 const MAX: Self = Self(Self::MAX_INT);
292
293 #[inline(always)]
294 fn is_zero(&self) -> bool {
295 self.0 == 0
296 }
297
298 #[inline(always)]
299 fn is_negative(&self) -> bool {
300 self.0 < 0
301 }
302
303 #[inline(always)]
304 fn is_positive(&self) -> bool {
305 self.0 > 0
306 }
307 }
308
309 impl InherentBehavior for #ident {
310 type Behavior = #behavior;
311 }
312
313 unsafe impl ClampedInteger<#integer> for #ident {
314 #[inline(always)]
315 fn from_primitive(n: #integer) -> ::anyhow::Result<Self> {
316 Ok(Self(Self::validate(n)?))
317 }
318
319 #[inline(always)]
320 fn as_primitive(&self) -> &#integer {
321 &self.0
322 }
323 }
324
325 #clamp_trait_impl
326
327 impl Default for #ident {
328 #[inline(always)]
329 fn default() -> Self {
330 Self(#default_val)
331 }
332 }
333
334 #implementations
335
336 #def_guard
337 }
338
339 #vis use #mod_ident::#ident;
340 })
341}