Skip to content

Commit fb4468c

Browse files
committed
Pass result to error code
1 parent 743edac commit fb4468c

3 files changed

Lines changed: 118 additions & 15 deletions

File tree

src/main.rs

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,16 @@ extern crate serde_derive;
88
mod config;
99
mod constants;
1010
mod file_location;
11-
mod operation_result;
1211
mod page_index;
12+
mod operation_result;
13+
mod program_error;
1314

1415
use std::fs;
1516
use std::env;
1617
use std::path::{Path};
1718

1819
use crate::operation_result::*;
20+
use crate::program_error::*;
1921
use crate::page_index::*;
2022
use crate::config::*;
2123
use crate::file_location::*;
@@ -24,21 +26,29 @@ use toml::Value;
2426
use walkdir::{DirEntry, WalkDir};
2527
use yaml_rust::{YamlLoader};
2628

27-
fn main() -> Result<(), std::io::Error> {
29+
30+
fn main() -> Result<(), ProgramError> {
2831
let args: Vec<String> = env::args().collect();
2932
let config = Config::new(&args);
3033

3134
println!("Scanning {0}", &config.scan_path);
3235
let index = traverse_files(&Path::new(&config.scan_path));
33-
let index = serde_json::to_string(&index).expect("Unable to serialize page index");
36+
let error_count: usize = index.iter().filter(|e| e.is_err()).count();
37+
let index: Vec<PageIndex> = index.into_iter().filter_map(|a| a.ok()).collect();
38+
let index = serde_json::to_string(&index)?;
3439

3540
println!("Writing index to {0}", &config.index_path);
36-
fs::create_dir_all(Path::new(&config.index_path).with_file_name(constants::EMPTY_STRING)).expect("Error writing index");
41+
fs::create_dir_all(Path::new(&config.index_path).with_file_name(constants::EMPTY_STRING))?;
3742

38-
fs::write(config.index_path, index)
43+
fs::write(config.index_path, index)?;
44+
if error_count > 0 {
45+
Err(ProgramError::MetaError(MetaError::new(error_count, "Failed to process all content files")))
46+
} else {
47+
Ok(())
48+
}
3949
}
4050

41-
fn traverse_files(content_dir_path: &Path) -> Vec<PageIndex> {
51+
fn traverse_files(content_dir_path: &Path) -> Vec<Result<PageIndex, OperationResult>> {
4252
let mut index = Vec::new();
4353
for entry in WalkDir::new(content_dir_path)
4454
.into_iter()
@@ -48,12 +58,13 @@ fn traverse_files(content_dir_path: &Path) -> Vec<PageIndex> {
4858
if file_location.is_err() {
4959
continue;
5060
}
51-
52-
match process_file(&file_location.unwrap()) {
53-
Ok(page) => index.push(page),
54-
Err(OperationResult::Parse(ref err)) => println!("{}", err),
55-
Err(OperationResult::Io(ref err)) => println!("{}", err),
56-
_ => ()
61+
let process_result = process_file(&file_location.unwrap());
62+
match process_result {
63+
Err(OperationResult::Skip(ref err)) => println!("{}", err), // Skips don't need to be handled
64+
Err(OperationResult::Path(ref err)) => { println!("{}", err); index.push(process_result); },
65+
Err(OperationResult::Parse(ref err)) => { println!("{}", err); index.push(process_result); },
66+
Err(OperationResult::Io(ref err)) => { println!("{}", err); index.push(process_result); },
67+
Ok(_) => index.push(process_result)
5768
}
5869
} else if let Some(io_error) = entry.unwrap_err().into_io_error() {
5970
println!("Failed {}", io_error);
@@ -151,7 +162,7 @@ fn process_yaml_front_matter(contents: &str, file_location: &FileLocation) -> Re
151162
return Err(OperationResult::Parse(ParseError::new(&file_location.absolute_path, "Could not split on YAML fence.")))
152163
}
153164

154-
let front_matter = split_content[length - 2].trim();
165+
let front_matter = split_content[1].trim();
155166
let front_matter = YamlLoader::load_from_str(front_matter)
156167
.map_err(|_| ParseError::new(&file_location.absolute_path, "Failed to get front matter."))?;
157168
let front_matter = front_matter.first()

src/operation_result.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ pub struct Skip {
4646

4747
impl fmt::Display for Skip {
4848
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
49-
write!(f, "Skiping {}. {}", self.directory, self.reason)
49+
write!(f, "Skipping {}. {}", self.directory, self.reason)
5050
}
5151
}
5252

@@ -77,7 +77,7 @@ pub struct PathError {
7777

7878
impl fmt::Display for PathError {
7979
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
80-
write!(f, "Skiping {}. {}", self.directory, self.reason)
80+
write!(f, "Skipping {}. {}", self.directory, self.reason)
8181
}
8282
}
8383

src/program_error.rs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
use std::io;
2+
use std::error;
3+
use std::fmt;
4+
5+
#[derive(Debug)]
6+
pub struct MetaError {
7+
reason: String,
8+
count: usize
9+
}
10+
11+
impl fmt::Display for MetaError {
12+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
13+
write!(f, "Program Error {}: {}", self.reason, self.count)
14+
}
15+
}
16+
17+
impl error::Error for MetaError {
18+
fn description(&self) -> &str {
19+
&self.reason
20+
}
21+
22+
fn cause(&self) -> Option<&error::Error> {
23+
None
24+
}
25+
}
26+
27+
impl MetaError {
28+
pub fn new (count: usize, reason: &str) -> Self {
29+
Self {
30+
count: count,
31+
reason: reason.to_owned(),
32+
}
33+
}
34+
}
35+
36+
#[derive(Debug)]
37+
pub enum ProgramError {
38+
IoError(io::Error),
39+
MetaError(MetaError),
40+
SerializationError(serde_json::error::Error)
41+
}
42+
43+
impl From<io::Error> for ProgramError {
44+
fn from(err: io::Error) -> Self {
45+
ProgramError::IoError(err)
46+
}
47+
}
48+
49+
impl From<MetaError> for ProgramError {
50+
fn from(err: MetaError) -> Self {
51+
ProgramError::MetaError(err)
52+
}
53+
}
54+
55+
impl From<serde_json::error::Error> for ProgramError {
56+
fn from(err: serde_json::error::Error) -> Self {
57+
ProgramError::SerializationError(err)
58+
}
59+
}
60+
61+
impl fmt::Display for ProgramError {
62+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
63+
match *self {
64+
ProgramError::IoError(ref err) => write!(f, "IO error: {}", err),
65+
ProgramError::MetaError(ref err) => write!(f, "Serialization error: {}", err),
66+
ProgramError::SerializationError(ref err) => write!(f, "Serialization error: {}", err),
67+
}
68+
}
69+
}
70+
71+
impl error::Error for ProgramError {
72+
fn description(&self) -> &str {
73+
// Both underlying errors already impl `Error`, so we defer to their
74+
// implementations.
75+
match *self {
76+
ProgramError::IoError(ref err) => err.description(),
77+
ProgramError::MetaError(ref err) => err.description(),
78+
ProgramError::SerializationError(ref err) => err.description(),
79+
}
80+
}
81+
82+
fn cause(&self) -> Option<&error::Error> {
83+
match *self {
84+
// N.B. Both of these implicitly cast `err` from their concrete
85+
// types to a trait object `&Error`. This works because both error
86+
// types implement `Error`.
87+
ProgramError::IoError(ref err) => Some(err),
88+
ProgramError::MetaError(ref err) => Some(err),
89+
ProgramError::SerializationError(ref err) => Some(err)
90+
}
91+
}
92+
}

0 commit comments

Comments
 (0)