ssd_core/
helper.rs

1use std::collections::HashMap;
2use std::path::PathBuf;
3
4use serde::{Deserialize, Serialize};
5
6use ssd_data::{Namespace, SsdModule, TypeName};
7
8#[derive(Serialize, Deserialize, Hash, Eq, PartialEq)]
9#[serde(untagged)]
10enum StringOrVec {
11    String(String),
12    Vec(Vec<String>),
13}
14
15pub fn print_or_write(out: Option<PathBuf>, result: &str) -> anyhow::Result<()> {
16    if let Some(out) = out {
17        std::fs::write(out, result)?;
18    } else {
19        println!("{result}");
20    }
21    Ok(())
22}
23
24pub fn parse_raw_data(file: PathBuf) -> anyhow::Result<serde_value::Value> {
25    let content = std::fs::read_to_string(file)?;
26    let result = serde_json::from_str(&content)
27        .or_else(|_| toml::from_str(&content))
28        .or_else(|_| serde_yaml::from_str(&content))
29        .or_else(|_| rsn::from_str(&content));
30    #[cfg(feature = "ron")]
31    let result = result.or_else(|_| ron::from_str(&content));
32    Ok(result?)
33}
34
35#[cfg(not(feature = "_bin"))]
36pub fn update_types(mut module: SsdModule, typemap: &str) -> anyhow::Result<SsdModule> {
37    let mappings: HashMap<StringOrVec, StringOrVec> = toml::from_str(typemap)?;
38    let mappings: HashMap<String, String> = mappings
39        .iter()
40        .map(|(k, v)| match (k, v) {
41            (StringOrVec::Vec(k), StringOrVec::Vec(v)) => (k.join("::"), v.join("::")),
42            (StringOrVec::Vec(k), StringOrVec::String(v)) => (k.join("::"), v.clone()),
43            (StringOrVec::String(k), StringOrVec::Vec(v)) => (k.clone(), v.join("::")),
44            (StringOrVec::String(k), StringOrVec::String(v)) => (k.clone(), v.clone()),
45        })
46        .collect();
47    for (_dt_name, dt) in &mut module.data_types {
48        for (_name, prop) in &mut dt.properties {
49            let name = prop.typ.to_string();
50            if let Some(v) = mappings.get(&name) {
51                prop.typ = Namespace::new(v);
52            }
53        }
54    }
55
56    for (_service_name, service) in &mut module.services {
57        for (_handler_name, h) in &mut service.functions {
58            if let Some(TypeName {
59                typ,
60                is_list,
61                count,
62                attributes,
63                comments,
64            }) = &h.return_type
65            {
66                let name = typ.to_string();
67                let mut comments = comments.clone();
68                if let Some(v) = mappings.get(&name) {
69                    h.return_type = Some(
70                        TypeName::new(Namespace::new(v), *is_list, *count, attributes.clone())
71                            .with_comments(&mut comments),
72                    );
73                }
74            }
75            for (_arg_name, arg) in &mut h.arguments {
76                let name = arg.typ.to_string();
77                if let Some(v) = mappings.get(&name) {
78                    arg.typ = Namespace::new(v);
79                }
80            }
81        }
82        for (_event_name, h) in &mut service.events {
83            for (_arg_name, arg) in &mut h.arguments {
84                let name = arg.typ.to_string();
85                if let Some(v) = mappings.get(&name) {
86                    arg.typ = Namespace::new(v);
87                }
88            }
89        }
90    }
91
92    Ok(module)
93}
94
95pub fn update_types_from_file(
96    mut module: SsdModule,
97    no_map: bool,
98    typemap: Option<PathBuf>,
99    script: Option<&PathBuf>,
100) -> anyhow::Result<SsdModule> {
101    if let (false, Some(map_file)) = (
102        no_map,
103        typemap.or_else(|| {
104            script.and_then(|script| {
105                let mut typemap = script.clone();
106                typemap.set_extension("tym");
107                typemap.exists().then_some(typemap)
108            })
109        }),
110    ) {
111        let mappings: HashMap<StringOrVec, StringOrVec> =
112            toml::from_str(&std::fs::read_to_string(map_file)?)?;
113        let mappings: HashMap<String, String> = mappings
114            .iter()
115            .map(|(k, v)| match (k, v) {
116                (StringOrVec::Vec(k), StringOrVec::Vec(v)) => (k.join("::"), v.join("::")),
117                (StringOrVec::Vec(k), StringOrVec::String(v)) => (k.join("::"), v.clone()),
118                (StringOrVec::String(k), StringOrVec::Vec(v)) => (k.clone(), v.join("::")),
119                (StringOrVec::String(k), StringOrVec::String(v)) => (k.clone(), v.clone()),
120            })
121            .collect();
122        for (_dt_name, dt) in &mut module.data_types {
123            for (_name, prop) in &mut dt.properties {
124                let name = prop.typ.to_string();
125                if let Some(v) = mappings.get(&name) {
126                    prop.typ = Namespace::new(v);
127                }
128            }
129        }
130
131        for (_service_name, service) in &mut module.services {
132            for (_handler_name, h) in &mut service.functions {
133                if let Some(TypeName {
134                    typ,
135                    is_list,
136                    count,
137                    attributes,
138                    comments,
139                }) = &h.return_type
140                {
141                    let name = typ.to_string();
142                    let mut comments = comments.clone();
143                    if let Some(v) = mappings.get(&name) {
144                        h.return_type = Some(
145                            TypeName::new(Namespace::new(v), *is_list, *count, attributes.clone())
146                                .with_comments(&mut comments),
147                        );
148                    }
149                }
150                for (_arg_name, arg) in &mut h.arguments {
151                    let name = arg.typ.to_string();
152                    if let Some(v) = mappings.get(&name) {
153                        arg.typ = Namespace::new(v);
154                    }
155                }
156            }
157            for (_event_name, h) in &mut service.events {
158                for (_arg_name, arg) in &mut h.arguments {
159                    let name = arg.typ.to_string();
160                    if let Some(v) = mappings.get(&name) {
161                        arg.typ = Namespace::new(v);
162                    }
163                }
164            }
165        }
166    }
167
168    Ok(module)
169}