diff --git a/src/config.rs b/src/config.rs index 0c510bb..7f0dbb4 100644 --- a/src/config.rs +++ b/src/config.rs @@ -55,4 +55,4 @@ impl Configuration { Environment::Development => Level::DEBUG, } } -} \ No newline at end of file +} diff --git a/src/error.rs b/src/error.rs index 4e8d70e..87024df 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,6 +1,6 @@ -use axum::http::{StatusCode}; +use axum::http::StatusCode; use axum::Json; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; pub enum TimeBannerError { ParseError(String), @@ -17,11 +17,25 @@ pub struct ErrorResponse { pub fn get_error_response(error: TimeBannerError) -> (StatusCode, Json) { let (code, message) = match error { - TimeBannerError::RenderError(msg) => (StatusCode::INTERNAL_SERVER_ERROR, format!("RenderError :: {}", msg)), - TimeBannerError::ParseError(msg) => (StatusCode::BAD_REQUEST, format!("ParserError :: {}", msg)), - TimeBannerError::RasterizeError(msg) => (StatusCode::INTERNAL_SERVER_ERROR, format!("RasterizeError :: {}", msg)), - TimeBannerError::NotFound => { (StatusCode::NOT_FOUND, "Not Found".to_string()) } + TimeBannerError::RenderError(msg) => ( + StatusCode::INTERNAL_SERVER_ERROR, + format!("RenderError :: {}", msg), + ), + TimeBannerError::ParseError(msg) => { + (StatusCode::BAD_REQUEST, format!("ParserError :: {}", msg)) + } + TimeBannerError::RasterizeError(msg) => ( + StatusCode::INTERNAL_SERVER_ERROR, + format!("RasterizeError :: {}", msg), + ), + TimeBannerError::NotFound => (StatusCode::NOT_FOUND, "Not Found".to_string()), }; - (code, Json(ErrorResponse { code: code.as_u16(), message })) -} \ No newline at end of file + ( + code, + Json(ErrorResponse { + code: code.as_u16(), + message, + }), + ) +} diff --git a/src/raster.rs b/src/raster.rs index 34cc7ad..f4724fe 100644 --- a/src/raster.rs +++ b/src/raster.rs @@ -1,5 +1,5 @@ -use resvg::{tiny_skia, usvg}; use resvg::usvg::{fontdb, TreeParsing, TreeTextToPath}; +use resvg::{tiny_skia, usvg}; #[derive(Debug, Clone)] pub struct RenderError { @@ -26,16 +26,18 @@ impl Rasterizer { fontdb.load_system_fonts(); fontdb.load_fonts_dir("./fonts"); - Self { - font_db: fontdb - } + Self { font_db: fontdb } } pub fn render(&self, svg_data: Vec) -> Result, RenderError> { let tree = { let opt = usvg::Options::default(); let mut tree_result = usvg::Tree::from_data(&*svg_data, &opt); - if tree_result.is_err() { return Err(RenderError { message: Some("Failed to parse".to_string()) }); } + if tree_result.is_err() { + return Err(RenderError { + message: Some("Failed to parse".to_string()), + }); + } let tree = tree_result.as_mut().unwrap(); tree.convert_text(&self.font_db); @@ -47,8 +49,8 @@ impl Rasterizer { let mut pixmap = tiny_skia::Pixmap::new(pixmap_size.width(), pixmap_size.height()).unwrap(); tree.render(tiny_skia::Transform::default(), &mut pixmap.as_mut()); - pixmap - .encode_png() - .map_err(|_| RenderError { message: Some("Failed to encode".to_string()) }) + pixmap.encode_png().map_err(|_| RenderError { + message: Some("Failed to encode".to_string()), + }) } -} \ No newline at end of file +} diff --git a/src/relative.rs b/src/relative.rs index eae0020..a160bd4 100644 --- a/src/relative.rs +++ b/src/relative.rs @@ -8,13 +8,14 @@ pub trait Months { impl Months for Duration { fn months(count: i32) -> Self { - Duration::milliseconds((Duration::days(1).num_milliseconds() as f64 * (365.25f64 / 12f64)) as i64) * count + Duration::milliseconds( + (Duration::days(1).num_milliseconds() as f64 * (365.25f64 / 12f64)) as i64, + ) * count } } - lazy_static! { - static ref FULL_RELATIVE_PATTERN : Regex = Regex::new(concat!( + static ref FULL_RELATIVE_PATTERN: Regex = Regex::new(concat!( "(?[-+])?", r"(?:(?\d+)\s?(?:y|yrs?|years?))?", r"(?:(?\d+)\s?(?:mon|months?))?", @@ -22,7 +23,9 @@ lazy_static! { r"(?:(?\d+)\s?(?:d|days?))?", r"(?:(?\d+)\s?(?:h|hrs?|hours?))?", r"(?:(?\d+)\s?(?:m|mins?|minutes?))?", - r"(?:(?\d+)\s?(?:s|secs?|seconds?))?")).unwrap(); + r"(?:(?\d+)\s?(?:s|secs?|seconds?))?" + )) + .unwrap(); } pub fn parse_duration(str: &str) -> Result { @@ -30,59 +33,115 @@ pub fn parse_duration(str: &str) -> Result { let mut value = Duration::zero(); if let Some(raw_year) = capture.name("year") { - value = value + match raw_year.as_str().parse::() { - Ok(year) => Duration::days(year * 365) + (if year > 0 { Duration::hours(6) * year as i32 } else { Duration::zero() }), - Err(e) => return Err(format!("Could not parse year from {} ({})", raw_year.as_str(), e.to_string())) - }; + value = value + + match raw_year.as_str().parse::() { + Ok(year) => { + Duration::days(year * 365) + + (if year > 0 { + Duration::hours(6) * year as i32 + } else { + Duration::zero() + }) + } + Err(e) => { + return Err(format!( + "Could not parse year from {} ({})", + raw_year.as_str(), + e.to_string() + )) + } + }; } if let Some(raw_month) = capture.name("month") { - value = value + match raw_month.as_str().parse::() { - Ok(month) => Duration::months(month), - Err(e) => return Err(format!("Could not parse month from {} ({})", raw_month.as_str(), e.to_string())) - }; + value = value + + match raw_month.as_str().parse::() { + Ok(month) => Duration::months(month), + Err(e) => { + return Err(format!( + "Could not parse month from {} ({})", + raw_month.as_str(), + e.to_string() + )) + } + }; } if let Some(raw_week) = capture.name("week") { - value = value + match raw_week.as_str().parse::() { - Ok(week) => Duration::days(7) * week as i32, - Err(e) => return Err(format!("Could not parse week from {} ({})", raw_week.as_str(), e.to_string())) - }; + value = value + + match raw_week.as_str().parse::() { + Ok(week) => Duration::days(7) * week as i32, + Err(e) => { + return Err(format!( + "Could not parse week from {} ({})", + raw_week.as_str(), + e.to_string() + )) + } + }; } if let Some(raw_day) = capture.name("day") { - value = value + match raw_day.as_str().parse::() { - Ok(day) => Duration::days(day), - Err(e) => return Err(format!("Could not parse day from {} ({})", raw_day.as_str(), e.to_string())) - }; + value = value + + match raw_day.as_str().parse::() { + Ok(day) => Duration::days(day), + Err(e) => { + return Err(format!( + "Could not parse day from {} ({})", + raw_day.as_str(), + e.to_string() + )) + } + }; } if let Some(raw_hour) = capture.name("hour") { - value = value + match raw_hour.as_str().parse::() { - Ok(hour) => Duration::hours(hour), - Err(e) => return Err(format!("Could not parse hour from {} ({})", raw_hour.as_str(), e.to_string())) - }; + value = value + + match raw_hour.as_str().parse::() { + Ok(hour) => Duration::hours(hour), + Err(e) => { + return Err(format!( + "Could not parse hour from {} ({})", + raw_hour.as_str(), + e.to_string() + )) + } + }; } if let Some(raw_minute) = capture.name("minute") { - value = value + match raw_minute.as_str().parse::() { - Ok(minute) => Duration::minutes(minute), - Err(e) => return Err(format!("Could not parse minute from {} ({})", raw_minute.as_str(), e.to_string())) - }; + value = value + + match raw_minute.as_str().parse::() { + Ok(minute) => Duration::minutes(minute), + Err(e) => { + return Err(format!( + "Could not parse minute from {} ({})", + raw_minute.as_str(), + e.to_string() + )) + } + }; } if let Some(raw_second) = capture.name("second") { - value = value + match raw_second.as_str().parse::() { - Ok(second) => Duration::seconds(second), - Err(e) => return Err(format!("Could not parse second from {} ({})", raw_second.as_str(), e.to_string())) - }; + value = value + + match raw_second.as_str().parse::() { + Ok(second) => Duration::seconds(second), + Err(e) => { + return Err(format!( + "Could not parse second from {} ({})", + raw_second.as_str(), + e.to_string() + )) + } + }; } if let Some(raw_sign) = capture.name("sign") { match raw_sign.as_str() { "-" => value = -value, "+" => (), - _ => return Err(format!("Could not parse sign from {}", raw_sign.as_str())) + _ => return Err(format!("Could not parse sign from {}", raw_sign.as_str())), }; } @@ -90,8 +149,8 @@ pub fn parse_duration(str: &str) -> Result { } mod tests { + use crate::relative::{parse_duration, Months}; use chrono::Duration; - use crate::relative::{Months, parse_duration}; #[test] fn parse_empty() { @@ -102,15 +161,37 @@ mod tests { #[test] fn parse_composite() { - assert_eq!(parse_duration("1y2mon3w4d5h6m7s"), Ok(Duration::hours(365 * 24 + 6) + Duration::months(2) + Duration::days(3 * 7 + 4) + Duration::hours(5) + Duration::minutes(6) + Duration::seconds(7))); - assert_eq!(parse_duration("19year33weeks4d9min"), Ok(Duration::hours((365 * 24 + 6) * 19) + Duration::days(33 * 7 + 4) + Duration::minutes(9))); + assert_eq!( + parse_duration("1y2mon3w4d5h6m7s"), + Ok(Duration::hours(365 * 24 + 6) + + Duration::months(2) + + Duration::days(3 * 7 + 4) + + Duration::hours(5) + + Duration::minutes(6) + + Duration::seconds(7)) + ); + assert_eq!( + parse_duration("19year33weeks4d9min"), + Ok(Duration::hours((365 * 24 + 6) * 19) + + Duration::days(33 * 7 + 4) + + Duration::minutes(9)) + ); } #[test] fn parse_year() { - assert_eq!(parse_duration("1y"), Ok(Duration::days(365) + Duration::hours(6))); - assert_eq!(parse_duration("2year"), Ok(Duration::days(365 * 2) + Duration::hours(6 * 2))); - assert_eq!(parse_duration("144years"), Ok(Duration::days(365 * 144) + Duration::hours(6 * 144))); + assert_eq!( + parse_duration("1y"), + Ok(Duration::days(365) + Duration::hours(6)) + ); + assert_eq!( + parse_duration("2year"), + Ok(Duration::days(365 * 2) + Duration::hours(6 * 2)) + ); + assert_eq!( + parse_duration("144years"), + Ok(Duration::days(365 * 144) + Duration::hours(6 * 144)) + ); } #[test] diff --git a/src/template.rs b/src/template.rs index 4f9c869..1ac4048 100644 --- a/src/template.rs +++ b/src/template.rs @@ -1,7 +1,7 @@ use chrono::{DateTime, FixedOffset, Utc}; -use timeago::Formatter; -use tera::{Context, Tera}; use lazy_static::lazy_static; +use tera::{Context, Tera}; +use timeago::Formatter; lazy_static! { static ref TEMPLATES: Tera = { @@ -10,7 +10,7 @@ lazy_static! { let names: Vec<&str> = t.get_template_names().collect(); println!("{} templates found ([{}]).", names.len(), names.join(", ")); t - }, + } Err(e) => { println!("Parsing error(s): {}", e); ::std::process::exit(1); @@ -37,11 +37,14 @@ pub fn render_template(context: RenderContext) -> Result { let mut template_context = Context::new(); let formatter = Formatter::new(); - template_context.insert("text", match context.output_form { - OutputForm::Relative => formatter.convert_chrono(context.value, Utc::now()), - OutputForm::Absolute => context.value.to_rfc3339() - }.as_str()); + template_context.insert( + "text", + match context.output_form { + OutputForm::Relative => formatter.convert_chrono(context.value, Utc::now()), + OutputForm::Absolute => context.value.to_rfc3339(), + } + .as_str(), + ); TEMPLATES.render("basic.svg", &template_context) } -