|
|
@ -12,63 +12,15 @@ use chrono::prelude::*;
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// Usually in UTC, pls keep it in Utc...
|
|
|
|
/// Usually in UTC, pls keep it in Utc...
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
|
|
pub struct PostTimestamp<T = Utc>
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
|
|
where T: TimeZone,
|
|
|
|
pub struct PostTimestamp
|
|
|
|
{
|
|
|
|
{
|
|
|
|
pub opened: DateTime<T>,
|
|
|
|
pub opened: DateTime<Utc>,
|
|
|
|
pub closed: Option<DateTime<T>>,
|
|
|
|
pub closed: Option<DateTime<Utc>>,
|
|
|
|
pub last_edit: DateTime<T>,
|
|
|
|
pub last_edit: DateTime<Utc>,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl<T> bytes::IntoBytes for PostTimestamp<T>
|
|
|
|
impl Hash for PostTimestamp {
|
|
|
|
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) {
|
|
|
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
|
|
|
self.opened.hash(state);
|
|
|
|
self.opened.hash(state);
|
|
|
|
self.closed.hash(state);
|
|
|
|
self.closed.hash(state);
|
|
|
@ -76,9 +28,7 @@ impl<Tz: TimeZone> Hash for PostTimestamp<Tz> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl<T> fmt::Display for PostTimestamp<T>
|
|
|
|
impl fmt::Display for PostTimestamp
|
|
|
|
where T: TimeZone,
|
|
|
|
|
|
|
|
T::Offset: fmt::Display
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -94,7 +44,7 @@ where T: TimeZone,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
|
|
/// A closed and finished post. The inverse of `Imouto`.
|
|
|
|
/// A closed and finished post. The inverse of `Imouto`.
|
|
|
|
pub struct Static
|
|
|
|
pub struct Static
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -122,26 +72,12 @@ impl Suspendable for Static
|
|
|
|
async fn suspend<S: SuspendStream +Send+Sync + ?Sized>(self, into: &mut S) -> Result<(), suspend::Error>
|
|
|
|
async fn suspend<S: SuspendStream +Send+Sync + ?Sized>(self, into: &mut S) -> Result<(), suspend::Error>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let mut output = suspend::Object::new();
|
|
|
|
let mut output = suspend::Object::new();
|
|
|
|
output.insert_value("id", self.id);
|
|
|
|
output.insert("post-static", self);
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
into.set_object(output).await
|
|
|
|
}
|
|
|
|
}
|
|
|
|
async fn load<S: SuspendStream +Send+Sync+ ?Sized>(from: &mut S) -> Result<Self, suspend::Error>
|
|
|
|
async fn load<S: SuspendStream +Send+Sync+ ?Sized>(from: &mut S) -> Result<Self, suspend::Error>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
fuck
|
|
|
|
let mut input = from.get_object().await?.ok_or(suspend::Error::BadObject)?;
|
|
|
|
todo!() //ehhhh... this is so dumb...
|
|
|
|
input.try_get("post-static").ok_or(suspend::Error::BadObject)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|