1use super::{Attribute, Comment, DocString, Ident, LitInt, Prelude, TypeName};
2use crate::error::{
3 DuplicateStructField, DuplicateStructFieldId, InvalidStructFieldId, RecursiveStruct,
4};
5use crate::grammar::Rule;
6use crate::validate::Validate;
7use crate::warning::{BrokenDocLink, NonCamelCaseStruct, NonSnakeCaseStructField};
8use crate::Span;
9use pest::iterators::Pair;
10
11#[derive(Debug, Clone)]
12pub struct StructDef {
13 span: Span,
14 comment: Vec<Comment>,
15 doc: Vec<DocString>,
16 attrs: Vec<Attribute>,
17 name: Ident,
18 fields: Vec<StructField>,
19 fallback: Option<StructFallback>,
20}
21
22impl StructDef {
23 pub(crate) fn parse(pair: Pair<Rule>) -> Self {
24 assert_eq!(pair.as_rule(), Rule::struct_def);
25
26 let span = Span::from_pair(&pair);
27 let mut pairs = pair.into_inner();
28 let mut prelude = Prelude::regular(&mut pairs);
29
30 pairs.next().unwrap(); let pair = pairs.next().unwrap();
33 let name = Ident::parse(pair);
34
35 pairs.next().unwrap(); let mut fields = Vec::new();
38 let mut fallback = None;
39
40 for pair in pairs {
41 match pair.as_rule() {
42 Rule::struct_field => fields.push(StructField::parse(pair)),
43 Rule::struct_fallback => fallback = Some(StructFallback::parse(pair)),
44 Rule::tok_cur_close => break,
45 _ => unreachable!(),
46 }
47 }
48
49 Self {
50 span,
51 comment: prelude.take_comment(),
52 doc: prelude.take_doc(),
53 attrs: prelude.take_attrs(),
54 name,
55 fields,
56 fallback,
57 }
58 }
59
60 pub(crate) fn validate(&self, validate: &mut Validate) {
61 DuplicateStructField::validate(
62 &self.fields,
63 self.fallback.as_ref(),
64 Some(&self.name),
65 validate,
66 );
67
68 BrokenDocLink::validate(&self.doc, validate);
69 DuplicateStructFieldId::validate(&self.fields, Some(&self.name), validate);
70 NonCamelCaseStruct::validate(self, validate);
71 RecursiveStruct::validate(self, validate);
72
73 self.name.validate(true, validate);
74
75 for field in &self.fields {
76 field.validate(validate);
77 }
78
79 if let Some(ref fallback) = self.fallback {
80 fallback.validate(validate);
81 }
82 }
83
84 pub fn span(&self) -> Span {
85 self.span
86 }
87
88 pub fn comment(&self) -> &[Comment] {
89 &self.comment
90 }
91
92 pub fn doc(&self) -> &[DocString] {
93 &self.doc
94 }
95
96 pub fn attributes(&self) -> &[Attribute] {
97 &self.attrs
98 }
99
100 pub fn name(&self) -> &Ident {
101 &self.name
102 }
103
104 pub fn fields(&self) -> &[StructField] {
105 &self.fields
106 }
107
108 pub fn fallback(&self) -> Option<&StructFallback> {
109 self.fallback.as_ref()
110 }
111}
112
113#[derive(Debug, Clone)]
114pub struct InlineStruct {
115 span: Span,
116 kw_span: Span,
117 doc: Vec<DocString>,
118 attrs: Vec<Attribute>,
119 fields: Vec<StructField>,
120 fallback: Option<StructFallback>,
121}
122
123impl InlineStruct {
124 pub(crate) fn parse(pair: Pair<Rule>) -> Self {
125 assert_eq!(pair.as_rule(), Rule::struct_inline);
126
127 let span = Span::from_pair(&pair);
128 let mut pairs = pair.into_inner();
129
130 let pair = pairs.next().unwrap();
131 let kw_span = Span::from_pair(&pair);
132
133 pairs.next().unwrap(); let mut prelude = Prelude::inline(&mut pairs);
136 let mut fields = Vec::new();
137 let mut fallback = None;
138
139 for pair in pairs {
140 match pair.as_rule() {
141 Rule::struct_field => fields.push(StructField::parse(pair)),
142 Rule::struct_fallback => fallback = Some(StructFallback::parse(pair)),
143 Rule::tok_cur_close => break,
144 _ => unreachable!(),
145 }
146 }
147
148 Self {
149 span,
150 kw_span,
151 doc: prelude.take_doc(),
152 attrs: prelude.take_attrs(),
153 fields,
154 fallback,
155 }
156 }
157
158 pub(crate) fn validate(&self, validate: &mut Validate) {
159 BrokenDocLink::validate(&self.doc, validate);
160 DuplicateStructField::validate(&self.fields, self.fallback.as_ref(), None, validate);
161 DuplicateStructFieldId::validate(&self.fields, None, validate);
162
163 for field in &self.fields {
164 field.validate(validate);
165 }
166
167 if let Some(ref fallback) = self.fallback {
168 fallback.validate(validate);
169 }
170 }
171
172 pub fn span(&self) -> Span {
173 self.span
174 }
175
176 pub fn keyword_span(&self) -> Span {
177 self.kw_span
178 }
179
180 pub fn doc(&self) -> &[DocString] {
181 &self.doc
182 }
183
184 pub fn attributes(&self) -> &[Attribute] {
185 &self.attrs
186 }
187
188 pub fn fields(&self) -> &[StructField] {
189 &self.fields
190 }
191
192 pub fn fallback(&self) -> Option<&StructFallback> {
193 self.fallback.as_ref()
194 }
195}
196
197#[derive(Debug, Clone)]
198pub struct StructField {
199 span: Span,
200 comment: Vec<Comment>,
201 doc: Vec<DocString>,
202 req: bool,
203 name: Ident,
204 id: LitInt,
205 field_type: TypeName,
206}
207
208impl StructField {
209 fn parse(pair: Pair<Rule>) -> Self {
210 assert_eq!(pair.as_rule(), Rule::struct_field);
211
212 let span = Span::from_pair(&pair);
213 let mut pairs = pair.into_inner();
214 let mut prelude = Prelude::regular(&mut pairs);
215
216 let (req, name) = match pairs.next().map(|pair| (pair.as_rule(), pair)).unwrap() {
217 (Rule::kw_required, _) => (true, Ident::parse(pairs.next().unwrap())),
218 (Rule::ident, pair) => (false, Ident::parse(pair)),
219 _ => unreachable!(),
220 };
221
222 pairs.next().unwrap(); let pair = pairs.next().unwrap();
225 let id = LitInt::parse(pair);
226
227 pairs.next().unwrap(); let pair = pairs.next().unwrap();
230 let field_type = TypeName::parse(pair);
231
232 Self {
233 span,
234 comment: prelude.take_comment(),
235 doc: prelude.take_doc(),
236 req,
237 name,
238 id,
239 field_type,
240 }
241 }
242
243 fn validate(&self, validate: &mut Validate) {
244 BrokenDocLink::validate(&self.doc, validate);
245 InvalidStructFieldId::validate(self, validate);
246 NonSnakeCaseStructField::validate(&self.name, validate);
247
248 self.name.validate(true, validate);
249 self.field_type.validate(false, validate);
250 }
251
252 pub fn span(&self) -> Span {
253 self.span
254 }
255
256 pub fn comment(&self) -> &[Comment] {
257 &self.comment
258 }
259
260 pub fn doc(&self) -> &[DocString] {
261 &self.doc
262 }
263
264 pub fn required(&self) -> bool {
265 self.req
266 }
267
268 pub fn name(&self) -> &Ident {
269 &self.name
270 }
271
272 pub fn id(&self) -> &LitInt {
273 &self.id
274 }
275
276 pub fn field_type(&self) -> &TypeName {
277 &self.field_type
278 }
279}
280
281#[derive(Debug, Clone)]
282pub struct StructFallback {
283 span: Span,
284 comment: Vec<Comment>,
285 doc: Vec<DocString>,
286 name: Ident,
287}
288
289impl StructFallback {
290 pub(crate) fn parse(pair: Pair<Rule>) -> Self {
291 assert_eq!(pair.as_rule(), Rule::struct_fallback);
292
293 let span = Span::from_pair(&pair);
294 let mut pairs = pair.into_inner();
295 let mut prelude = Prelude::regular(&mut pairs);
296
297 Self {
298 span,
299 comment: prelude.take_comment(),
300 doc: prelude.take_doc(),
301 name: Ident::parse(pairs.next().unwrap()),
302 }
303 }
304
305 pub(crate) fn validate(&self, validate: &mut Validate) {
306 BrokenDocLink::validate(&self.doc, validate);
307 NonSnakeCaseStructField::validate(&self.name, validate);
308
309 self.name.validate(true, validate);
310 }
311
312 pub fn span(&self) -> Span {
313 self.span
314 }
315
316 pub fn comment(&self) -> &[Comment] {
317 &self.comment
318 }
319
320 pub fn doc(&self) -> &[DocString] {
321 &self.doc
322 }
323
324 pub fn name(&self) -> &Ident {
325 &self.name
326 }
327}