@ -16,6 +16,9 @@ const ID_MAX_LEN: usize = defaults::POST_ID_MAX_LEN;
/// String type that limits its bytes to the ID string max limit.
pub type IDMaxString = MaxLenString < ID_MAX_LEN > ;
/// The timestamp type used in posts
pub type PostTimestamp = chrono ::DateTime < defaults ::Timezone > ;
/// A single completed post
#[ derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize) ]
pub struct Post
@ -34,10 +37,39 @@ pub struct Post
/// Hash of the body
hash : Sha256Hash ,
/// When the post was created
created : PostTimestamp ,
/// When the post was last edited.
///
/// # Notes
/// Each new edit is pushed to the end of the vec, creation does not count as an edit.
edited : Vec < PostTimestamp > ,
/// Optional dynamic expiry duration.
expires_in : Option < tokio ::time ::Duration > ,
}
impl Post
{
/// Time since this post was created as a Chrono `Duration`.
pub fn time_since_creation ( & self ) -> chrono ::Duration
{
defaults ::Timezone ::now ( ) - self . created
}
/// Has this post expired?
///
/// Expired posts should be removed
pub fn expired ( & self ) -> bool
{
if let Ok ( dur ) = self . time_since_creation ( ) . to_std ( )
{
dur > = * self . expires_in . as_ref ( ) . unwrap_or ( & defaults ::POST_EXPIRE )
} else {
// Conversion failed. Expire the post
true
}
}
/// The user-set name for this post if there is one.
#[ inline ] pub fn own_name ( & self ) -> Option < & str >
{
@ -85,6 +117,10 @@ mod tests
body : unsafe { super ::PEMFormattedStr ::new_unchecked ( "test" ) . to_owned ( ) } , //temporary
signature : None ,
hash : Default ::default ( ) ,
created : crate ::defaults ::Timezone ::now ( ) ,
edited : Default ::default ( ) ,
expires_in : None ,
} ;
let post_json = serde_json ::to_vec ( & post ) . expect ( "Serialise" ) ;
println! ( "Post json: {}" , std ::str ::from_utf8 ( & post_json [ .. ] ) . unwrap ( ) ) ;