Skip to content

Commit 73e1283

Browse files
MecryTvMecryTv
authored andcommitted
[feat] custom Error Handling
1 parent 34a600d commit 73e1283

File tree

1 file changed

+106
-75
lines changed

1 file changed

+106
-75
lines changed

crates/package/src/lib.rs

Lines changed: 106 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,113 +1,144 @@
11
use serde::Deserialize;
22
use serde::de::DeserializeOwned;
3-
use std::path::Path;
3+
use std::path::{Path, PathBuf};
44
use std::{fs, io};
5-
use tucana::shared::{DefinitionDataType, FlowType, RuntimeFunctionDefinition};
5+
use tucana::shared::{DefinitionDataType, FlowType, RuntimeFunctionDefinition, Version};
66
use walkdir::WalkDir;
77

8-
#[derive(Deserialize, Debug)]
8+
#[derive(Deserialize, Debug, Clone)]
99
pub struct Feature {
1010
pub name: String,
1111
pub data_types: Vec<DefinitionDataType>,
1212
pub flow_types: Vec<FlowType>,
1313
pub functions: Vec<RuntimeFunctionDefinition>,
1414
}
1515

16-
pub fn read_features(path: &str) -> Result<Vec<Feature>, io::Error> {
17-
let definitions = Path::new(path);
16+
pub struct Reader {
17+
should_break: bool,
18+
accepted_features: Vec<String>,
19+
accepted_versions: Option<Version>,
20+
path: String,
21+
}
1822

19-
match read_feature_content(definitions) {
20-
Ok(features) => {
21-
log::info!("Loaded Successfully {} features", features.len());
22-
Ok(features)
23-
}
24-
Err(err) => {
25-
panic!("Cannot loaded content: {}", err)
26-
}
27-
}
23+
pub enum ReaderError {
24+
JsonError { path: PathBuf, error: serde_json::Error },
25+
ReadFeatureError { path: String, source: Box<ReaderError> },
26+
ReadDirectoryError { path: PathBuf, error: io::Error },
27+
ReadFileError { path: PathBuf, error: io::Error },
28+
DirectoryEntryError(io::Error),
2829
}
2930

30-
fn read_feature_content(dir: &Path) -> Result<Vec<Feature>, io::Error> {
31-
let mut features: Vec<Feature> = Vec::new();
32-
let readdir = match fs::read_dir(dir) {
33-
Ok(readdir) => readdir,
34-
Err(err) => {
35-
log::error!("Failed to read directory {}: {}", dir.display(), err);
36-
return Err(err);
31+
impl Reader {
32+
pub fn read_features(&self, path: &str) -> Result<Vec<Feature>, ReaderError> {
33+
let definitions = Path::new(path);
34+
35+
match self.read_feature_content(definitions) {
36+
Ok(features) => {
37+
log::info!("Loaded Successfully {} features", features.len());
38+
Ok(features)
39+
}
40+
Err(err) => {
41+
log::error!("Failed to read features from {}", path);
42+
Err(ReaderError::ReadFeatureError {
43+
path: path.to_string(),
44+
source: Box::new(err),
45+
})
46+
}
3747
}
38-
};
48+
}
3949

40-
for entry_result in readdir {
41-
let entry = match entry_result {
42-
Ok(entry) => entry,
50+
fn read_feature_content(&self, dir: &Path) -> Result<Vec<Feature>, ReaderError> {
51+
let mut features: Vec<Feature> = Vec::new();
52+
let readdir = match fs::read_dir(dir) {
53+
Ok(readdir) => readdir,
4354
Err(err) => {
44-
log::error!("Failed to read directory entry: {}", err);
45-
continue;
55+
log::error!("Failed to read directory {}: {}", dir.display(), err);
56+
return Err(ReaderError::ReadDirectoryError {
57+
path: dir.to_path_buf(),
58+
error: err,
59+
});
4660
}
4761
};
4862

49-
let path = entry.path();
63+
for entry_result in readdir {
64+
let entry = match entry_result {
65+
Ok(entry) => entry,
66+
Err(err) => {
67+
log::error!("Failed to read directory entry: {}", err);
68+
return Err(ReaderError::DirectoryEntryError(err));
69+
}
70+
};
5071

51-
if path.is_dir() {
52-
let feature_name = path
53-
.file_name()
54-
.unwrap_or_default()
55-
.to_string_lossy()
56-
.to_string();
72+
let path = entry.path();
5773

58-
let data_types_path = path.join("data_type");
59-
let data_types: Vec<DefinitionDataType> = collect_definitions(&data_types_path)?;
74+
if path.is_dir() {
75+
let feature_name = path
76+
.file_name()
77+
.unwrap_or_default()
78+
.to_string_lossy()
79+
.to_string();
6080

61-
let flow_types_path = path.join("flow_type");
62-
let flow_types: Vec<FlowType> = collect_definitions(&flow_types_path)?;
81+
let data_types_path = path.join("data_type");
82+
let data_types: Vec<DefinitionDataType> = self.collect_definitions(&data_types_path)?;
6383

64-
let functions_path = path.join("runtime_definition");
65-
let functions: Vec<RuntimeFunctionDefinition> = collect_definitions(&functions_path)?;
84+
let flow_types_path = path.join("flow_type");
85+
let flow_types: Vec<FlowType> = self.collect_definitions(&flow_types_path)?;
6686

67-
let feature = Feature {
68-
name: feature_name,
69-
data_types,
70-
flow_types,
71-
functions,
72-
};
87+
let functions_path = path.join("runtime_definition");
88+
let functions: Vec<RuntimeFunctionDefinition> = self.collect_definitions(&functions_path)?;
7389

74-
features.push(feature);
75-
}
76-
}
77-
78-
Ok(features)
79-
}
90+
let feature = Feature {
91+
name: feature_name,
92+
data_types,
93+
flow_types,
94+
functions,
95+
};
8096

81-
fn collect_definitions<T>(dir: &Path) -> Result<Vec<T>, io::Error>
82-
where
83-
T: DeserializeOwned,
84-
{
85-
let mut definitions = Vec::new();
97+
features.push(feature);
98+
}
99+
}
86100

87-
if !dir.exists() {
88-
return Ok(definitions);
101+
Ok(features)
89102
}
90103

91-
for entry in WalkDir::new(dir).into_iter().filter_map(Result::ok) {
92-
let path = entry.path();
104+
fn collect_definitions<T>(&self, dir: &Path) -> Result<Vec<T>, ReaderError>
105+
where
106+
T: DeserializeOwned,
107+
{
108+
let mut definitions = Vec::new();
93109

94-
if path.is_file() && path.extension().is_some_and(|ext| ext == "json") {
95-
let content = match fs::read_to_string(path) {
96-
Ok(content) => content,
97-
Err(err) => {
98-
log::error!("Failed to read file {}: {}", path.display(), err);
99-
continue;
100-
}
101-
};
110+
if !dir.exists() {
111+
return Ok(definitions);
112+
}
102113

103-
match serde_json::from_str::<T>(&content) {
104-
Ok(def) => definitions.push(def),
105-
Err(e) => {
106-
log::error!("Failed to parse JSON in file {}: {}", path.display(), e);
114+
for entry in WalkDir::new(dir).into_iter().filter_map(Result::ok) {
115+
let path = entry.path();
116+
117+
if path.is_file() && path.extension().is_some_and(|ext| ext == "json") {
118+
let content = match fs::read_to_string(path) {
119+
Ok(content) => content,
120+
Err(err) => {
121+
log::error!("Failed to read file {}: {}", path.display(), err);
122+
return Err(ReaderError::ReadFileError {
123+
path: path.to_path_buf(),
124+
error: err,
125+
})
126+
}
127+
};
128+
129+
match serde_json::from_str::<T>(&content) {
130+
Ok(def) => definitions.push(def),
131+
Err(e) => {
132+
log::error!("Failed to parse JSON in file {}: {}", path.display(), e);
133+
return Err(ReaderError::JsonError {
134+
path: path.to_path_buf(),
135+
error: e,
136+
});
137+
}
107138
}
108139
}
109140
}
110-
}
111141

112-
Ok(definitions)
142+
Ok(definitions)
143+
}
113144
}

0 commit comments

Comments
 (0)