You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
yuurei/src/post/mod.rs

148 lines
4.0 KiB

//! Structure for updating posts in-place
use super::*;
use std::{
fmt,
hash::{
Hash,Hasher,
},
};
use chrono::prelude::*;
/// Represents all valid timestamps for a post.
///
/// Usually in UTC, pls keep it in Utc...
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PostTimestamp<T = Utc>
where T: TimeZone,
{
pub opened: DateTime<T>,
pub closed: Option<DateTime<T>>,
pub last_edit: DateTime<T>,
}
impl<T> bytes::IntoBytes for PostTimestamp<T>
where T: TimeZone,
{
fn into_bytes(self) -> Box<[u8]> {
const ESIZE: usize = std::mem::size_of::<i64>();
let mut output =[0u8; ESIZE * 3];
use byteorder::{
LittleEndian,
WriteBytesExt,
};
//FUCK this. why is ther eno from_timestamp_nanos()!??? wtf is the point of the nanos versions then?????? fuck
output[..ESIZE] .as_mut().write_i64::<LittleEndian>(self.opened.timestamp()).unwrap();
output[ESIZE..ESIZE*2] .as_mut().write_i64::<LittleEndian>(self.closed.map(|x| x.timestamp()).unwrap_or(i64::MIN)).unwrap();
output[ESIZE*2..ESIZE*3].as_mut().write_i64::<LittleEndian>(self.last_edit.timestamp()).unwrap();
output.into()
}
}
impl bytes::FromBytes for PostTimestamp
{
type Error = bytes::SizeError;
fn from_bytes<U: AsRef<[u8]>>(bytes: U) -> Result<Self,Self::Error> {
const ESIZE: usize = std::mem::size_of::<i64>();
let bytes=bytes.as_ref();
if bytes.len() < ESIZE * 3 {
return Err(bytes::SizeError);
}
use byteorder::{
LittleEndian,
ReadBytesExt,
};
let opened = bytes.read_i64::<LittleEndian>().unwrap();
let closed = match bytes[ESIZE..].as_ref().read_i64::<LittleEndian>().unwrap() {
i64::MIN => None,
x => Some(x),
};
let last_edit = bytes[ESIZE*2..].as_ref().read_i64::<LittleEndian>().unwrap();
Ok(Self{
opened: DateTime::from_utc(NaiveDateTime::from_timestamp(opened, 0), Utc),
closed: closed.map(|closed| DateTime::from_utc(NaiveDateTime::from_timestamp(closed, 0), Utc)),
last_edit: DateTime::from_utc(NaiveDateTime::from_timestamp(last_edit, 0), Utc),
})
}
}
impl<Tz: TimeZone> Hash for PostTimestamp<Tz> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.opened.hash(state);
self.closed.hash(state);
self.last_edit.hash(state);
}
}
impl<T> fmt::Display for PostTimestamp<T>
where T: TimeZone,
T::Offset: fmt::Display
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
writeln!(f, " Opened - {}", self.opened)?;
writeln!(f, " Edited - {}", self.last_edit)?;
write!(f, " Closed - ")?;
if let Some(closed) = &self.closed {
writeln!(f, "{}", closed)?;
} else {
writeln!(f, "Stil open")?;
}
Ok(())
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
/// A closed and finished post. The inverse of `Imouto`.
pub struct Static
{
id: identity::PostID,
user: identity::User,
title: Option<String>,
karada: String,
timestamp: PostTimestamp,
/// Hash of the rest of the post data. . . .
hash: crypto::sha256::Sha256Hash,
}
use suspend::{
Suspendable,
SuspendStream,
};
#[async_trait]
impl Suspendable for Static
{
async fn suspend<S: SuspendStream +Send+Sync + ?Sized>(self, into: &mut S) -> Result<(), suspend::Error>
{
let mut output = suspend::Object::new();
output.insert_value("id", self.id);
output.insert_bool("Some(user-name)", self.user.name.is_some());
output.insert_string("user-name", self.user.name.unwrap_or_default());
output.insert_bool("Some(user-email)", self.user.email.is_some());
output.insert_string("user-email", self.user.email.unwrap_or_default());
//TODO: Tripcode
output.insert_bool("Some(title)", self.title.is_some());
output.insert_string("title", self.title.unwrap_or_default());
output.insert_string("body", self.karada);
output.insert_value("timestamp", self.timestamp);
output.insert_bytes("hash", self.hash);
into.set_object(output).await
}
async fn load<S: SuspendStream +Send+Sync+ ?Sized>(from: &mut S) -> Result<Self, suspend::Error>
{
fuck
todo!() //ehhhh... this is so dumb...
}
}