1#![cfg_attr(coverage_nightly, feature(coverage_attribute))]
2
3use std::collections::HashMap;
14use std::num::NonZeroU16;
15
16pub mod grammar;
17mod interner;
18mod invariants;
19pub mod utils;
20
21#[cfg(test)]
22mod interner_tests;
23#[cfg(test)]
24mod lib_tests;
25#[cfg(test)]
26mod utils_tests;
27
28pub use interner::{Interner, Symbol};
29
30#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
32pub struct RawNode {
33 #[serde(rename = "type")]
34 pub type_name: String,
35 pub named: bool,
36 #[serde(default)]
37 pub root: bool,
38 #[serde(default)]
39 pub extra: bool,
40 #[serde(default)]
41 pub fields: HashMap<String, RawCardinality>,
42 pub children: Option<RawCardinality>,
43 pub subtypes: Option<Vec<RawTypeRef>>,
44}
45
46#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
48pub struct RawCardinality {
49 pub multiple: bool,
50 pub required: bool,
51 pub types: Vec<RawTypeRef>,
52}
53
54#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
56pub struct RawTypeRef {
57 #[serde(rename = "type")]
58 pub type_name: String,
59 pub named: bool,
60}
61
62pub fn parse_node_types(json: &str) -> Result<Vec<RawNode>, serde_json::Error> {
64 serde_json::from_str(json)
65}
66
67pub type NodeTypeId = NonZeroU16;
69
70pub type NodeFieldId = NonZeroU16;
72
73#[derive(Debug, Clone, Copy, PartialEq, Eq)]
75pub struct Cardinality {
76 pub multiple: bool,
77 pub required: bool,
78}
79
80pub trait NodeTypes {
90 fn root(&self) -> Option<NodeTypeId>;
91 fn is_extra(&self, node_type_id: NodeTypeId) -> bool;
92
93 fn has_field(&self, node_type_id: NodeTypeId, node_field_id: NodeFieldId) -> bool;
94 fn field_cardinality(
95 &self,
96 node_type_id: NodeTypeId,
97 node_field_id: NodeFieldId,
98 ) -> Option<Cardinality>;
99 fn valid_field_types(
100 &self,
101 node_type_id: NodeTypeId,
102 node_field_id: NodeFieldId,
103 ) -> &[NodeTypeId];
104 fn is_valid_field_type(
105 &self,
106 node_type_id: NodeTypeId,
107 node_field_id: NodeFieldId,
108 child: NodeTypeId,
109 ) -> bool;
110
111 fn children_cardinality(&self, node_type_id: NodeTypeId) -> Option<Cardinality>;
112 fn valid_child_types(&self, node_type_id: NodeTypeId) -> &[NodeTypeId];
113 fn is_valid_child_type(&self, node_type_id: NodeTypeId, child: NodeTypeId) -> bool;
114}
115
116impl<T: NodeTypes + ?Sized> NodeTypes for &T {
117 fn root(&self) -> Option<NodeTypeId> {
118 (*self).root()
119 }
120 fn is_extra(&self, node_type_id: NodeTypeId) -> bool {
121 (*self).is_extra(node_type_id)
122 }
123 fn has_field(&self, node_type_id: NodeTypeId, node_field_id: NodeFieldId) -> bool {
124 (*self).has_field(node_type_id, node_field_id)
125 }
126 fn field_cardinality(
127 &self,
128 node_type_id: NodeTypeId,
129 node_field_id: NodeFieldId,
130 ) -> Option<Cardinality> {
131 (*self).field_cardinality(node_type_id, node_field_id)
132 }
133 fn valid_field_types(
134 &self,
135 node_type_id: NodeTypeId,
136 node_field_id: NodeFieldId,
137 ) -> &[NodeTypeId] {
138 (*self).valid_field_types(node_type_id, node_field_id)
139 }
140 fn is_valid_field_type(
141 &self,
142 node_type_id: NodeTypeId,
143 node_field_id: NodeFieldId,
144 child: NodeTypeId,
145 ) -> bool {
146 (*self).is_valid_field_type(node_type_id, node_field_id, child)
147 }
148 fn children_cardinality(&self, node_type_id: NodeTypeId) -> Option<Cardinality> {
149 (*self).children_cardinality(node_type_id)
150 }
151 fn valid_child_types(&self, node_type_id: NodeTypeId) -> &[NodeTypeId] {
152 (*self).valid_child_types(node_type_id)
153 }
154 fn is_valid_child_type(&self, node_type_id: NodeTypeId, child: NodeTypeId) -> bool {
155 (*self).is_valid_child_type(node_type_id, child)
156 }
157}
158
159#[derive(Debug, Clone, Copy)]
161pub struct StaticFieldInfo {
162 pub cardinality: Cardinality,
163 pub valid_types: &'static [NodeTypeId],
164}
165
166#[derive(Debug, Clone, Copy)]
168pub struct StaticChildrenInfo {
169 pub cardinality: Cardinality,
170 pub valid_types: &'static [NodeTypeId],
171}
172
173#[derive(Debug, Clone, Copy)]
178pub struct StaticNodeTypeInfo {
179 pub name: &'static str,
180 pub named: bool,
181 pub fields: &'static [(NodeFieldId, StaticFieldInfo)],
183 pub children: Option<StaticChildrenInfo>,
184}
185
186#[derive(Debug, Clone, Copy)]
191pub struct StaticNodeTypes {
192 nodes: &'static [(NodeTypeId, StaticNodeTypeInfo)],
194 extras: &'static [NodeTypeId],
196 root: Option<NodeTypeId>,
197}
198
199impl StaticNodeTypes {
200 pub const fn new(
201 nodes: &'static [(NodeTypeId, StaticNodeTypeInfo)],
202 extras: &'static [NodeTypeId],
203 root: Option<NodeTypeId>,
204 ) -> Self {
205 Self {
206 nodes,
207 extras,
208 root,
209 }
210 }
211
212 pub fn get(&self, node_type_id: NodeTypeId) -> Option<&'static StaticNodeTypeInfo> {
214 self.nodes
215 .binary_search_by_key(&node_type_id, |(node_id, _)| *node_id)
216 .ok()
217 .map(|idx| &self.nodes[idx].1)
218 }
219
220 pub fn contains(&self, node_type_id: NodeTypeId) -> bool {
222 self.nodes
223 .binary_search_by_key(&node_type_id, |(node_id, _)| *node_id)
224 .is_ok()
225 }
226
227 pub fn field(
229 &self,
230 node_type_id: NodeTypeId,
231 field_id: NodeFieldId,
232 ) -> Option<&'static StaticFieldInfo> {
233 let info = self.ensure_node(node_type_id);
234 info.fields
235 .binary_search_by_key(&field_id, |(fid, _)| *fid)
236 .ok()
237 .map(|idx| &info.fields[idx].1)
238 }
239
240 pub fn children(&self, node_type_id: NodeTypeId) -> Option<StaticChildrenInfo> {
242 self.ensure_node(node_type_id).children
243 }
244
245 pub fn extras(&self) -> &'static [NodeTypeId] {
247 self.extras
248 }
249
250 pub fn len(&self) -> usize {
251 self.nodes.len()
252 }
253
254 pub fn is_empty(&self) -> bool {
255 self.nodes.is_empty()
256 }
257
258 pub fn iter(&self) -> impl Iterator<Item = (NodeTypeId, &'static StaticNodeTypeInfo)> {
259 self.nodes.iter().map(|(id, info)| (*id, info))
260 }
261}
262
263impl NodeTypes for StaticNodeTypes {
264 fn root(&self) -> Option<NodeTypeId> {
265 self.root
266 }
267
268 fn is_extra(&self, node_type_id: NodeTypeId) -> bool {
269 self.extras.contains(&node_type_id)
270 }
271
272 fn has_field(&self, node_type_id: NodeTypeId, node_field_id: NodeFieldId) -> bool {
273 self.get(node_type_id).is_some_and(|info| {
274 info.fields
275 .binary_search_by_key(&node_field_id, |(fid, _)| *fid)
276 .is_ok()
277 })
278 }
279
280 fn field_cardinality(
281 &self,
282 node_type_id: NodeTypeId,
283 node_field_id: NodeFieldId,
284 ) -> Option<Cardinality> {
285 self.field(node_type_id, node_field_id)
286 .map(|f| f.cardinality)
287 }
288
289 fn valid_field_types(
290 &self,
291 node_type_id: NodeTypeId,
292 node_field_id: NodeFieldId,
293 ) -> &[NodeTypeId] {
294 self.field(node_type_id, node_field_id)
295 .map(|f| f.valid_types)
296 .unwrap_or(&[])
297 }
298
299 fn is_valid_field_type(
300 &self,
301 node_type_id: NodeTypeId,
302 node_field_id: NodeFieldId,
303 child: NodeTypeId,
304 ) -> bool {
305 self.valid_field_types(node_type_id, node_field_id)
306 .contains(&child)
307 }
308
309 fn children_cardinality(&self, node_type_id: NodeTypeId) -> Option<Cardinality> {
310 self.children(node_type_id).map(|c| c.cardinality)
311 }
312
313 fn valid_child_types(&self, node_type_id: NodeTypeId) -> &[NodeTypeId] {
314 self.children(node_type_id)
315 .map(|c| c.valid_types)
316 .unwrap_or(&[])
317 }
318
319 fn is_valid_child_type(&self, node_type_id: NodeTypeId, child: NodeTypeId) -> bool {
320 self.valid_child_types(node_type_id).contains(&child)
321 }
322}
323
324#[derive(Debug, Clone)]
326pub struct FieldInfo {
327 pub cardinality: Cardinality,
328 pub valid_types: Vec<NodeTypeId>,
329}
330
331#[derive(Debug, Clone)]
333pub struct ChildrenInfo {
334 pub cardinality: Cardinality,
335 pub valid_types: Vec<NodeTypeId>,
336}
337
338#[derive(Debug, Clone)]
342pub struct NodeTypeInfo {
343 pub name: String,
344 pub named: bool,
345 pub fields: HashMap<NodeFieldId, FieldInfo>,
346 pub children: Option<ChildrenInfo>,
347}
348
349#[derive(Debug, Clone)]
354pub struct DynamicNodeTypes {
355 nodes: HashMap<NodeTypeId, NodeTypeInfo>,
356 extras: Vec<NodeTypeId>,
357 root: Option<NodeTypeId>,
358}
359
360impl DynamicNodeTypes {
361 pub fn from_raw(
362 nodes: HashMap<NodeTypeId, NodeTypeInfo>,
363 extras: Vec<NodeTypeId>,
364 root: Option<NodeTypeId>,
365 ) -> Self {
366 Self {
367 nodes,
368 extras,
369 root,
370 }
371 }
372
373 pub fn build<F, G>(raw_nodes: &[RawNode], node_id_for_name: F, field_id_for_name: G) -> Self
375 where
376 F: Fn(&str, bool) -> Option<NodeTypeId>,
377 G: Fn(&str) -> Option<NodeFieldId>,
378 {
379 let mut nodes = HashMap::new();
380 let mut extras = Vec::new();
381 let mut root = None;
382
383 for raw in raw_nodes {
384 let Some(node_id) = node_id_for_name(&raw.type_name, raw.named) else {
385 continue;
386 };
387
388 if raw.root {
389 root = Some(node_id);
390 }
391
392 if raw.extra {
393 extras.push(node_id);
394 }
395
396 let mut fields = HashMap::new();
397 for (field_name, raw_card) in &raw.fields {
398 let Some(field_id) = field_id_for_name(field_name) else {
399 continue;
400 };
401
402 let valid_types = raw_card
403 .types
404 .iter()
405 .filter_map(|t| node_id_for_name(&t.type_name, t.named))
406 .collect();
407
408 fields.insert(
409 field_id,
410 FieldInfo {
411 cardinality: Cardinality {
412 multiple: raw_card.multiple,
413 required: raw_card.required,
414 },
415 valid_types,
416 },
417 );
418 }
419
420 let children = raw.children.as_ref().map(|raw_card| {
421 let valid_types = raw_card
422 .types
423 .iter()
424 .filter_map(|t| node_id_for_name(&t.type_name, t.named))
425 .collect();
426
427 ChildrenInfo {
428 cardinality: Cardinality {
429 multiple: raw_card.multiple,
430 required: raw_card.required,
431 },
432 valid_types,
433 }
434 });
435
436 nodes.insert(
437 node_id,
438 NodeTypeInfo {
439 name: raw.type_name.clone(),
440 named: raw.named,
441 fields,
442 children,
443 },
444 );
445 }
446
447 Self {
448 nodes,
449 extras,
450 root,
451 }
452 }
453
454 pub fn get(&self, node_type_id: NodeTypeId) -> Option<&NodeTypeInfo> {
455 self.nodes.get(&node_type_id)
456 }
457
458 pub fn contains(&self, node_type_id: NodeTypeId) -> bool {
459 self.nodes.contains_key(&node_type_id)
460 }
461
462 pub fn field(&self, node_type_id: NodeTypeId, field_id: NodeFieldId) -> Option<&FieldInfo> {
463 self.ensure_node(node_type_id).fields.get(&field_id)
464 }
465
466 pub fn children(&self, node_type_id: NodeTypeId) -> Option<&ChildrenInfo> {
467 self.ensure_node(node_type_id).children.as_ref()
468 }
469
470 pub fn extras(&self) -> &[NodeTypeId] {
471 &self.extras
472 }
473
474 pub fn len(&self) -> usize {
475 self.nodes.len()
476 }
477
478 pub fn is_empty(&self) -> bool {
479 self.nodes.is_empty()
480 }
481
482 pub fn iter(&self) -> impl Iterator<Item = (NodeTypeId, &NodeTypeInfo)> {
483 self.nodes.iter().map(|(&id, info)| (id, info))
484 }
485
486 pub fn sorted_node_ids(&self) -> Vec<NodeTypeId> {
488 let mut ids: Vec<_> = self.nodes.keys().copied().collect();
489 ids.sort_unstable();
490 ids
491 }
492
493 pub fn sorted_extras(&self) -> Vec<NodeTypeId> {
495 let mut ids = self.extras.clone();
496 ids.sort_unstable();
497 ids
498 }
499}
500
501impl NodeTypes for DynamicNodeTypes {
502 fn root(&self) -> Option<NodeTypeId> {
503 self.root
504 }
505
506 fn is_extra(&self, node_type_id: NodeTypeId) -> bool {
507 self.extras.contains(&node_type_id)
508 }
509
510 fn has_field(&self, node_type_id: NodeTypeId, node_field_id: NodeFieldId) -> bool {
511 self.nodes
512 .get(&node_type_id)
513 .is_some_and(|n| n.fields.contains_key(&node_field_id))
514 }
515
516 fn field_cardinality(
517 &self,
518 node_type_id: NodeTypeId,
519 node_field_id: NodeFieldId,
520 ) -> Option<Cardinality> {
521 self.field(node_type_id, node_field_id)
522 .map(|f| f.cardinality)
523 }
524
525 fn valid_field_types(
526 &self,
527 node_type_id: NodeTypeId,
528 node_field_id: NodeFieldId,
529 ) -> &[NodeTypeId] {
530 self.field(node_type_id, node_field_id)
531 .map(|f| f.valid_types.as_slice())
532 .unwrap_or(&[])
533 }
534
535 fn is_valid_field_type(
536 &self,
537 node_type_id: NodeTypeId,
538 node_field_id: NodeFieldId,
539 child: NodeTypeId,
540 ) -> bool {
541 self.valid_field_types(node_type_id, node_field_id)
542 .contains(&child)
543 }
544
545 fn children_cardinality(&self, node_type_id: NodeTypeId) -> Option<Cardinality> {
546 self.children(node_type_id).map(|c| c.cardinality)
547 }
548
549 fn valid_child_types(&self, node_type_id: NodeTypeId) -> &[NodeTypeId] {
550 self.children(node_type_id)
551 .map(|c| c.valid_types.as_slice())
552 .unwrap_or(&[])
553 }
554
555 fn is_valid_child_type(&self, node_type_id: NodeTypeId, child: NodeTypeId) -> bool {
556 self.valid_child_types(node_type_id).contains(&child)
557 }
558}