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