1use core::fmt::Display;
2use std::{borrow::Cow, collections::VecDeque};
3
4use alloc::vec::Vec;
5use tree_ds::prelude::{Node, NodeRemovalStrategy, Tree};
6
7use crate::{
8 path::Path,
9 type_info::{GenBinding, ValueType},
10};
11
12#[derive(Debug, Clone, PartialEq, Eq)]
13pub struct Container {
14 pub path: Path<'static, 'static>,
15 pub name: &'static str,
16 pub r#type: BindingType,
17}
18
19impl Container {
20 pub fn flatten_paths(&mut self) {
21 self.path.flatten();
22
23 match self.r#type {
24 BindingType::Struct(ref mut ty) => ty.flatten_paths(),
25 BindingType::Enum(ref mut ty) => ty.flatten_paths(),
26 BindingType::TupleStruct(ref mut ty) => ty.flatten_paths(),
27 _ => (),
28 }
29 }
30}
31
32pub struct ContainerInfo<'a> {
33 pub name: Cow<'a, str>,
34 pub path: Path<'a, 'a>,
35}
36
37impl From<&Container> for ContainerInfo<'_> {
38 fn from(container: &Container) -> Self {
39 Self {
40 name: Cow::Borrowed(container.name),
41 path: container.path.clone(),
42 }
43 }
44}
45
46#[derive(Debug, Clone, PartialEq, Eq)]
47pub enum BindingType {
48 Struct(StructType),
49 TupleStruct(TupleStructType),
50 UnitStruct(UnitStructType),
51 Enum(EnumType),
52}
53
54#[derive(Debug, Default, Clone, PartialEq, Eq)]
55pub struct EnumType {
57 pub variants: Vec<EnumVariant>,
58}
59
60impl EnumType {
61 pub fn new() -> Self {
62 Self::default()
63 }
64
65 pub fn register_variant(&mut self, name: &'static str) {
67 self.variants.push(EnumVariant {
68 index: self.variants.len(),
69 name,
70 inner_type: EnumVariantType::Empty,
71 });
72 }
73
74 pub fn register_variant_tuple(&mut self, name: &'static str, fields: TupleFields) {
75 self.variants.push(EnumVariant {
76 index: self.variants.len(),
77 name,
78 inner_type: EnumVariantType::Tuple(fields.into_inner()),
79 });
80 }
81
82 pub fn register_unnamed_struct(&mut self, name: &'static str, fields: StructFields) {
83 self.variants.push(EnumVariant {
84 index: self.variants.len(),
85 name,
86 inner_type: EnumVariantType::NewType(fields.into_inner()),
87 })
88 }
89
90 fn flatten_paths(&mut self) {
91 for variant in &mut self.variants {
92 match &mut variant.inner_type {
93 EnumVariantType::NewType(fields) => {
94 for field in fields {
95 field.v_type.flatten_paths();
96 }
97 }
98 EnumVariantType::Tuple(fields) => {
99 for field in fields {
100 field.flatten_paths();
101 }
102 }
103 _ => {}
104 }
105 }
106 }
107}
108
109#[derive(Debug, Clone, PartialEq, Eq)]
110pub struct EnumVariant {
111 pub index: usize,
112 pub name: &'static str,
113 pub inner_type: EnumVariantType,
114}
115
116impl AsRef<EnumVariant> for EnumVariant {
117 fn as_ref(&self) -> &EnumVariant {
118 self
119 }
120}
121
122#[derive(Debug, Clone, PartialEq, Eq)]
123pub enum EnumVariantType {
124 Empty,
125 Tuple(Vec<ValueType>),
126 NewType(Vec<StructField>),
128}
129
130#[derive(Debug, Default, Clone, PartialEq, Eq)]
131pub struct StructType {
132 pub fields: Vec<StructField>,
133}
134
135impl StructType {
136 pub fn new() -> Self {
137 Self::default()
138 }
139
140 pub fn register_field<T: GenBinding>(&mut self, name: &'static str) {
141 self.fields.push(StructField {
142 name,
143 v_type: T::get_type(),
144 })
145 }
146
147 fn flatten_paths(&mut self) {
148 for field in &mut self.fields {
149 field.v_type.flatten_paths();
150 }
151 }
152}
153
154#[derive(Debug, Default, Clone, PartialEq, Eq)]
155pub struct TupleStructType {
156 pub fields: Vec<ValueType>,
157}
158
159impl TupleStructType {
160 pub fn new() -> Self {
161 Self::default()
162 }
163
164 pub fn register_field<T: GenBinding>(&mut self) {
165 self.fields.push(T::get_type())
166 }
167
168 fn flatten_paths(&mut self) {
169 for field in &mut self.fields {
170 field.flatten_paths();
171 }
172 }
173}
174
175#[derive(Debug, Default, Clone, PartialEq, Eq)]
176pub struct UnitStructType;
177
178impl UnitStructType {
179 pub fn new() -> Self {
180 Self {}
181 }
182}
183
184#[derive(Debug, Clone, PartialEq, Eq)]
185pub struct StructField {
186 pub name: &'static str,
187 pub v_type: ValueType,
188}
189
190#[derive(Debug, Default)]
191pub struct StructFields(Vec<StructField>);
192
193impl StructFields {
194 pub fn register_field<T: GenBinding>(&mut self, name: &'static str) {
195 self.0.push(StructField {
196 name,
197 v_type: T::get_type(),
198 })
199 }
200
201 fn into_inner(self) -> Vec<StructField> {
202 self.0
203 }
204}
205
206#[derive(Default)]
207pub struct TupleFields(Vec<ValueType>);
208
209impl TupleFields {
210 pub fn register_field<T: GenBinding>(&mut self) {
211 self.0.push(T::get_type())
212 }
213
214 fn into_inner(self) -> Vec<ValueType> {
215 self.0
216 }
217}
218
219#[derive(Debug, Clone)]
223pub struct ContainerCollection(Tree<NodeId, NodeType>);
224
225impl ContainerCollection {
226 pub fn flatten(&mut self) {
230 let root_node_id = self.0.get_root_node().unwrap().get_node_id();
231 let root_node = self.0.get_node_by_id(&root_node_id).unwrap();
232
233 let root_mod_nodes = root_node
234 .get_children_ids()
235 .iter()
236 .filter_map(|i| {
237 let node = self.0.get_node_by_id(i).unwrap();
238
239 let node_value = node.get_value().unwrap();
240 if node_value.is_module() {
241 Some(node)
242 } else {
243 None
244 }
245 })
246 .collect::<VecDeque<_>>();
247
248 let mut mod_nodes = root_mod_nodes.clone();
249
250 loop {
251 if mod_nodes.is_empty() {
252 break;
253 }
254
255 let node = mod_nodes.pop_front().unwrap();
256
257 let children = node.get_children_ids();
258
259 for child in children {
260 let child_node = self.0.get_node_by_id(&child).unwrap();
261 let child_value = child_node.get_value().unwrap();
262
263 node.remove_child(child_node.clone());
264
265 if child_value.is_container() {
266 root_node.add_child(child_node);
267 } else if child_value.is_module() {
268 mod_nodes.push_back(child_node);
269 }
270 }
271 }
272
273 for node in root_mod_nodes {
274 self.0
275 .remove_node(
276 &node.get_node_id(),
277 NodeRemovalStrategy::RemoveNodeAndChildren,
278 )
279 .unwrap();
280 }
281
282 for node in root_node
283 .get_children_ids()
284 .iter()
285 .map(|node| self.0.get_node_by_id(node).unwrap())
286 {
287 node.update_value(|v| v.as_mut().unwrap().container_mut().unwrap().flatten_paths());
288 }
289 }
290
291 pub fn all_containers(&self) -> impl Iterator<Item = Container> + Clone + '_ {
292 self.0
293 .get_nodes()
294 .iter()
295 .filter_map(|node| node.get_value().unwrap().container().cloned())
296 }
297
298 pub fn containers_per_module(&self) -> (Vec<Container>, Vec<Module<'_>>) {
299 let root_node = self.0.get_root_node().unwrap().get_node_id();
300 container_and_modules_per_mod(&self.0, &root_node)
301 }
302}
303
304#[derive(Debug, Clone)]
305pub struct Module<'a> {
306 tree: &'a Tree<NodeId, NodeType>,
307 node_id: NodeId,
308 name: Cow<'static, str>,
309 cached_path: Option<String>,
310}
311
312impl<'a> Module<'a> {
313 fn new(tree: &'a Tree<NodeId, NodeType>, node_id: NodeId, name: Cow<'static, str>) -> Self {
314 Self {
315 tree,
316 node_id,
317 name,
318 cached_path: None,
319 }
320 }
321
322 pub fn path(&self) -> String {
323 if let Some(path) = &self.cached_path {
324 path.clone()
325 } else {
326 let mut curr_node = self.tree.get_node_by_id(&self.node_id).unwrap();
327 let mut path = Vec::new();
328 while let Some(id) = curr_node.get_parent_id() {
329 let node = self.tree.get_node_by_id(&id).unwrap();
330 if let NodeType::Module(name) = node.get_value().unwrap() {
331 if name != "::" {
332 path.push(name);
333 curr_node = node;
334 } else {
335 break;
336 }
337 }
338 }
339
340 path.join("/")
341 }
342 }
343
344 pub fn name(&self) -> &str {
345 self.name.as_ref()
346 }
347
348 pub fn entries(&self) -> (Vec<Container>, Vec<Module<'a>>) {
349 container_and_modules_per_mod(self.tree, &self.node_id)
350 }
351}
352
353fn container_and_modules_per_mod<'a>(
354 tree: &'a Tree<NodeId, NodeType>,
355 node_id: &NodeId,
356) -> (Vec<Container>, Vec<Module<'a>>) {
357 let node = tree.get_node_by_id(node_id).unwrap();
358
359 node.sort_children(|a, b| {
360 let a_height = tree.get_node_height(a).unwrap();
361 let b_height = tree.get_node_height(b).unwrap();
362
363 a_height.cmp(&b_height).reverse()
364 });
365
366 let mut mods = Vec::new();
367 let mut containers = Vec::new();
368
369 for (id, child) in node
370 .get_children_ids()
371 .iter()
372 .map(|id| (id, tree.get_node_by_id(id).unwrap()))
373 {
374 match child.get_value().unwrap() {
375 NodeType::Module(name) => mods.push(Module::new(tree, *id, name)),
376 NodeType::Container(container) => containers.push(container.clone()),
377 }
378 }
379
380 (containers, mods)
381}
382
383type NodeId = u128;
384
385enum PathExists {
386 Full(NodeId),
387 Partly(NodeId, Cow<'static, str>),
388}
389
390#[derive(Debug, Clone, PartialEq, Eq)]
391enum NodeType {
392 Container(Container),
393 Module(Cow<'static, str>),
394}
395
396impl Default for NodeType {
397 fn default() -> Self {
398 NodeType::Module("_".into())
399 }
400}
401
402impl Display for NodeType {
403 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
404 match self {
405 NodeType::Container(c) => write!(f, "Container({}, {})", c.name, c.path),
406 NodeType::Module(m) => write!(f, "Module({})", m),
407 }
408 }
409}
410
411impl NodeType {
412 fn container(&self) -> Option<&Container> {
413 match self {
414 NodeType::Container(c) => Some(c),
415 _ => None,
416 }
417 }
418
419 fn container_mut(&mut self) -> Option<&mut Container> {
420 match self {
421 NodeType::Container(c) => Some(c),
422 _ => None,
423 }
424 }
425
426 fn is_module(&self) -> bool {
427 matches!(self, NodeType::Module(_))
428 }
429
430 fn is_container(&self) -> bool {
431 matches!(self, NodeType::Container(_))
432 }
433}
434
435#[derive(Debug)]
436pub struct BindingsRegistry(Tree<NodeId, NodeType>);
437
438impl BindingsRegistry {
439 pub fn register_struct_binding(
440 &mut self,
441 name: &'static str,
442 path: impl Into<Cow<'static, str>>,
443 value: StructType,
444 ) {
445 self.insert_container(Container {
446 path: Path::new(path, "::"),
447 name,
448 r#type: BindingType::Struct(value),
449 });
450 }
451
452 pub fn register_tuple_struct_binding(
453 &mut self,
454 name: &'static str,
455 path: impl Into<Cow<'static, str>>,
456 value: TupleStructType,
457 ) {
458 self.insert_container(Container {
459 path: Path::new(path, "::"),
460 name,
461 r#type: BindingType::TupleStruct(value),
462 });
463 }
464
465 pub fn register_unit_struct_binding(
466 &mut self,
467 name: &'static str,
468 path: impl Into<Cow<'static, str>>,
469 value: UnitStructType,
470 ) {
471 self.insert_container(Container {
472 path: Path::new(path, "::"),
473 name,
474 r#type: BindingType::UnitStruct(value),
475 });
476 }
477
478 pub fn register_enum_binding(
479 &mut self,
480 name: &'static str,
481 path: impl Into<Cow<'static, str>>,
482 value: EnumType,
483 ) {
484 self.insert_container(Container {
485 path: Path::new(path, "::"),
486 name,
487 r#type: BindingType::Enum(value),
488 });
489 }
490
491 pub fn into_entries(self) -> ContainerCollection {
492 ContainerCollection(self.0)
493 }
494
495 fn insert_container(&mut self, container: Container) {
496 let mut node = self.0.get_root_node().unwrap();
497 let node_id = {
498 let container_path = &container.path;
499 let mut parts = container_path
500 .parts()
501 .skip(1)
502 .map(|p| p.to_owned())
503 .peekable();
504 let path_exists = loop {
505 let part = parts.next();
506 let is_last = parts.peek().is_none();
507
508 if let Some(part) = part {
509 let node_ids = node.get_children_ids();
510 let child = node_ids.iter().find(|child| {
511 let node = self.0.get_node_by_id(child).unwrap();
512 matches!(node.get_value(), Some(NodeType::Module(p)) if p == part)
513 });
514
515 if let Some(child) = child {
516 if is_last {
517 break PathExists::Full(*child);
518 }
519
520 node = self.0.get_node_by_id(child).unwrap();
521 } else {
522 break PathExists::Partly(node.get_node_id(), part.into());
523 }
524 } else {
525 break PathExists::Full(node.get_node_id());
526 }
527 };
528
529 match path_exists {
530 PathExists::Full(node_id) => node_id,
531 PathExists::Partly(node_id, part) => {
532 let mut node = self
533 .0
534 .add_node(
535 Node::new_with_auto_id(Some(NodeType::Module(part.clone()))),
536 Some(&node_id),
537 )
538 .unwrap();
539
540 for part in parts {
541 node = self
542 .0
543 .add_node(
544 Node::new_with_auto_id(Some(NodeType::Module(part.clone().into()))),
545 Some(&node),
546 )
547 .unwrap();
548 }
549
550 node
551 }
552 }
553 };
554
555 self.0
556 .add_node(
557 Node::new_with_auto_id(Some(NodeType::Container(container))),
558 Some(&node_id),
559 )
560 .unwrap();
561 }
562}
563
564impl Default for BindingsRegistry {
565 fn default() -> Self {
566 let mut tree: Tree<NodeId, NodeType> = Tree::new(None);
567 tree.add_node(
568 Node::new_with_auto_id(Some(NodeType::Module("::".into()))),
569 None,
570 )
571 .unwrap();
572 Self(tree)
573 }
574}
575
576pub trait JsBindings {
577 fn create_bindings(registry: &mut BindingsRegistry);
578}
579
580#[cfg(test)]
581mod test {
582 use crate::registry::{
583 BindingsRegistry, EnumType, JsBindings, StructFields, StructType, TupleFields,
584 TupleStructType,
585 };
586
587 #[test]
588 fn test_registry_struct() {
589 #[allow(unused)]
590 struct Test {
591 a: u8,
592 b: u16,
593 c: &'static str,
594 }
595
596 impl JsBindings for Test {
597 fn create_bindings(registry: &mut BindingsRegistry) {
598 let mut ty = StructType::new();
599
600 ty.register_field::<u8>("a");
601 ty.register_field::<u16>("b");
602 ty.register_field::<&str>("c");
603
604 registry.register_struct_binding("Test", "", ty);
605 }
606 }
607
608 let mut registry = BindingsRegistry::default();
609 Test::create_bindings(&mut registry);
610 }
611
612 #[test]
613 fn test_registry_tuple_struct() {
614 #[allow(dead_code)]
615 struct Test(u8, &'static str, &'static [u8]);
616
617 impl JsBindings for Test {
618 fn create_bindings(registry: &mut BindingsRegistry) {
619 let mut ty = TupleStructType::new();
620
621 ty.register_field::<u8>();
622 ty.register_field::<&str>();
623 ty.register_field::<&[u8]>();
624
625 registry.register_tuple_struct_binding("Test", "", ty);
626 }
627 }
628
629 let mut registry = BindingsRegistry::default();
630 Test::create_bindings(&mut registry);
631 }
632
633 #[test]
634 fn test_registry_enum() {
635 #[allow(unused)]
636 enum Test {
637 A,
638 B(u8),
639 C { a: &'static str, b: u16 },
640 }
641
642 impl JsBindings for Test {
643 fn create_bindings(registry: &mut BindingsRegistry) {
644 let mut ty = EnumType::new();
645
646 ty.register_variant("A");
647
648 let mut fields = TupleFields::default();
649 fields.register_field::<u8>();
650 ty.register_variant_tuple("B", fields);
651
652 let mut fields = StructFields::default();
653 fields.register_field::<&str>("a");
654 fields.register_field::<u16>("b");
655 ty.register_unnamed_struct("C", fields);
656
657 registry.register_enum_binding("Test", "", ty);
658 }
659 }
660
661 let mut registry = BindingsRegistry::default();
662 Test::create_bindings(&mut registry);
663 }
664}