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    pub 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        let definition = meta.definition_string.as_str();
92        match meta.r#type {
93            MetaType::DataType => match serde_json::from_str::<DefinitionDataType>(definition) {
94                Ok(data_type) => feature.data_types.push(data_type),
95                Err(err) => feature.errors.push(DefinitionError {
96                    definition: Parser::extract_identifier(definition, MetaType::DataType),
97                    definition_type: MetaType::DataType,
98                    error: err.to_string(),
99                }),
100            },
101            MetaType::FlowType => match serde_json::from_str::<FlowType>(definition) {
102                Ok(flow_type) => feature.flow_types.push(flow_type),
103                Err(err) => feature.errors.push(DefinitionError {
104                    definition: Parser::extract_identifier(definition, MetaType::FlowType),
105                    definition_type: MetaType::FlowType,
106                    error: err.to_string(),
107                }),
108            },
109            MetaType::RuntimeFunction => {
110                match serde_json::from_str::<RuntimeFunctionDefinition>(definition) {
111                    Ok(func) => feature.runtime_functions.push(func),
112                    Err(err) => feature.errors.push(DefinitionError {
113                        definition: Parser::extract_identifier(
114                            definition,
115                            MetaType::RuntimeFunction,
116                        ),
117                        definition_type: MetaType::RuntimeFunction,
118                        error: err.to_string(),
119                    }),
120                }
121            }
122        }
123    }
124}