From 4e4d7fecb17e061bef734e79d7c5075d23eebd43 Mon Sep 17 00:00:00 2001 From: sevenpigeons Date: Fri, 24 Apr 2026 21:32:05 -0400 Subject: [PATCH] structs for questions and themes and parsing of questions from text files --- Cargo.lock | 26 +++++++++++++++ Cargo.toml | 2 ++ src/main.rs | 49 ++++++++++++++-------------- src/util.rs | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 146 insertions(+), 25 deletions(-) create mode 100644 src/util.rs diff --git a/Cargo.lock b/Cargo.lock index 4698d33..1d4b7c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -348,6 +348,12 @@ dependencies = [ "rusttype", ] +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "http" version = "1.4.0" @@ -648,6 +654,8 @@ dependencies = [ "axum", "genpdf", "hyphenation", + "strum", + "strum_macros", "tokio", ] @@ -910,6 +918,24 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" +[[package]] +name = "strum" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" + +[[package]] +name = "strum_macros" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "syn" version = "1.0.109" diff --git a/Cargo.toml b/Cargo.toml index efb859f..fce12b3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,6 @@ edition = "2024" axum = "0.8.9" genpdf = { version = "0.2.0", features = ["hyphenation"] } hyphenation = { version = "0.8.4", features = ["embed_en-us"] } +strum = "0.28.0" +strum_macros = "0.28.0" tokio = { version = "1.52.1", features = ["rt-multi-thread"] } diff --git a/src/main.rs b/src/main.rs index 9495052..a8afef6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,11 @@ -use genpdf::{elements::{self, Paragraph}, fonts::FontData, style}; + +use std::str::FromStr; + +use genpdf::fonts::FontData; use hyphenation::{Load, Standard}; +mod util; +use crate::util::{Question, build_document_base, build_response}; use axum::{Router, extract::{Path, State}, http::{HeaderMap, header}, response::IntoResponse, routing::get}; @@ -22,39 +27,17 @@ async fn send_pdf( None => 1, }; - // this block should be really moved somewhere in a function - let mut doc = genpdf::Document::new(state.font_family); - doc.set_title("Test document title"); - let mut decorator = genpdf::SimplePageDecorator::new(); - decorator.set_margins(10); - doc.set_page_decorator(decorator); - let mut title = Paragraph::default(); - title.push_styled("title", style::Effect::Bold); - title.set_alignment(genpdf::Alignment::Center); - doc.push(title); - - - - doc.push(elements::Break::new(5)); - doc.set_hyphenator(state.hyphenator); + let mut doc = build_document_base(state); for i in 0..len { doc.push( genpdf::elements::Paragraph::new( format!("this is line {}", i) )); - - } - let mut headers = HeaderMap::new(); - headers.insert(header::CONTENT_TYPE, "application/pdf".parse().unwrap()); - - - let mut w: Vec = vec![]; - let _ = doc.render(&mut w).expect("error during pdf rendering"); - (headers,w.clone()) + build_response(doc) } @@ -84,3 +67,19 @@ async fn main() { } + + + + +#[test] +fn test_string_to_question_parse() { + let test_question = Question {subject:util::Subject::Math,theme:util::Theme::Math(util::MathTheme::ParametricEquations),text: "\n\n{{}} + y = 12".to_string()}; + let test_string: &str = "Math +ParametricEquations + + +{{}} + y = 12"; + + assert_eq!(Question::from_str(test_string).unwrap(),test_question); + +} diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 0000000..ef32dcf --- /dev/null +++ b/src/util.rs @@ -0,0 +1,94 @@ + +use std::str::FromStr; + +use axum::{http::{HeaderMap, header}, response::IntoResponse}; +use genpdf::{Document, elements::{self, Paragraph}, style}; +use crate::GenpdfState; +use strum_macros::{Display, EnumString}; + + +#[derive(Debug,EnumString,Display,PartialEq)] +pub enum Subject { + Math, + Physics +} + +#[derive(Debug,Display,PartialEq)] +pub enum Theme { + Math(MathTheme), + Physics(PhysTheme) +} + + +#[derive(Debug,EnumString,Display,PartialEq)] +pub enum PhysTheme { + LawMotion, + Momentum, + Energy, +} + +#[derive(Debug,EnumString,Display,PartialEq)] +pub enum MathTheme { + ParametricEquations, + InfiniteSequenceSeries, + PartialDerivatives, + +} + +#[derive(Debug,PartialEq)] +pub struct Question { + pub subject: Subject, + pub theme: Theme, + pub text: String +} + +#[derive(Debug,Display)] +pub enum QuestionParseError { + QuestionFileParseError, + Strum(strum::ParseError) +} + +impl FromStr for Question { + type Err = QuestionParseError; + fn from_str(s: &str) -> Result { + let l : Vec<&str> = s.splitn(3, '\n').collect(); + let subj: Subject = Subject::from_str(l[0]).unwrap(); + let theme: Theme = match subj { + Subject::Math => Theme::Math(MathTheme::from_str(l[1]).unwrap()), + Subject::Physics => Theme::Physics(PhysTheme::from_str(l[1]).unwrap()), + }; + if !l[2].is_empty() { + Ok(Question { subject: subj, theme: theme, text: l[2].to_string() }) + } else { + Err(QuestionParseError::QuestionFileParseError) + } + } + +} + + +pub fn build_document_base(state:GenpdfState) -> Document { + + let mut doc = genpdf::Document::new(state.font_family); + doc.set_title("Test document title"); + let mut decorator = genpdf::SimplePageDecorator::new(); + decorator.set_margins(10); + doc.set_page_decorator(decorator); + doc.set_hyphenator(state.hyphenator); + let mut title = Paragraph::default(); + title.push_styled("title", style::Effect::Bold); + title.set_alignment(genpdf::Alignment::Center); + doc.push(title); + + doc.push(elements::Break::new(5)); + doc +} + +pub fn build_response(doc: Document) -> impl IntoResponse { + + let mut headers = HeaderMap::new(); + headers.insert(header::CONTENT_TYPE, "application/pdf".parse().unwrap()); + let mut w: Vec = vec![]; + let _ = doc.render(&mut w).expect("error during pdf rendering"); + (headers,w) +} -- 2.51.2