core: Incorporate code for custom error handling.

This commit is contained in:
Dorian 2019-08-30 09:27:45 -04:00
parent 443fd2bc36
commit a1df508e87
3 changed files with 66 additions and 19 deletions

35
src/errors.rs Normal file
View File

@ -0,0 +1,35 @@
use std::{error, fmt, io};
#[derive(Debug)]
pub enum DoubleError {
EmptyVec,
IO(io::Error),
}
impl fmt::Display for DoubleError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
DoubleError::EmptyVec => write!(f, "please use a vector with at least one element"),
// This is a wrapper, so defer to the underlying types' implementation of `fmt`.
DoubleError::IO(ref e) => e.fmt(f),
}
}
}
impl error::Error for DoubleError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match *self {
DoubleError::EmptyVec => None,
// The cause is the underlying implementation error type. Is implicitly
// cast to the trait object `&error::Error`. This works because the
// underlying type already implements the `Error` trait.
DoubleError::IO(ref e) => Some(e),
}
}
}
impl From<io::Error> for DoubleError {
fn from(err: io::Error) -> DoubleError {
DoubleError::IO(err)
}
}

View File

@ -12,6 +12,8 @@ use std::default::Default;
use chrono::{DateTime, Utc};
use serde_json::Value;
pub mod errors;
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Page {
pub slug: String,

View File

@ -22,7 +22,7 @@ use chrono::prelude::*;
use colored::Colorize;
use docopt::Docopt;
use env_logger::{Builder, Env};
use rookeries::{Page, Site};
use rookeries::{errors, Page, Site};
use serde_json::Value;
use std::collections::HashMap;
use std::ffi::OsString;
@ -124,7 +124,17 @@ fn main() {
}
if args.cmd_serve {
serve_site(&args);
match serve_site(&args) {
Ok(_) => {
header_message(&format!(
"Serving project at local port {}",
&args.flag_port.to_string().cyan()
));
}
Err(e) => {
fatal_error(e.into(), "Server failed!");
}
};
}
if args.cmd_build {
@ -160,7 +170,7 @@ fn fatal_condition(message: &str) -> ! {
std::process::exit(2);
}
fn serve_site(args: &Args) {
fn serve_site(args: &Args) -> Result<(), errors::DoubleError> {
// TODO: Add an option to open up a browser window using xdg-open.
// TODO: Create a file watcher to check for changes to the source files?
let project_directory = get_project_directory(&args);
@ -180,28 +190,28 @@ fn serve_site(args: &Args) {
x => x,
};
header_message(&format!(
"Serving project at local port {}",
port.to_string().cyan()
));
HttpServer::new(move || {
App::new()
.service(actix_files::Files::new("/", build_directory.clone()).index_file("index.html"))
.wrap(Logger::default())
})
.bind(format!("127.0.0.1:{}", port))
.unwrap_or_else(|err| {
let error_message = format!(
"The server could not to bind to port \"{}\". Try using a different port.",
port.to_string().red()
);
fatal_error(err.into(), &error_message);
})
.run()
.unwrap_or_else(|err| {
fatal_error(err.into(), "The server could not start!");
});
.and_then(|res| {
header_message(&format!(
"Serving project at local port {}",
port.to_string().cyan()
));
Ok(res)
})?
// .unwrap_or_else(|err| {
// let error_message = format!(
// "The server could not to bind to port \"{}\". Try using a different port.",
// port.to_string().red()
// );
// fatal_error(err.into(), &error_message);
// })
.run()?;
Ok(())
}
fn build_site(args: &Args) {