code0_definition_reader/
reader.rs

1use serde::Serialize;
2use std::io::ErrorKind;
3use std::{
4    fs::{self, DirEntry},
5    io::Error,
6    path::Path,
7};
8
9#[derive(Serialize, Debug, Clone, Copy)]
10pub enum MetaType {
11    FlowType,
12    DataType,
13    RuntimeFunction,
14}
15
16impl std::fmt::Display for MetaType {
17    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18        match self {
19            MetaType::FlowType => write!(f, "FlowType"),
20            MetaType::DataType => write!(f, "DataType"),
21            MetaType::RuntimeFunction => write!(f, "RuntimeFunction"),
22        }
23    }
24}
25
26pub struct Reader {
27    pub meta: Vec<Meta>,
28}
29
30#[derive(Clone)]
31pub struct Meta {
32    pub name: String,
33    pub r#type: MetaType,
34    pub definition_string: String,
35    pub path: String,
36}
37
38impl Meta {
39    pub fn read_from_file<P>(name: String, r#type: MetaType, file_path: P) -> Result<Meta, Error>
40    where
41        P: AsRef<Path>,
42    {
43        let path = match file_path.as_ref().to_str() {
44            Some(path) => path,
45            None => return Err(Error::new(ErrorKind::InvalidInput, "Invalid path")),
46        };
47
48        if !path.ends_with("json") {
49            return Err(Error::new(
50                ErrorKind::InvalidInput,
51                format!(
52                    "File {} does not end with .json",
53                    file_path.as_ref().display()
54                ),
55            ));
56        }
57
58        let content = match fs::read_to_string(&file_path) {
59            Ok(content) => content,
60            Err(err) => {
61                println!("Error reading file: {err}");
62                return Err(err);
63            }
64        };
65
66        Ok(Meta {
67            name,
68            r#type,
69            definition_string: content,
70            path: path.to_string(),
71        })
72    }
73}
74
75/// Reader
76///
77/// Expecting the file system to look like:
78/// - <path>
79///   - <feature>
80///     - <flow_types>
81///     - <data_types>
82///     - <runtime_functions>
83///    - <feature>
84///     - <flow_types>
85///     - <data_types>
86///     - <runtime_functions>
87impl Reader {
88    pub fn from_path(path: &str) -> Option<Reader> {
89        let mut result: Vec<Meta> = vec![];
90
91        // Reading the path folder
92        for feature_path in fs::read_dir(path).unwrap() {
93            let feature_path_result = match feature_path {
94                Ok(path) => path,
95                Err(_) => continue,
96            };
97
98            let feature_name = match get_file_name(&feature_path_result) {
99                Some(file_name) => file_name,
100                None => continue,
101            };
102
103            // Reading the feature folder
104            for type_path in fs::read_dir(feature_path_result.path()).unwrap() {
105                let type_path_result = match type_path {
106                    Ok(path) => path,
107                    Err(_) => continue,
108                };
109
110                let meta_type = match get_file_name(&type_path_result) {
111                    Some(name) => match name.as_str() {
112                        "flow_type" => MetaType::FlowType,
113                        "data_type" => MetaType::DataType,
114                        "runtime_definition" => MetaType::RuntimeFunction,
115                        _ => continue,
116                    },
117                    None => continue,
118                };
119
120                // Reading the type folder
121                for definition_path in fs::read_dir(type_path_result.path()).unwrap() {
122                    let definition_path_result = match definition_path {
123                        Ok(path) => path,
124                        Err(_) => continue,
125                    };
126
127                    if definition_path_result.file_type().unwrap().is_file() {
128                        let meta = Meta::read_from_file(
129                            feature_name.clone(),
130                            meta_type,
131                            definition_path_result.path(),
132                        );
133
134                        if let Ok(meta_result) = meta {
135                            result.push(meta_result);
136                        }
137                    } else {
138                        for sub_definition_path in
139                            fs::read_dir(definition_path_result.path()).unwrap()
140                        {
141                            let sub_definition_path_result = match sub_definition_path {
142                                Ok(path) => path,
143                                Err(_) => continue,
144                            };
145
146                            let meta = Meta::read_from_file(
147                                feature_name.clone(),
148                                meta_type,
149                                sub_definition_path_result.path(),
150                            );
151
152                            if let Ok(meta_result) = meta {
153                                result.push(meta_result);
154                            }
155                        }
156                    }
157                }
158            }
159        }
160
161        Some(Reader { meta: result })
162    }
163}
164
165fn get_file_name(entry: &DirEntry) -> Option<String> {
166    entry
167        .file_name()
168        .to_str()
169        .map(|file_name| file_name.to_string())
170}