code0_definition_reader/
parser.rs1use 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 if let Some(start) = definition.find(&format!("\"{field_name}\"")) {
71 if let Some(colon_pos) = definition[start..].find(':') {
73 let after_colon = &definition[start + colon_pos + 1..];
74
75 let trimmed = after_colon.trim_start();
77 if let Some(stripped) = trimmed.strip_prefix('"') {
78 if let Some(end_quote) = stripped.find('"') {
80 return trimmed[1..end_quote + 1].to_string();
81 }
82 }
83 }
84 }
85
86 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}