diff --git a/src/main.rs b/src/main.rs index b125f7b..42138e5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,19 +1,19 @@ use std::net::SocketAddr; -use axum::{Router, routing::get}; -use dotenvy::dotenv; +use crate::routes::{ + absolute_handler, fallback_handler, implicit_handler, index_handler, relative_handler, +}; +use axum::{routing::get, Router}; use config::Configuration; -use crate::routes::{relative_handler, implicit_handler, absolute_handler, index_handler, fallback_handler}; +use dotenvy::dotenv; -mod config; -mod raster; mod abbr; -mod routes; -mod parse; -mod template; +mod config; mod error; +mod raster; mod relative; - +mod routes; +mod template; #[tokio::main] async fn main() { @@ -43,4 +43,4 @@ async fn main() { .serve(app.into_make_service_with_connect_info::()) .await .unwrap(); -} \ No newline at end of file +} diff --git a/src/parse.rs b/src/parse.rs deleted file mode 100644 index 4f1aae3..0000000 --- a/src/parse.rs +++ /dev/null @@ -1,26 +0,0 @@ -use chrono::{DateTime, FixedOffset, Utc}; - -/// Split a path into a tuple of the preceding path and the extension. -/// Can handle paths with multiple dots (period characters). -/// Returns None if there is no extension. -/// Returns None if the preceding path is empty (for example, dotfiles like ".env"). -pub fn split_on_extension(path: &str) -> Option<(&str, &str)> { - let split = path.rsplit_once('.'); - if split.is_none() { return None; } - - // Check that the file is not a dotfile (.env) - if split.unwrap().0.len() == 0 { - return None; - } - - Some(split.unwrap()) -} - -pub fn parse_absolute(raw: String) -> Result<(DateTime, FixedOffset), String> { - let datetime_with_offset = DateTime::parse_from_rfc3339(&raw); - if datetime_with_offset.is_err() { - return Err("Failed to parse datetime".to_string()); - } - - Ok((datetime_with_offset.unwrap().with_timezone(&Utc), *(datetime_with_offset.unwrap().offset()))) -} \ No newline at end of file diff --git a/src/routes.rs b/src/routes.rs index 9b560df..38fa01f 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -1,16 +1,27 @@ -use axum::{http::StatusCode, response::IntoResponse}; -use axum::body::{Bytes, Full}; -use axum::extract::{Path}; -use axum::http::{header}; -use axum::response::{Redirect, Response}; -use chrono::{DateTime, NaiveDateTime, Offset, Utc}; use crate::error::{get_error_response, TimeBannerError}; +use axum::body::{Bytes, Full}; +use axum::extract::Path; +use axum::http::header; +use axum::response::{Redirect, Response}; +use axum::{http::StatusCode, response::IntoResponse}; +use chrono::{DateTime, NaiveDateTime, Offset, Utc}; - -use crate::parse::split_on_extension; use crate::raster::Rasterizer; -use crate::template::{OutputForm, render_template, RenderContext}; +use crate::template::{render_template, OutputForm, RenderContext}; +fn split_on_extension(path: &str) -> Option<(&str, &str)> { + let split = path.rsplit_once('.'); + if split.is_none() { + return None; + } + + // Check that the file is not a dotfile (.env) + if split.unwrap().0.len() == 0 { + return None; + } + + Some(split.unwrap()) +} fn parse_path(path: &str) -> (&str, &str) { split_on_extension(path) @@ -25,12 +36,20 @@ fn handle_rasterize(data: String, extension: &str) -> Result<(&str, Bytes), Time let renderer = Rasterizer::new(); let raw_image = renderer.render(data.into_bytes()); if raw_image.is_err() { - return Err(TimeBannerError::RasterizeError(raw_image.unwrap_err().message.unwrap_or("Unknown error".to_string()))); + return Err(TimeBannerError::RasterizeError( + raw_image + .unwrap_err() + .message + .unwrap_or("Unknown error".to_string()), + )); } Ok(("image/x-png", Bytes::from(raw_image.unwrap()))) } - _ => Err(TimeBannerError::RasterizeError(format!("Unsupported extension: {}", extension))) + _ => Err(TimeBannerError::RasterizeError(format!( + "Unsupported extension: {}", + extension + ))), } } @@ -51,7 +70,6 @@ pub async fn absolute_handler(Path(path): Path) -> impl IntoResponse { let (raw_time, extension) = parse_path(path.as_str()); } - // basic handler that responds with a static string pub async fn implicit_handler(Path(path): Path) -> impl IntoResponse { // Get extension if available @@ -60,13 +78,19 @@ pub async fn implicit_handler(Path(path): Path) -> impl IntoResponse { // Parse epoch let parsed_epoch = raw_time.parse::(); if parsed_epoch.is_err() { - return get_error_response(TimeBannerError::ParseError("Input could not be parsed into integer.".to_string())).into_response(); + return get_error_response(TimeBannerError::ParseError( + "Input could not be parsed into integer.".to_string(), + )) + .into_response(); } // Convert epoch to DateTime let naive_time = NaiveDateTime::from_timestamp_opt(parsed_epoch.unwrap(), 0); if naive_time.is_none() { - return get_error_response(TimeBannerError::ParseError("Input was not a valid DateTime".to_string())).into_response(); + return get_error_response(TimeBannerError::ParseError( + "Input was not a valid DateTime".to_string(), + )) + .into_response(); } let utc_time = DateTime::::from_utc(naive_time.unwrap(), Utc); @@ -85,10 +109,12 @@ pub async fn implicit_handler(Path(path): Path) -> impl IntoResponse { if rendered_template.is_err() { return Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) - .body(Full::from( - format!("Template Could Not Be Rendered :: {}", rendered_template.err().unwrap()) - )) - .unwrap().into_response(); + .body(Full::from(format!( + "Template Could Not Be Rendered :: {}", + rendered_template.err().unwrap() + ))) + .unwrap() + .into_response(); } let rasterize_result = handle_rasterize(rendered_template.unwrap(), extension); @@ -96,6 +122,6 @@ pub async fn implicit_handler(Path(path): Path) -> impl IntoResponse { Ok((mime_type, bytes)) => { (StatusCode::OK, [(header::CONTENT_TYPE, mime_type)], bytes).into_response() } - Err(e) => get_error_response(e).into_response() + Err(e) => get_error_response(e).into_response(), } -} \ No newline at end of file +}