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