This commit is contained in:
2026-01-12 14:50:20 +00:00
parent a059b91327
commit a5659dda04
7 changed files with 245 additions and 22 deletions

56
Cargo.lock generated
View File

@@ -541,6 +541,15 @@ dependencies = [
"syn",
]
[[package]]
name = "serde_spanned"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776"
dependencies = [
"serde_core",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.8"
@@ -622,6 +631,7 @@ name = "templateServe"
version = "0.1.0"
dependencies = [
"anyhow",
"bytes",
"http-body-util",
"hyper",
"macro_rules_attribute",
@@ -630,6 +640,7 @@ dependencies = [
"smol",
"smol-hyper",
"smol-macros",
"toml",
]
[[package]]
@@ -655,6 +666,45 @@ dependencies = [
"tokio",
]
[[package]]
name = "toml"
version = "0.9.11+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3afc9a848309fe1aaffaed6e1546a7a14de1f935dc9d89d32afd9a44bab7c46"
dependencies = [
"indexmap",
"serde_core",
"serde_spanned",
"toml_datetime",
"toml_parser",
"toml_writer",
"winnow",
]
[[package]]
name = "toml_datetime"
version = "0.7.5+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347"
dependencies = [
"serde_core",
]
[[package]]
name = "toml_parser"
version = "1.0.6+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44"
dependencies = [
"winnow",
]
[[package]]
name = "toml_writer"
version = "1.0.6+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607"
[[package]]
name = "tracing"
version = "0.1.44"
@@ -694,3 +744,9 @@ checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
dependencies = [
"windows-link",
]
[[package]]
name = "winnow"
version = "0.7.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829"

View File

@@ -7,6 +7,7 @@ edition = "2021"
[dependencies]
anyhow = "1.0.100"
bytes = "1.11.0"
http-body-util = "0.1.3"
hyper = { version = "1.8.1", features = ["http1", "http2", "server"] }
macro_rules_attribute = "0.2.2"
@@ -15,3 +16,4 @@ serde = { version = "1.0.228", features = ["derive"] }
smol = "2.0.2"
smol-hyper = "0.1.1"
smol-macros = "0.1.1"
toml = "0.9.11"

44
bleh.txt Normal file
View File

@@ -0,0 +1,44 @@
- templete-serve
- config.toml
- home
- id: "MAINHOME"
- type: root
- assets
- pngs & mp4's
- base
- config.toml
- id: "base"
- title: ""
- type: page
- path: Empty, Not meant to be visited
- comment: "Base page that others can extend from"
- include: [style.css] // <- FEATURE FOR LATER
- extras
- index.html
- home
- config.toml
- id: "mainHome"
- title: "home"
- type: page
- path: "/"
- extras
- web stamps
- extra data yk
- index.html
- second
- config.toml
- id: "secondPage"
- title: "bleh"
- type: page
- path: "/"
- extras
- web stamps
- extra data yk
- index.html
- 404
- config.toml
- id: "404page"
- title: "home"
- type: page
- path: "/404"
- index.html

83
src/loader.rs Normal file
View File

@@ -0,0 +1,83 @@
use std::future::IntoFuture;
use crate::AppState;
use anyhow::anyhow;
use minijinja::Value;
use serde::Deserialize;
use smol::{
fs::{self, DirEntry},
stream::StreamExt,
};
use toml::Table;
pub struct Page {
header: Header,
content: String,
}
#[derive(Deserialize, Debug)]
pub enum PageType {
// If root, the dir contains all the pages, if there are no dirs within the root, we can assume
// its empty
Root,
// Contains a single html
Page,
// Is template
Base,
}
#[derive(Deserialize, Debug)]
pub struct Header {
id: String,
// r#type: PageType,
r#type: String,
title: Option<String>,
path: Option<String>,
// TODO impl this later
// extras: Table,
}
#[derive(Deserialize, Debug)]
pub struct Root {
id: String,
// r#type: PageType,
r#type: String,
title: Option<String>,
path: Option<String>,
// TODO impl this later
// extras: Table,
}
impl AppState<'_> {
pub async fn load_from_fs(&mut self) -> anyhow::Result<()> {
let mut dir = fs::read_dir("./template-serve").await?;
// Find config.toml from within dir
let config = dir
.find(|x| x.as_ref().unwrap().file_name().eq("config.toml"))
.await
.unwrap()?;
while let Some(Ok(entry)) = dir.next().await {
if entry.file_type().await?.is_dir() {
let entry_opened = fs::read_dir(entry.path()).await?;
println!("Opened {}", entry.file_name().to_str().unwrap());
} else {
println!("Not parsing {}", entry.file_name().to_str().unwrap());
}
}
let config_file = fs::read(config.path()).await?;
let config_parsed: Root = toml::from_slice(config_file.as_slice())?;
Ok(())
}
}
// impl From<Table> for Value {
// fn from(value: Table) -> Self {
// Value {
// ..Default::default()
// }
// }
// }

View File

@@ -1,56 +1,78 @@
use std::net::{TcpListener, TcpStream};
use std::pin::Pin;
use std::string;
use std::sync::Arc;
use std::task::{Context, Poll};
use anyhow::Result;
use bytes::Bytes;
use http_body_util::Full;
use hyper::body::Incoming;
use hyper::service::service_fn;
use hyper::{Request, Response, Uri};
use hyper::{Request, Response};
use macro_rules_attribute::apply;
use smol::{future, io, prelude::*, Async, Executor};
use minijinja::{context, Environment};
use smol::{fs, io, prelude::*, Async, Executor};
use smol_hyper::rt::{FuturesIo, SmolTimer};
use smol_macros::main;
/// Serves a request and returns a response.
async fn serve(req: Request<Incoming>) -> Result<Response<Full<&'static [u8]>>> {
println!("Serving {}", req.uri());
let path = req.uri().path();
let reply = match path {
"/" => "mreow",
_ => "Invalid path!",
};
Ok(Response::new(Full::new(reply.as_bytes())))
mod loader;
use crate::loader::*;
struct AppState<'a> {
pages: Vec<Page>,
env: Environment<'a>,
}
/// Handle a new client.
async fn handle_client(client: Async<TcpStream>) -> Result<()> {
// Wrap it in TLS if necessary.
/// Serves a request and returns a response.
async fn serve(req: Request<Incoming>, state: Arc<AppState<'_>>) -> Result<Response<Full<Bytes>>> {
println!("Serving {}", req.uri());
let tmpl = state.env.get_template("hello").unwrap();
let guh = tmpl.render(context!(name => "meowmeowmeowmeow!")).unwrap();
let guh2 = state.env.get_template("meow").unwrap();
let guh3 = guh2.render(context!(meow => "meow")).unwrap();
let path = req.uri().path();
let reply: Bytes = match path {
"/" => guh.into(),
"/mreow" => guh3.into(),
_ => "Invalid path!".into(),
};
Ok(Response::new(Full::new(reply)))
}
async fn handle_client(client: Async<TcpStream>, state: Arc<AppState<'_>>) -> Result<()> {
let client = SmolStream::Plain(client);
// Build the server.
hyper::server::conn::http1::Builder::new()
.timer(SmolTimer::new())
.serve_connection(FuturesIo::new(client), service_fn(serve))
.serve_connection(
FuturesIo::new(client),
service_fn(move |req| serve(req, state.clone())),
)
.await?;
Ok(())
}
/// Listens for incoming connections and serves them.
async fn listen(ex: &Arc<Executor<'static>>, listener: Async<TcpListener>) -> Result<()> {
async fn listen(
ex: &Arc<Executor<'static>>,
listener: Async<TcpListener>,
state: Arc<AppState<'static>>,
) -> Result<()> {
// Format the full host address.
// println!("Listening on {}", host);
loop {
// Wait for a new client.
let (client, _) = listener.accept().await?;
let cloned_state = state.clone();
// Spawn a task to handle this connection.
ex.spawn({
async move {
if let Err(e) = handle_client(client).await {
if let Err(e) = handle_client(client, cloned_state).await {
println!("Error while handling client: {}", e);
}
}
@@ -59,11 +81,25 @@ async fn listen(ex: &Arc<Executor<'static>>, listener: Async<TcpListener>) -> Re
}
}
async fn init<'a>() -> Result<AppState<'a>> {
let mut env = Environment::new();
let mut pages: Vec<Page> = Vec::new();
let mut state: AppState = AppState { pages, env };
state.load_from_fs().await?;
Ok(state)
}
#[apply(main!)]
async fn main(ex: &Arc<Executor<'static>>) -> Result<()> {
// Start HTTP and HTTPS servers.
let _ = listen(ex, Async::<TcpListener>::bind(([127, 0, 0, 1], 8000))?).await;
print!("mroew");
let mut state = init().await?;
let _ = listen(
ex,
Async::<TcpListener>::bind(([127, 0, 0, 1], 8000))?,
Arc::new(state),
)
.await;
Ok(())
}

View File

@@ -0,0 +1,2 @@
id = "mainhome"
type = "Root"

View File