Skip to content

Commit 730eb99

Browse files
committed
ref: inlined code in local modules
1 parent d6eb485 commit 730eb99

File tree

8 files changed

+296
-24
lines changed

8 files changed

+296
-24
lines changed

Cargo.lock

Lines changed: 0 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[workspace]
2-
members = ["crates/cli", "crates/package", "crates/parser"]
2+
members = ["crates/cli", "crates/package"]
33
resolver = "3"
44

55
[workspace.package]

crates/cli/src/main.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use clap::{Parser as ClapParser, Subcommand};
22

3-
#[path = "../../parser/src/lib.rs"]
43
pub mod parser;
54

65
mod analyser;
File renamed without changes.

crates/package/src/lib.rs

Lines changed: 295 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,297 @@
1-
#[path = "../../parser/src/lib.rs"]
2-
mod parser;
3-
41
pub mod package {
5-
pub use super::parser::*;
2+
use serde::Serialize;
3+
use tucana::shared::{DefinitionDataType, FlowType, RuntimeFunctionDefinition};
4+
use std::io::ErrorKind;
5+
use std::{
6+
fs::{self, DirEntry},
7+
io::Error,
8+
path::Path,
9+
};
10+
11+
#[derive(Serialize, Clone, Debug)]
12+
pub struct DefinitionError {
13+
pub definition: String,
14+
pub definition_type: MetaType,
15+
pub error: String,
16+
}
17+
18+
#[derive(Debug)]
19+
pub struct Parser {
20+
pub features: Vec<Feature>,
21+
}
22+
23+
#[derive(Serialize, Clone, Debug)]
24+
pub struct Feature {
25+
pub name: String,
26+
pub data_types: Vec<DefinitionDataType>,
27+
pub flow_types: Vec<FlowType>,
28+
pub runtime_functions: Vec<RuntimeFunctionDefinition>,
29+
pub errors: Vec<DefinitionError>,
30+
}
31+
32+
impl Feature {
33+
fn new(name: String) -> Self {
34+
Feature {
35+
name,
36+
data_types: Vec::new(),
37+
flow_types: Vec::new(),
38+
runtime_functions: Vec::new(),
39+
errors: Vec::new(),
40+
}
41+
}
42+
}
43+
44+
impl Parser {
45+
pub fn from_path(path: &str) -> Option<Self> {
46+
let reader = Reader::from_path(path)?;
47+
48+
Some(Self::from_reader(reader))
49+
}
50+
51+
pub fn from_reader(reader: Reader) -> Self {
52+
let mut features: Vec<Feature> = vec![];
53+
54+
for meta in &reader.meta {
55+
let feature = features.iter_mut().find(|f| f.name == meta.name);
56+
57+
if let Some(existing) = feature {
58+
Parser::append_meta(existing, meta);
59+
} else {
60+
let mut new_feature = Feature::new(meta.name.clone());
61+
Parser::append_meta(&mut new_feature, meta);
62+
features.push(new_feature);
63+
}
64+
}
65+
66+
Parser { features }
67+
}
68+
69+
pub fn extract_identifier(definition: &str, meta_type: MetaType) -> String {
70+
let field_name = match meta_type {
71+
MetaType::DataType | MetaType::FlowType => "identifier",
72+
MetaType::RuntimeFunction => "runtime_name",
73+
};
74+
75+
// Look for the field pattern: "field_name": "value" or "field_name":"value"
76+
if let Some(start) = definition.find(&format!("\"{field_name}\"")) {
77+
// Find the colon after the field name
78+
if let Some(colon_pos) = definition[start..].find(':') {
79+
let after_colon = &definition[start + colon_pos + 1..];
80+
81+
// Skip whitespace and find the opening quote
82+
let trimmed = after_colon.trim_start();
83+
if let Some(stripped) = trimmed.strip_prefix('"') {
84+
// Find the closing quote
85+
if let Some(end_quote) = stripped.find('"') {
86+
return trimmed[1..end_quote + 1].to_string();
87+
}
88+
}
89+
}
90+
}
91+
92+
// Fallback: return the whole definition if identifier can't be extracted
93+
definition.to_string()
94+
}
95+
96+
fn append_meta(feature: &mut Feature, meta: &Meta) {
97+
let definition = meta.definition_string.as_str();
98+
match meta.r#type {
99+
MetaType::DataType => match serde_json::from_str::<DefinitionDataType>(definition) {
100+
Ok(data_type) => feature.data_types.push(data_type),
101+
Err(err) => feature.errors.push(DefinitionError {
102+
definition: Parser::extract_identifier(definition, MetaType::DataType),
103+
definition_type: MetaType::DataType,
104+
error: err.to_string(),
105+
}),
106+
},
107+
MetaType::FlowType => match serde_json::from_str::<FlowType>(definition) {
108+
Ok(flow_type) => feature.flow_types.push(flow_type),
109+
Err(err) => feature.errors.push(DefinitionError {
110+
definition: Parser::extract_identifier(definition, MetaType::FlowType),
111+
definition_type: MetaType::FlowType,
112+
error: err.to_string(),
113+
}),
114+
},
115+
MetaType::RuntimeFunction => {
116+
match serde_json::from_str::<RuntimeFunctionDefinition>(definition) {
117+
Ok(func) => feature.runtime_functions.push(func),
118+
Err(err) => feature.errors.push(DefinitionError {
119+
definition: Parser::extract_identifier(
120+
definition,
121+
MetaType::RuntimeFunction,
122+
),
123+
definition_type: MetaType::RuntimeFunction,
124+
error: err.to_string(),
125+
}),
126+
}
127+
}
128+
}
129+
}
130+
}
131+
132+
133+
#[derive(Serialize, Debug, Clone, Copy)]
134+
pub enum MetaType {
135+
FlowType,
136+
DataType,
137+
RuntimeFunction,
138+
}
139+
140+
impl std::fmt::Display for MetaType {
141+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
142+
match self {
143+
MetaType::FlowType => write!(f, "FlowType"),
144+
MetaType::DataType => write!(f, "DataType"),
145+
MetaType::RuntimeFunction => write!(f, "RuntimeFunction"),
146+
}
147+
}
148+
}
149+
150+
pub struct Reader {
151+
pub meta: Vec<Meta>,
152+
}
153+
154+
#[derive(Clone)]
155+
pub struct Meta {
156+
pub name: String,
157+
pub r#type: MetaType,
158+
pub definition_string: String,
159+
pub path: String,
160+
}
161+
162+
impl Meta {
163+
pub fn read_from_file<P>(name: String, r#type: MetaType, file_path: P) -> Result<Meta, Error>
164+
where
165+
P: AsRef<Path>,
166+
{
167+
let path = match file_path.as_ref().to_str() {
168+
Some(path) => path,
169+
None => return Err(Error::new(ErrorKind::InvalidInput, "Invalid path")),
170+
};
171+
172+
if !path.ends_with("json") {
173+
return Err(Error::new(
174+
ErrorKind::InvalidInput,
175+
format!(
176+
"File {} does not end with .json",
177+
file_path.as_ref().display()
178+
),
179+
));
180+
}
181+
182+
let content = match fs::read_to_string(&file_path) {
183+
Ok(content) => content,
184+
Err(err) => {
185+
println!("Error reading file: {err}");
186+
return Err(err);
187+
}
188+
};
189+
190+
Ok(Meta {
191+
name,
192+
r#type,
193+
definition_string: content,
194+
path: path.to_string(),
195+
})
196+
}
197+
}
198+
199+
/// Reader
200+
///
201+
/// Expecting the file system to look like:
202+
/// - <path>
203+
/// - <feature>
204+
/// - <flow_types>
205+
/// - <data_types>
206+
/// - <runtime_functions>
207+
/// - <feature>
208+
/// - <flow_types>
209+
/// - <data_types>
210+
/// - <runtime_functions>
211+
impl Reader {
212+
pub fn from_path(path: &str) -> Option<Reader> {
213+
let mut result: Vec<Meta> = vec![];
214+
215+
// Reading the path folder
216+
for feature_path in fs::read_dir(path).unwrap() {
217+
let feature_path_result = match feature_path {
218+
Ok(path) => path,
219+
Err(_) => continue,
220+
};
221+
222+
let feature_name = match get_file_name(&feature_path_result) {
223+
Some(file_name) => file_name,
224+
None => continue,
225+
};
226+
227+
// Reading the feature folder
228+
for type_path in fs::read_dir(feature_path_result.path()).unwrap() {
229+
let type_path_result = match type_path {
230+
Ok(path) => path,
231+
Err(_) => continue,
232+
};
233+
234+
let meta_type = match get_file_name(&type_path_result) {
235+
Some(name) => match name.as_str() {
236+
"flow_type" => MetaType::FlowType,
237+
"data_type" => MetaType::DataType,
238+
"runtime_definition" => MetaType::RuntimeFunction,
239+
_ => continue,
240+
},
241+
None => continue,
242+
};
243+
244+
// Reading the type folder
245+
for definition_path in fs::read_dir(type_path_result.path()).unwrap() {
246+
let definition_path_result = match definition_path {
247+
Ok(path) => path,
248+
Err(_) => continue,
249+
};
250+
251+
if definition_path_result.file_type().unwrap().is_file() {
252+
let meta = Meta::read_from_file(
253+
feature_name.clone(),
254+
meta_type,
255+
definition_path_result.path(),
256+
);
257+
258+
if let Ok(meta_result) = meta {
259+
result.push(meta_result);
260+
}
261+
} else {
262+
for sub_definition_path in
263+
fs::read_dir(definition_path_result.path()).unwrap()
264+
{
265+
let sub_definition_path_result = match sub_definition_path {
266+
Ok(path) => path,
267+
Err(_) => continue,
268+
};
269+
270+
let meta = Meta::read_from_file(
271+
feature_name.clone(),
272+
meta_type,
273+
sub_definition_path_result.path(),
274+
);
275+
276+
if let Ok(meta_result) = meta {
277+
result.push(meta_result);
278+
}
279+
}
280+
}
281+
}
282+
}
283+
}
284+
285+
Some(Reader { meta: result })
286+
}
287+
}
288+
289+
fn get_file_name(entry: &DirEntry) -> Option<String> {
290+
entry
291+
.file_name()
292+
.to_str()
293+
.map(|file_name| file_name.to_string())
294+
}
295+
296+
6297
}

crates/parser/Cargo.toml

Lines changed: 0 additions & 9 deletions
This file was deleted.

crates/parser/src/parser.rs

Whitespace-only changes.

crates/parser/src/reader.rs

Whitespace-only changes.

0 commit comments

Comments
 (0)