code0_definition_reader/
parser.rs

1use crate::reader::{MetaType, Reader};
2use serde::Serialize;
3use tucana::shared::{DefinitionDataType, FlowType, RuntimeFunctionDefinition};
4
5#[derive(Serialize, Clone, Debug)]
6pub struct DefinitionError {
7    pub definition: String,
8    pub definition_type: MetaType,
9    pub error: String,
10}
11
12#[derive(Debug)]
13pub struct Parser {
14    pub features: Vec<Feature>,
15}
16
17#[derive(Serialize, Clone, Debug)]
18pub struct Feature {
19    pub name: String,
20    pub data_types: Vec<DefinitionDataType>,
21    pub flow_types: Vec<FlowType>,
22    pub runtime_functions: Vec<RuntimeFunctionDefinition>,
23    pub errors: Vec<DefinitionError>,
24}
25
26impl Feature {
27    fn new(name: String) -> Self {
28        Feature {
29            name,
30            data_types: Vec::new(),
31            flow_types: Vec::new(),
32            runtime_functions: Vec::new(),
33            errors: Vec::new(),
34        }
35    }
36}
37
38impl Parser {
39    pub fn from_path(path: &str) -> Option<Self> {
40        let reader = Reader::from_path(path)?;
41
42        Some(Self::from_reader(reader))
43    }
44
45    pub fn from_reader(reader: Reader) -> Self {
46        let mut features: Vec<Feature> = vec![];
47
48        for meta in &reader.meta {
49            let feature = features.iter_mut().find(|f| f.name == meta.name);
50
51            if let Some(existing) = feature {
52                Parser::append_meta(existing, meta);
53            } else {
54                let mut new_feature = Feature::new(meta.name.clone());
55                Parser::append_meta(&mut new_feature, meta);
56                features.push(new_feature);
57            }
58        }
59
60        Parser { features }
61    }
62
63    fn extract_identifier(definition: &str, meta_type: MetaType) -> String {
64        let field_name = match meta_type {
65            MetaType::DataType | MetaType::FlowType => "identifier",
66            MetaType::RuntimeFunction => "runtime_name",
67        };
68
69        // Look for the field pattern: "field_name": "value" or "field_name":"value"
70        if let Some(start) = definition.find(&format!("\"{field_name}\"")) {
71            // Find the colon after the field name
72            if let Some(colon_pos) = definition[start..].find(':') {
73                let after_colon = &definition[start + colon_pos + 1..];
74
75                // Skip whitespace and find the opening quote
76                let trimmed = after_colon.trim_start();
77                if let Some(stripped) = trimmed.strip_prefix('"') {
78                    // Find the closing quote
79                    if let Some(end_quote) = stripped.find('"') {
80                        return trimmed[1..end_quote + 1].to_string();
81                    }
82                }
83            }
84        }
85
86        // Fallback: return the whole definition if identifier can't be extracted
87        definition.to_string()
88    }
89
90    fn append_meta(feature: &mut Feature, meta: &crate::reader::Meta) {
91        for definition in &meta.data {
92            match meta.r#type {
93                MetaType::DataType => {
94                    match serde_json::from_str::<DefinitionDataType>(definition) {
95                        Ok(data_type) => feature.data_types.push(data_type),
96                        Err(err) => feature.errors.push(DefinitionError {
97                            definition: Parser::extract_identifier(definition, MetaType::DataType),
98                            definition_type: MetaType::DataType,
99                            error: err.to_string(),
100                        }),
101                    }
102                }
103                MetaType::FlowType => match serde_json::from_str::<FlowType>(definition) {
104                    Ok(flow_type) => feature.flow_types.push(flow_type),
105                    Err(err) => feature.errors.push(DefinitionError {
106                        definition: Parser::extract_identifier(definition, MetaType::FlowType),
107                        definition_type: MetaType::FlowType,
108                        error: err.to_string(),
109                    }),
110                },
111                MetaType::RuntimeFunction => {
112                    match serde_json::from_str::<RuntimeFunctionDefinition>(definition) {
113                        Ok(func) => feature.runtime_functions.push(func),
114                        Err(err) => feature.errors.push(DefinitionError {
115                            definition: Parser::extract_identifier(
116                                definition,
117                                MetaType::RuntimeFunction,
118                            ),
119                            definition_type: MetaType::RuntimeFunction,
120                            error: err.to_string(),
121                        }),
122                    }
123                }
124            }
125        }
126    }
127}