postcard_bindgen_core/
registry.rs

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)]
55// encoded into | variant index | (inner)
56pub struct EnumType {
57    pub variants: Vec<EnumVariant>,
58}
59
60impl EnumType {
61    pub fn new() -> Self {
62        Self::default()
63    }
64
65    // index is set based on order of variant registration
66    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    // for unnamed structs create struct with custom name ( __EnumName_Struct1)
127    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/// Wraps a tree of nodes that contain the bindings.
220///
221/// Can be build from a `BindingsRegistry` by calling [BindingsRegistry::into_entries()].
222#[derive(Debug, Clone)]
223pub struct ContainerCollection(Tree<NodeId, NodeType>);
224
225impl ContainerCollection {
226    /// Removes all module nodes and moves their children to the root node.
227    ///
228    /// Can be used to remove the module hierarchy.
229    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}