Always save comments

This commit is contained in:
p11 2023-07-19 21:10:56 +02:00
parent accd37204f
commit 4eb59a01b7
3 changed files with 101 additions and 2 deletions

7
Cargo.lock generated
View File

@ -2,6 +2,12 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "data-stream"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "405b47b778683e13f388382bf1fb59e54e1008a2e6d048fb2b63672632863c95"
[[package]] [[package]]
name = "formatting" name = "formatting"
version = "0.1.0" version = "0.1.0"
@ -78,6 +84,7 @@ dependencies = [
name = "pukram-server" name = "pukram-server"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"data-stream",
"maud", "maud",
"percent-encoding", "percent-encoding",
"pukram2html", "pukram2html",

View File

@ -7,3 +7,4 @@ edition = "2021"
percent-encoding = "2.3" percent-encoding = "2.3"
maud = "0.25.0" maud = "0.25.0"
pukram2html = { git = "https://gitlab.com/porky11/pukram2html" } pukram2html = { git = "https://gitlab.com/porky11/pukram2html" }
data-stream = "0.2.0"

View File

@ -2,10 +2,14 @@ use std::{
collections::{hash_map::Entry, HashMap}, collections::{hash_map::Entry, HashMap},
env, env,
fs::File, fs::File,
io::{prelude::*, BufReader}, io::{prelude::*, BufReader, Error, ErrorKind, Result},
net::{TcpListener, TcpStream}, net::{TcpListener, TcpStream},
}; };
use data_stream::{
collections::SizeSettings, default_settings::PortableSettings, from_stream, to_stream,
FromStream, ToStream,
};
use maud::html; use maud::html;
use percent_encoding::percent_decode_str; use percent_encoding::percent_decode_str;
use pukram2html::{convert, convert_extended, convert_subheader, Settings}; use pukram2html::{convert, convert_extended, convert_subheader, Settings};
@ -14,7 +18,12 @@ mod request;
use request::Request; use request::Request;
fn main() { fn main() {
let mut context = Context::default(); let mut context = File::open("context.dat")
.map(|mut file| {
from_stream::<PortableSettings, Context, _>(&mut file)
.unwrap_or_else(|_| panic!("Context file corrupted. Delete or repair it!"))
})
.unwrap_or_default();
let mut args = env::args(); let mut args = env::args();
args.next(); args.next();
let address = args.next().unwrap_or("127.0.0.1:8080".to_string()); let address = args.next().unwrap_or("127.0.0.1:8080".to_string());
@ -56,6 +65,81 @@ struct Context {
infos: HashMap<Box<str>, SiteInfo>, infos: HashMap<Box<str>, SiteInfo>,
} }
impl<S: SizeSettings> ToStream<S> for Context {
fn to_stream<W: Write>(&self, stream: &mut W) -> Result<()> {
S::size_to_stream(self.infos.len(), stream)?;
for (key, info) in &self.infos {
let key_bytes = key.as_bytes();
S::size_to_stream(key_bytes.len(), stream)?;
stream.write_all(key_bytes)?;
S::size_to_stream(info.comments.len(), stream)?;
for Comment { name, text } in &info.comments {
let name_bytes = name.as_bytes();
S::size_to_stream(name_bytes.len(), stream)?;
stream.write_all(name_bytes)?;
let text_bytes = text.as_bytes();
S::size_to_stream(text_bytes.len(), stream)?;
stream.write_all(text_bytes)?;
}
S::size_to_stream(info.visits, stream)?;
S::size_to_stream(info.up, stream)?;
S::size_to_stream(info.down, stream)?;
}
Ok(())
}
}
impl<S: SizeSettings> FromStream<S> for Context {
fn from_stream<R: Read>(stream: &mut R) -> Result<Self> {
let size = S::size_from_stream(stream)?;
let infos = (0..size)
.map(|_| {
let key_bytes = <Vec<_> as FromStream<S>>::from_stream(stream)?;
let key = std::str::from_utf8(&key_bytes)
.map_err(|e| Error::new(ErrorKind::InvalidData, e))?
.into();
let size = S::size_from_stream(stream)?;
let comments = (0..size)
.map(|_| {
let name_bytes = <Vec<_> as FromStream<S>>::from_stream(stream)?;
let name = std::str::from_utf8(&name_bytes)
.map_err(|e| Error::new(ErrorKind::InvalidData, e))?
.into();
let text_bytes = <Vec<_> as FromStream<S>>::from_stream(stream)?;
let text = std::str::from_utf8(&text_bytes)
.map_err(|e| Error::new(ErrorKind::InvalidData, e))?
.into();
Ok(Comment { name, text })
})
.collect::<Result<Vec<_>>>()?;
let visits = S::size_from_stream(stream)?;
let up = S::size_from_stream(stream)?;
let down = S::size_from_stream(stream)?;
Ok((
key,
SiteInfo {
comments,
visits,
up,
down,
},
))
})
.collect::<Result<HashMap<_, _>>>()?;
Ok(Self { infos })
}
}
impl Context { impl Context {
fn handle_connection(&mut self, mut stream: TcpStream) { fn handle_connection(&mut self, mut stream: TcpStream) {
let Some(request) = Request::from(&stream) else { let Some(request) = Request::from(&stream) else {
@ -294,5 +378,12 @@ impl Context {
let _ = writeln!(stream, "<hr>"); let _ = writeln!(stream, "<hr>");
let _ = writeln!(stream, "<a href=\"/{parent_path}\">&lt;&lt; Back</a>"); let _ = writeln!(stream, "<a href=\"/{parent_path}\">&lt;&lt; Back</a>");
if let Ok(mut file) = File::create("context.dat") {
if to_stream::<PortableSettings, _, _>(self, &mut file).is_err() {
eprintln!("Error saving data!");
eprintln!();
}
}
} }
} }