checked_rs_macro_impl/item/
struct_item.rs1use syn::{parse::Parse, parse_quote};
2
3use crate::{
4 params::{
5 kw, AsSoftOrHard, BehaviorArg, DerivedTraits, NumberArg, NumberKind, Params, SemiOrComma,
6 },
7 range_seq::RangeSeq,
8};
9
10pub mod field;
11
12pub use field::*;
13
14pub struct ClampedStructItem {
15 pub pound: syn::Token![#],
16 pub bracket: syn::token::Bracket,
17 pub integer: NumberKind,
18 pub as_soft_or_hard: Option<AsSoftOrHard>,
19 pub integer_semi: Option<SemiOrComma>,
20 pub derived_traits: Option<DerivedTraits>,
21 pub derived_semi: Option<SemiOrComma>,
22 pub default_kw: Option<kw::default>,
23 pub default_eq: Option<syn::Token![=]>,
24 pub default_val: Option<NumberArg>,
25 pub default_semi: Option<SemiOrComma>,
26 pub behavior_kw: kw::behavior,
27 pub behavior_eq: syn::Token![=],
28 pub behavior_val: BehaviorArg,
29 pub behavior_semi: Option<SemiOrComma>,
30 pub vis: Option<syn::Visibility>,
31 pub struct_token: syn::Token![struct],
32 pub ident: syn::Ident,
33 pub field: ClampedStructField,
34 pub final_semi: Option<syn::Token![;]>,
35}
36
37impl Parse for ClampedStructItem {
38 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
39 let pound = input.parse()?;
40
41 let content;
42 let bracket = syn::bracketed!(content in input);
43 let integer = content.parse()?;
44 let mut as_soft_or_hard = None;
45 let mut integer_semi = None;
46 let mut derived_traits = None;
47 let mut derived_semi = None;
48 let mut default_kw = None;
49 let mut default_eq = None;
50 let mut default_val = None;
51 let mut default_semi = None;
52 let mut behavior_kw = None;
53 let mut behavior_eq = None;
54 let mut behavior_val = None;
55 let mut behavior_semi = None;
56 let mut vis = None;
57
58 if !content.is_empty() {
59 if content.peek(syn::Token![as]) {
60 as_soft_or_hard = Some(content.parse()?);
61 }
62
63 if !content.is_empty() {
64 integer_semi = Some(content.parse()?);
65
66 while !content.is_empty() {
67 if content.peek(kw::derive) {
68 derived_traits = Some(content.parse()?);
69 derived_semi = if content.peek(syn::Token![;]) {
70 Some(content.parse()?)
71 } else {
72 None
73 };
74 }
75
76 if content.peek(kw::default) {
77 default_kw = Some(content.parse()?);
78 default_eq = Some(content.parse()?);
79 default_val = Some(content.parse()?);
80 default_semi = if content.peek(syn::Token![;]) {
81 Some(content.parse()?)
82 } else {
83 None
84 };
85 }
86
87 if content.peek(kw::behavior) {
88 behavior_kw = Some(content.parse()?);
89 behavior_eq = Some(content.parse()?);
90 behavior_val = Some(content.parse()?);
91 behavior_semi = if content.peek(syn::Token![;]) {
92 Some(content.parse()?)
93 } else {
94 None
95 };
96 }
97 }
98 }
99 }
100
101 if input.peek(syn::Token![pub]) {
102 vis = Some(input.parse()?);
103 }
104
105 Ok(Self {
106 pound,
107 bracket,
108 integer,
109 as_soft_or_hard,
110 integer_semi,
111 derived_traits,
112 derived_semi,
113 default_kw,
114 default_eq,
115 default_val,
116 default_semi,
117 behavior_kw: behavior_kw.unwrap_or_else(|| parse_quote!(behavior)),
118 behavior_eq: behavior_eq.unwrap_or_else(|| parse_quote!(=)),
119 behavior_val: behavior_val.unwrap_or_else(|| parse_quote!(Panic)),
120 behavior_semi,
121 vis,
122 struct_token: input.parse()?,
123 ident: input.parse()?,
124 field: input.parse()?,
125 final_semi: if input.is_empty() {
126 None
127 } else {
128 Some(input.parse()?)
129 },
130 })
131 }
132}
133
134impl ClampedStructItem {
135 pub fn params(&self) -> syn::Result<Params> {
136 let kind = self.integer;
137 let (mut lower_limit, mut upper_limit) = NumberArg::LIMITS_INIT.clone();
138
139 let mut range_seq = RangeSeq::new(kind);
140
141 for range in self.field.ranges.iter() {
142 range_seq.insert(range.to_value_range(kind)?)?;
143
144 let start = range.start_arg(kind);
145 let end = range.end_arg(kind);
146
147 lower_limit = lower_limit.map_or_else(
148 || Some(start.clone()),
149 |lower_limit| Some(lower_limit.min(&start, kind)),
150 );
151
152 upper_limit = upper_limit.map_or_else(
153 || Some(end.clone()),
154 |upper_limit| Some(upper_limit.max(&end, kind)),
155 );
156 }
157
158 Ok(Params {
159 integer: self.integer,
160 derived_traits: self.derived_traits.clone(),
161 vis: self.vis.clone().unwrap_or(syn::Visibility::Inherited),
162 ident: self.ident.clone(),
163 as_soft_or_hard: self.as_soft_or_hard.clone(),
164 default_val: self.default_val.as_ref().map(|arg| arg.into_value(kind)),
165 behavior: self.behavior_val.clone(),
166 lower_limit_val: lower_limit
167 .or_else(|| Some(NumberArg::new_min_constant(kind)))
168 .map(|arg| arg.into_value(kind))
169 .unwrap(),
170 upper_limit_val: upper_limit
171 .or_else(|| Some(NumberArg::new_max_constant(kind)))
172 .map(|arg| arg.into_value(kind))
173 .unwrap(),
174 full_coverage: !range_seq.has_gaps(),
175 exact_values: None,
176 valid_ranges: Some(range_seq.uniq_ranges()),
177 })
178 }
179}