1use std::collections::HashSet;
2
3use convert_case::{Case, Casing};
4use proc_macro2::{Span, TokenStream};
5use quote::{format_ident, quote, ToTokens};
6use syn::parse_quote;
7
8use crate::{
9 common_impl::{
10 define_guard, impl_binary_op, impl_conversions, impl_deref, impl_other_compare,
11 impl_other_eq, impl_self_cmp, impl_self_eq,
12 },
13 hard_impl,
14 item::enum_item::{ClampedEnumItem, ClampedEnumVariant, ClampedEnumVariantField},
15 params::{DerivedTraits, NumberArg, NumberKind, NumberValue, Params},
16 range_seq::RangeSeq,
17};
18
19pub fn define_mod(
20 params: &Params,
21 parsed_variants: &syn::punctuated::Punctuated<ClampedEnumVariant, syn::Token![,]>,
22) -> syn::Result<TokenStream> {
23 let kind = params.integer;
24 let integer = ¶ms.integer;
25 let behavior = ¶ms.behavior;
26
27 let vis = ¶ms.vis;
28 let ident = ¶ms.ident;
29 let mod_ident = params.mod_ident();
30 let value_ident = params.value_ident();
31
32 let implementations = TokenStream::from_iter(vec![
33 impl_deref(ident, params),
34 impl_conversions(ident, params),
35 impl_self_eq(ident),
36 impl_self_cmp(ident),
37 impl_other_eq(ident, params),
38 impl_other_compare(ident, params),
39 impl_binary_op(
40 ident,
41 params,
42 format_ident!("Add"),
43 format_ident!("add"),
44 behavior,
45 None,
46 ),
47 impl_binary_op(
48 ident,
49 params,
50 format_ident!("Sub"),
51 format_ident!("sub"),
52 behavior,
53 None,
54 ),
55 impl_binary_op(
56 ident,
57 params,
58 format_ident!("Mul"),
59 format_ident!("mul"),
60 behavior,
61 None,
62 ),
63 impl_binary_op(
64 ident,
65 params,
66 format_ident!("Div"),
67 format_ident!("div"),
68 behavior,
69 None,
70 ),
71 impl_binary_op(
72 ident,
73 params,
74 format_ident!("Rem"),
75 format_ident!("rem"),
76 behavior,
77 None,
78 ),
79 impl_binary_op(
80 ident,
81 params,
82 format_ident!("BitAnd"),
83 format_ident!("bitand"),
84 behavior,
85 None,
86 ),
87 impl_binary_op(
88 ident,
89 params,
90 format_ident!("BitOr"),
91 format_ident!("bitor"),
92 behavior,
93 None,
94 ),
95 impl_binary_op(
96 ident,
97 params,
98 format_ident!("BitXor"),
99 format_ident!("bitxor"),
100 behavior,
101 None,
102 ),
103 ]);
104
105 let mut exact_items = Vec::with_capacity(parsed_variants.len());
106 let mut range_items = Vec::with_capacity(parsed_variants.len());
107 let mut nested_enum_items = Vec::with_capacity(parsed_variants.len());
108 let mut from_nested_enum_impls = Vec::with_capacity(parsed_variants.len());
109
110 let mut variants = Vec::with_capacity(parsed_variants.len());
111
112 let mut factory_methods = Vec::with_capacity(parsed_variants.len());
113 let mut matches_methods = Vec::with_capacity(parsed_variants.len());
114 let mut from_exact_cases = Vec::with_capacity(parsed_variants.len());
115 let mut from_range_cases = Vec::with_capacity(parsed_variants.len());
116 let mut from_nested_cases = Vec::with_capacity(parsed_variants.len());
117 let mut as_primitive_cases = Vec::with_capacity(parsed_variants.len());
118
119 let mut has_catchall = false;
120
121 for variant in parsed_variants.iter() {
122 let variant_ident = &variant.ident;
123 let variant_as_snake_case = variant_ident.to_string().to_case(Case::Snake);
124
125 let default_val = variant.default_val.as_ref();
126
127 match &variant.field {
128 ClampedEnumVariantField::Values { values, .. } => {
129 let other_ident = params.other_ident(variant_ident);
130 let literal_values = values
131 .iter()
132 .map(|arg| arg.into_literal_as_tokens(kind))
133 .collect::<Vec<_>>();
134
135 let default_impl = if let Some(default_val) = default_val {
136 quote! {
137 impl Default for #value_ident<#other_ident> {
138 #[inline(always)]
139 fn default() -> Self {
140 Self::new(#default_val).unwrap()
141 }
142 }
143 }
144 } else {
145 TokenStream::new()
146 };
147
148 exact_items.push(quote! {
149 #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize)]
150 pub struct #other_ident;
151
152 unsafe impl ExactValues<#integer> for #other_ident {
153 const VALUES: &'static [#integer] = &[
154 #(#literal_values),*
155 ];
156 }
157
158 #default_impl
159 });
160
161 variants.push(quote! {
162 #variant_ident(#value_ident<#other_ident>),
163 });
164
165 let factory_ident = format_ident!("new_{}", &variant_as_snake_case);
166
167 if values.len() == 1 {
168 let val = &values[0];
169
170 factory_methods.push(quote! {
171 #[inline(always)]
172 pub fn #factory_ident() -> Self {
173 #ident::#variant_ident(#value_ident::from_primitive(#val).unwrap())
174 }
175 });
176 } else {
177 factory_methods.push(quote! {
178 #[inline(always)]
179 pub fn #factory_ident(val: #integer) -> anyhow::Result<Self> {
180 Ok(#ident::#variant_ident(#value_ident::from_primitive(val)?))
181 }
182 });
183 }
184
185 let matches_method_ident = format_ident!("is_{}", &variant_as_snake_case);
186
187 matches_methods.push(quote! {
188 #[inline(always)]
189 pub fn #matches_method_ident(&self) -> bool {
190 matches!(self, #ident::#variant_ident(_))
191 }
192 });
193
194 from_exact_cases.push(quote! {
195 #(#literal_values)|* => #ident::#variant_ident(#value_ident(val, std::marker::PhantomData)),
196 });
197
198 as_primitive_cases.push(quote! {
199 #ident::#variant_ident(val) => val.as_primitive(),
200 });
201 }
202 ClampedEnumVariantField::Ranges { values, .. } => {
203 let kind = *integer;
204 let other_ident = params.other_ident(variant_ident);
205
206 let variant_limits = variant.field.limits(kind, None, None)?;
207
208 let lower_limit_val = variant_limits.first_val(kind);
209 let upper_limit_val = variant_limits.last_val(kind);
210
211 let mut literal_args = Vec::with_capacity(values.len());
212 let mut range_seq = RangeSeq::with_capacity(kind, values.len());
213 let mut is_catchall = false;
214
215 if values.len() == 1 {
216 let range = &values[0];
217
218 if range.is_full_range() {
219 is_catchall = true;
220 has_catchall = true;
221 }
222
223 let range = range.to_value_range(kind)?;
224
225 literal_args.push(range.clone());
226 range_seq.insert(range)?;
227 } else {
228 for range in values {
229 if range.is_full_range() {
230 return Err(syn::Error::new(
231 Span::call_site(),
232 "Cannot have a catch-all range in a range that contains other ranges",
233 ));
234 }
235
236 let range = range.to_value_range(kind)?;
237
238 literal_args.push(range.clone());
239 range_seq.insert(range)?;
240 }
241 }
242
243 range_items.push(hard_impl::define_mod(
244 &Params {
245 integer: kind,
246 derived_traits: params.derived_traits.clone(),
247 vis: parse_quote!(pub),
248 ident: other_ident.clone(),
249 as_soft_or_hard: Some(parse_quote!(as Hard)),
250 default_val: default_val.map(|arg| arg.into_value(kind)),
251 behavior: behavior.clone(),
252 lower_limit_val,
253 upper_limit_val,
254 full_coverage: !range_seq.has_gaps(),
255 exact_values: None,
256 valid_ranges: Some(range_seq.uniq_ranges()),
257 },
258 &range_seq
259 .all_ranges()
260 .into_iter()
261 .map(|range| range.into())
262 .collect(),
263 )?);
264
265 variants.push(quote! {
266 #variant_ident(#other_ident),
267 });
268
269 let factory_ident = format_ident!("new_{}", &variant_as_snake_case);
270
271 factory_methods.push(quote! {
272 #[inline(always)]
273 pub fn #factory_ident(val: #integer) -> anyhow::Result<Self> {
274 Ok(#ident::#variant_ident(#other_ident::from_primitive(val)?))
275 }
276 });
277
278 let matches_method_ident = format_ident!("is_{}", &variant_as_snake_case);
279
280 matches_methods.push(quote! {
281 #[inline(always)]
282 pub fn #matches_method_ident(&self) -> bool {
283 matches!(self, #ident::#variant_ident(_))
284 }
285 });
286
287 if is_catchall {
288 let min = params.first_uniq_val();
289 let max = params.last_uniq_val();
290
291 from_range_cases.push(quote! {
292 #min..=#max => #ident::#variant_ident(unsafe { #other_ident::new_unchecked(val) }),
293 });
294 } else {
295 from_range_cases.push(quote! {
296 #(#literal_args)|* => #ident::#variant_ident(unsafe { #other_ident::new_unchecked(val) }),
297 });
298 }
299
300 as_primitive_cases.push(quote! {
301 #ident::#variant_ident(val) => val.as_primitive(),
302 });
303 }
304 ClampedEnumVariantField::ClampedEnum {
305 value_range,
306 variants: nested_variants,
307 ..
308 } => {
309 let kind = *integer;
310 let other_ident = params.other_ident(variant_ident);
311
312 let variant_lower_limit = value_range
313 .as_ref()
314 .map(|range| range.0.first_val(kind))
315 .unwrap_or_else(|| NumberArg::new_min_constant(kind).into_value(kind));
316 let variant_upper_limit = value_range
317 .as_ref()
318 .map(|range| range.0.last_val(kind))
319 .unwrap_or_else(|| NumberArg::new_max_constant(kind).into_value(kind));
320
321 let mut exacts = HashSet::with_capacity(nested_variants.len());
322 let mut range_seq = RangeSeq::with_capacity(kind, nested_variants.len());
323
324 nested_enum_items.push(define_mod(
325 &Params {
326 integer: *integer,
327 derived_traits: params.derived_traits.clone(),
328 vis: parse_quote!(pub),
329 ident: other_ident.clone(),
330 as_soft_or_hard: None,
331 default_val: default_val.map(|arg| arg.into_value(kind)),
332 behavior: behavior.clone(),
333 lower_limit_val: variant_lower_limit,
334 upper_limit_val: variant_upper_limit,
335 full_coverage: ClampedEnumItem::check_coverage(
336 Some(&mut exacts),
337 Some(&mut range_seq),
338 Some(variant_lower_limit),
339 Some(variant_upper_limit),
340 kind,
341 nested_variants.iter(),
342 )?,
343 exact_values: if exacts.is_empty() {
344 None
345 } else {
346 let mut exact_values = exacts.iter().copied().collect::<Vec<_>>();
347 exact_values.sort_unstable();
348 exact_values.dedup();
349 Some(exact_values)
350 },
351 valid_ranges: if range_seq.is_empty() {
352 None
353 } else {
354 Some(range_seq.uniq_ranges())
355 },
356 },
357 nested_variants,
358 )?);
359
360 from_nested_enum_impls.push(quote! {
361 impl From<#other_ident> for #ident {
362 #[inline(always)]
363 fn from(val: #other_ident) -> Self {
364 #ident::#variant_ident(val)
365 }
366 }
367 });
368
369 variants.push(quote! {
370 #variant_ident(#other_ident),
371 });
372
373 let factory_ident = format_ident!("new_{}", &variant_as_snake_case);
374
375 factory_methods.push(quote! {
376 #[inline(always)]
377 pub fn #factory_ident(val: #integer) -> anyhow::Result<Self> {
378 Ok(#ident::#variant_ident(#other_ident::from_primitive(val)?))
379 }
380 });
381
382 let matches_method_ident = format_ident!("is_{}", &variant_as_snake_case);
383
384 matches_methods.push(quote! {
385 #[inline(always)]
386 pub fn #matches_method_ident(&self) -> bool {
387 matches!(self, #ident::#variant_ident(_))
388 }
389 });
390
391 if !exacts.is_empty() {
392 let literal_values = exacts.iter().collect::<Vec<_>>();
393
394 from_nested_cases.push(quote! {
395 #(#literal_values)|* => #ident::#variant_ident(#value_ident::new(val).unwrap()),
396 });
397 }
398
399 if !range_seq.is_empty() {
400 let literal_ranges = range_seq
401 .all_ranges()
402 .into_iter()
403 .map(|range| {
404 let start = range.start();
405 let end = range.end();
406
407 quote! {
408 #start..=#end
409 }
410 })
411 .collect::<Vec<_>>();
412
413 from_range_cases.push(quote! {
414 #(#literal_ranges)|* => #ident::#variant_ident(unsafe { #other_ident::new_unchecked(val) }),
415 });
416 }
417
418 as_primitive_cases.push(quote! {
419 #ident::#variant_ident(val) => val.as_primitive(),
420 });
421 }
422 }
423 }
424
425 let lower_limit = params.lower_limit_token();
426 let upper_limit = params.upper_limit_token();
427 let default_val = params.default_val_token();
428
429 let guard_ident = params.guard_ident();
430 let def_guard = define_guard(ident, &guard_ident, params);
431
432 let def_value_item = define_value_item(
433 ¶ms.derived_traits,
434 &value_ident,
435 params.integer,
436 ¶ms.lower_limit_val,
437 ¶ms.upper_limit_val,
438 );
439
440 let mut traits = params
441 .derived_traits
442 .as_ref()
443 .map(|x| {
444 let mut traits = Vec::with_capacity(x.traits.len());
445
446 traits.extend(
447 x.traits
448 .iter()
449 .filter(|ty| {
450 let ty = ty
451 .path
452 .segments
453 .last()
454 .unwrap()
455 .to_token_stream()
456 .to_string();
457
458 match ty.as_str() {
459 "Clone" | "Copy" => false,
460 _ => true,
461 }
462 })
463 .cloned(),
464 );
465
466 traits
467 })
468 .unwrap_or(Vec::with_capacity(2));
469
470 traits.extend(vec![parse_quote!(Clone), parse_quote!(Copy)]);
471
472 let exact_values_trait_impl = if let Some(values) = ¶ms.exact_values {
473 Some(quote! {
474 unsafe impl ExactValues<#integer> for #ident {
475 const VALUES: &'static [#integer] = &[
476 #(#values),*
477 ];
478 }
479 })
480 } else {
481 None
482 };
483
484 let valid_ranges_trait_impl = if let Some(ranges) = ¶ms.valid_ranges {
485 Some(quote! {
486 unsafe impl RangeValues<#integer> for #ident {
487 const VALID_RANGES: &'static [ValueRangeInclusive<#integer>] = &[
488 #(ValueRangeInclusive(#ranges)),*
489 ];
490 }
491 })
492 } else {
493 None
494 };
495
496 let op_behavior_params_method = match (&exact_values_trait_impl, &valid_ranges_trait_impl) {
497 (None, None) => {
498 return Err(syn::Error::new(
499 Span::call_site(),
500 "Clamped enums must have at least one variant",
501 ));
502 }
503 (Some(..), None) => {
505 quote! {
506 #[inline(always)]
507 pub(self) fn op_behavior_params(&self) -> OpBehaviorParams<#integer> {
508 OpBehaviorParams::ExactsOnly(<#ident as ExactValues<#integer>>::VALUES)
509 }
510 }
511 }
512 (None, Some(..)) => {
514 quote! {
515 #[inline(always)]
516 pub(self) fn op_behavior_params(&self) -> OpBehaviorParams<#integer> {
517 let ranges = <#ident as RangeValues<#integer>>::VALID_RANGES;
518
519 if ranges.len() == 1 {
520 let range = &ranges[0];
521
522 OpBehaviorParams::Simple {
523 min: range.first_val(),
524 max: range.last_val(),
525 }
526 } else {
527 let min = ranges.first().unwrap().first_val();
528 let max = ranges.last().unwrap().last_val();
529
530 OpBehaviorParams::RangesOnly(ranges)
531 }
532 }
533 }
534 }
535 (Some(..), Some(..)) => {
537 quote! {
538 #[inline(always)]
539 pub(self) fn op_behavior_params(&self) -> OpBehaviorParams<#integer> {
540 OpBehaviorParams::ExactsAndRanges {
541 exacts: <#ident as ExactValues<#integer>>::VALUES,
542 ranges: <#ident as RangeValues<#integer>>::VALID_RANGES,
543 }
544 }
545 }
546 }
547 };
548
549 let catchall_case_is_needed = {
550 let lower_limit_val = params.lower_limit_val;
551 let upper_limit_val = params.upper_limit_val;
552 let lowest_val_of_kind = NumberArg::new_min_constant(kind).into_value(kind);
553 let highest_val_of_kind = NumberArg::new_max_constant(kind).into_value(kind);
554
555 if lower_limit_val > lowest_val_of_kind {
556 true
557 } else if upper_limit_val < highest_val_of_kind {
558 true
559 } else if !has_catchall {
560 true
561 } else if !params.full_coverage {
562 true
563 } else {
564 false
565 }
566 };
567
568 let catchall_case = if catchall_case_is_needed {
569 Some(quote! {
570 _ => anyhow::bail!("value is not allowed"),
571 })
572 } else if kind == NumberKind::USize {
573 Some(quote! {
574 usize::MAX.. => unreachable!(),
575 })
576 } else {
577 None
578 };
579
580 let const_catchall_case = if catchall_case_is_needed {
581 Some(quote! {
582 _ => panic!("value is not allowed"),
583 })
584 } else if kind == NumberKind::USize {
585 Some(quote! {
586 usize::MAX.. => unreachable!(),
587 })
588 } else {
589 None
590 };
591
592 Ok(quote! {
593 #vis mod #mod_ident {
594 use super::*;
595
596 #[derive(#(#traits),*)]
597 pub enum #ident {
598 #(#variants)*
599 }
600
601 #[inline(always)]
602 const fn const_from_primitive(val: #integer) -> #ident {
603 match val {
604 #(#from_exact_cases)*
605 #(#from_range_cases)*
606 #const_catchall_case
607 }
608 }
609
610 impl #ident {
611 #[inline(always)]
612 pub fn new(val: #integer) -> Option<Self> {
613 match <Self as ClampedInteger<#integer>>::from_primitive(val) {
614 Ok(val) => Some(val),
615 Err(e) => None,
616 }
617 }
618
619 #[inline(always)]
620 pub const unsafe fn new_unchecked(val: #integer) -> Self {
621 const_from_primitive(val)
622 }
623
624 #op_behavior_params_method
625
626 #(#factory_methods)*
627
628 #(#matches_methods)*
629
630 #[inline(always)]
631 pub fn validate(value: #integer) -> ::anyhow::Result<()> {
632 <Self as ClampedInteger<#integer>>::from_primitive(value)?;
633 Ok(())
634 }
635
636 #[inline(always)]
637 pub fn modify<'a>(&'a mut self) -> #guard_ident<'a> {
638 #guard_ident::new(self)
639 }
640 }
641
642
643 impl InherentLimits<#integer> for #ident {
644 const MIN_INT: #integer = #lower_limit;
645 const MAX_INT: #integer = #upper_limit;
646 const MIN: #ident = const_from_primitive(#lower_limit);
647 const MAX: #ident = const_from_primitive(#upper_limit);
648
649 #[inline(always)]
650 fn is_zero(&self) -> bool {
651 self.into_primitive() == 0
652 }
653
654 #[inline(always)]
655 fn is_negative(&self) -> bool {
656 self.into_primitive() < 0
657 }
658
659 #[inline(always)]
660 fn is_positive(&self) -> bool {
661 self.into_primitive() > 0
662 }
663 }
664
665 impl InherentBehavior for #ident {
666 type Behavior = #behavior;
667 }
668
669 unsafe impl ClampedInteger<#integer> for #ident {
670 #[inline(always)]
671 fn from_primitive(val: #integer) -> ::anyhow::Result<Self> {
672 Ok(match val {
673 #(#from_exact_cases)*
674 #(#from_range_cases)*
675 #catchall_case
676 })
677 }
678
679 #[inline(always)]
680 fn as_primitive(&self) -> &#integer {
681 match &*self {
682 #(#as_primitive_cases)*
683 }
684 }
685 }
686
687 #exact_values_trait_impl
688
689 #valid_ranges_trait_impl
690
691 unsafe impl ClampedEnum<#integer> for #ident {}
692
693 impl Default for #ident {
694 #[inline(always)]
695 fn default() -> Self {
696 <Self as ClampedInteger<#integer>>::from_primitive(#default_val).unwrap()
697 }
698 }
699
700 #implementations
701
702 #def_value_item
703
704 #(#exact_items)*
705
706 #(#range_items)*
707
708 #(#nested_enum_items)*
709
710 #(#from_nested_enum_impls)*
711
712 #def_guard
713 }
714
715 #vis use #mod_ident::#ident;
716 })
717}
718
719fn define_value_item(
720 derived_traits: &Option<DerivedTraits>,
721 value_item_ident: &syn::Ident,
722 integer: NumberKind,
723 lower_limit: &NumberValue,
724 upper_limit: &NumberValue,
725) -> TokenStream {
726 let mut traits = derived_traits
727 .as_ref()
728 .map(|x| {
729 let mut traits = Vec::with_capacity(x.traits.len());
730
731 traits.extend(
732 x.traits
733 .iter()
734 .filter(|ty| {
735 let ty = ty
736 .path
737 .segments
738 .last()
739 .unwrap()
740 .to_token_stream()
741 .to_string();
742
743 match ty.as_str() {
744 "Debug" | "Clone" | "Copy" | "PartialEq" | "Eq" | "PartialOrd"
745 | "Ord" => false,
746 _ => true,
747 }
748 })
749 .cloned(),
750 );
751
752 traits
753 })
754 .unwrap_or(Vec::with_capacity(6));
755
756 traits.extend(vec![
757 parse_quote!(Clone),
758 parse_quote!(Copy),
759 parse_quote!(PartialEq),
760 parse_quote!(Eq),
761 parse_quote!(PartialOrd),
762 parse_quote!(Ord),
763 ]);
764
765 quote! {
766 #[derive(#(#traits),*)]
767 pub struct #value_item_ident<T: ExactValues<#integer>>(pub(self) #integer, pub(self) std::marker::PhantomData<T>);
768
769
770 impl<T: ExactValues<#integer>> #value_item_ident<T> {
771 #[inline(always)]
772 pub const unsafe fn new_unchecked(val: #integer) -> Self {
773 Self(val, std::marker::PhantomData)
774 }
775 }
776
777 impl<T: ExactValues<#integer>> InherentLimits<#integer> for #value_item_ident<T> {
778 const MIN_INT: #integer = #lower_limit;
779 const MAX_INT: #integer = #upper_limit;
780 const MIN: Self = Self(#lower_limit, std::marker::PhantomData);
781 const MAX: Self = Self(#upper_limit, std::marker::PhantomData);
782
783 #[inline(always)]
784 fn is_zero(&self) -> bool {
785 self.0 == 0
786 }
787
788 #[inline(always)]
789 fn is_negative(&self) -> bool {
790 self.0 < 0
791 }
792
793 #[inline(always)]
794 fn is_positive(&self) -> bool {
795 self.0 > 0
796 }
797 }
798
799 impl<T: ExactValues<#integer>> Default for #value_item_ident<T> {
800 #[inline(always)]
801 fn default() -> Self {
802 Self(T::VALUES[0], std::marker::PhantomData)
803 }
804 }
805
806 impl<T: ExactValues<#integer>> std::fmt::Debug for #value_item_ident<T> {
807 #[inline(always)]
808 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
809 self.0.fmt(f)
810 }
811 }
812
813 impl<T: ExactValues<#integer>> std::fmt::Display for #value_item_ident<T> {
814 #[inline(always)]
815 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
816 self.0.fmt(f)
817 }
818 }
819
820 impl<T: ExactValues<#integer>> std::ops::Deref for #value_item_ident<T> {
821 type Target = #integer;
822
823 #[inline(always)]
824 fn deref(&self) -> &Self::Target {
825 &self.0
826 }
827 }
828
829 impl<T: ExactValues<#integer>> AsRef<#integer> for #value_item_ident<T> {
830 #[inline(always)]
831 fn as_ref(&self) -> &#integer {
832 &self.0
833 }
834 }
835
836 impl<T: ExactValues<#integer>> From<#value_item_ident<T>> for #integer {
837 #[inline(always)]
838 fn from(val: #value_item_ident<T>) -> Self {
839 val.0
840 }
841 }
842
843 unsafe impl<T: ExactValues<#integer>> ClampedInteger<#integer> for #value_item_ident<T> {
844 #[inline(always)]
845 fn from_primitive(val: #integer) -> anyhow::Result<Self> {
846 if T::contains_value(val) {
847 Ok(Self(val, std::marker::PhantomData))
848 } else {
849 Err(anyhow::anyhow!("value is not allowed"))
850 }
851 }
852
853 #[inline(always)]
854 fn as_primitive(&self) -> &#integer {
855 &self.0
856 }
857 }
858 }
859}