mermaid_markdown_api/
scanner_pipeline.rs

1use crate::{
2    md_api::MdAPI,
3    objects::{
4        connection::{self, Connection, ConnectionType},
5        node::{ActionType, Node, ScopeType},
6    },
7    syntax::{flow_chart::FlowChart, FlowDirection},
8};
9use scanner_syn::contract_descriptor::{
10    ContractDescriptor, ContractInfo, DefaultContractDescriptor, FunctionInfo,
11};
12use std::{
13    ops::{Deref, DerefMut},
14    vec::Vec,
15};
16struct Connections(Vec<Connection>);
17impl Deref for Connections {
18    type Target = Vec<Connection>;
19
20    fn deref(&self) -> &Self::Target {
21        &self.0
22    }
23}
24
25impl DerefMut for Connections {
26    fn deref_mut(&mut self) -> &mut Self::Target {
27        &mut self.0
28    }
29}
30
31impl Into<ScopeType> for FunctionInfo {
32    fn into(self) -> ScopeType {
33        if self.is_public && !self.is_init && !self.is_payable {
34            return ScopeType::Public
35        }
36        if !self.is_public {
37            return ScopeType::Private
38        }
39        if self.is_trait_impl {
40            return ScopeType::Trait
41        }
42        if self.is_init {
43            return ScopeType::Initializer
44        }
45        if self.is_payable {
46            return ScopeType::Payable
47        } else {
48            ScopeType::Public
49        }
50    }
51}
52impl Into<ActionType> for FunctionInfo {
53    fn into(self) -> ActionType {
54        if self.is_event {
55            ActionType::Event
56        } else if self.is_mutable {
57            ActionType::Mutation
58        } else if self.is_process {
59            ActionType::Process
60        } else if self.is_view {
61            ActionType::View
62        } else {
63            ActionType::None
64        }
65    }
66}
67impl Into<ConnectionType> for FunctionInfo {
68    fn into(self) -> ConnectionType {
69        if self.is_event {
70            ConnectionType::Emission
71        } else if self.is_trait_impl {
72            ConnectionType::CrossContractConnection
73        } else {
74            ConnectionType::DirectConnection
75        }
76    }
77}
78
79impl From<Option<Vec<FunctionInfo>>> for Connections {
80    fn from(val: Option<Vec<FunctionInfo>>) -> Self {
81        if val.is_some() {
82            let finfo = val.unwrap();
83            if !finfo.is_empty() {
84                let inner = finfo
85                    .into_iter()
86                    .map(|ifn| -> Connection {
87                        Connection {
88                            connection_type: ifn.clone().into(),
89                            node: Node {
90                                name: ifn.name.clone(),
91                                scope: ifn.clone().into(),
92                                action: ifn.clone().into(),
93                                connections: Connections::from(ifn.clone().inner_calls).0,
94                            },
95                        }
96                    })
97                    .collect();
98                return Connections(inner);
99            }
100        }
101        Connections(Vec::new())
102    }
103}
104
105pub struct ScannerPipeline {
106    pub content: String,
107}
108impl ScannerPipeline {
109    pub fn from(contract: ContractInfo, flow_direction: FlowDirection) -> ScannerPipeline {
110        let mut hierarchy_tree_root = Node {
111            name: contract.contract_name.unwrap().replace(" ","-"),
112            scope: ScopeType::Contract,
113            action: ActionType::None,
114            connections: Vec::new(),
115        };
116        contract
117            .contract_metadata
118            .into_iter()
119            .enumerate()
120            .for_each(|(_, value)| {
121                hierarchy_tree_root
122                    .connections
123                    .extend(Connections::from(Some(value.fns)).0);
124            });
125
126        let mut api = MdAPI::<FlowChart>::new(flow_direction, hierarchy_tree_root);
127        let mut result = api.parse_hierarchy();
128
129        result.push_str("\n\tclassDef Public-Mutation fill:#12A5F1,stroke:#333,stroke-width:2px;");
130        result.push_str("\n\tclassDef Public-View fill:#12A5F1,stroke:#333,stroke-width:2px;");
131        result.push_str("\n\tclassDef Private-View fill:#858585,stroke:#333,stroke-width:2px;");
132
133        result.push_str("\n\tclassDef Private-Mutation fill:#858585,stroke:#333,stroke-width:1px;");
134        result.push_str("\n\tclassDef Public-Event fill:#FFDF80,stroke:#333,stroke-width:2px,stroke-dasharray: 4 4;");
135        result.push_str("\n\tclassDef Private-Event fill:#FFDF80,stroke:#333,stroke-width:1px,stroke-dasharray: 4 4;");
136        result.push_str("\n\tclassDef Private-None fill:#858585,stroke:#333,stroke-width:1px;");
137        result.push_str("\n\tclassDef Private-Process fill:#858585,stroke:#333,stroke-width:1px;");
138        result.push_str("\n\tclassDef Public-Process fill:#858585,stroke:#333,stroke-width:2px;");
139        result.push_str("\n\tclassDef Public-None fill:#858585,stroke:#333,stroke-width:2px;");
140        result.push_str("\n\tclassDef Initializer-None fill:#FFA080,stroke:#333,stroke-width:2px;");
141        result.push_str("\n\tclassDef Payable-None fill:#6AA84F,stroke:#333,stroke-width:2px;");
142        result.push_str("\n\tclassDef Payable-Mutation fill:#6AA84F,stroke:#333,stroke-width:2px;");
143        result.push_str("\n\tclassDef Contract-None fill:#C2D5E3,stroke:#333,stroke-width:2px;");
144
145        ScannerPipeline { content: result }
146    }
147}