use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Default, Deserialize, Serialize, PartialEq, Eq, Debug, Clone)]
pub struct Thread {
pub thid: String,
pub pthid: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub sender_order: Option<usize>,
#[serde(skip_serializing_if = "Option::is_none")]
pub received_orders: Option<HashMap<String, usize>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub goal_code: Option<String>,
}
impl Thread {
pub fn implicit(message_id: &str) -> Self {
Self {
thid: message_id.into(),
sender_order: Some(0),
..Default::default()
}
}
pub fn implicit_reply(thid: &str) -> Self {
Self {
thid: thid.into(),
..Default::default()
}
}
pub fn effective_implicit_reply(thid: &str, sender: &str) -> Self {
let mut thr = Self::implicit_reply(thid);
thr.received_orders = Some(HashMap::from([(sender.into(), 0)]));
thr
}
pub fn is_implicit_reply(&self, message_id: &str) -> bool {
if self.thid != message_id {
match self.received_orders {
Some(ref recv_orders) => recv_orders.values().all(|&x| x == 0),
None => true,
}
} else {
false
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use fake::faker::internet::en;
use fake::uuid::UUIDv4;
use fake::Fake;
use quickcheck::{Arbitrary, Gen};
use uuid::Uuid;
#[test]
fn default_thread_can_be_created() {
let thr = Thread::default();
assert_eq!(thr.thid, thr.thid);
assert_eq!(thr.thid, thr.pthid);
assert!(thr.sender_order.is_none());
assert!(thr.received_orders.is_none());
assert!(thr.goal_code.is_none());
}
#[derive(Clone, Debug)]
struct Id(String);
#[derive(Clone, Debug)]
struct Header {
id: String,
sender: String,
}
impl Arbitrary for Id {
fn arbitrary(_: &mut Gen) -> Self {
let s: Uuid = UUIDv4.fake();
Self(s.to_string())
}
}
impl Arbitrary for Header {
fn arbitrary(_: &mut Gen) -> Self {
let s: Uuid = UUIDv4.fake();
Self {
id: s.to_string(),
sender: en::Username().fake(),
}
}
}
#[quickcheck_macros::quickcheck]
fn create_implicit_thread(id: Id) -> bool {
let thread = Thread::implicit(&id.0);
thread.thid == id.0
}
#[quickcheck_macros::quickcheck]
fn create_effective_implicit_reply_thread(header: Header) -> bool {
let thread = Thread::effective_implicit_reply(&header.id, &header.sender);
thread.thid == header.id
}
#[quickcheck_macros::quickcheck]
fn implicit_thread_without_received_order_successfully_detected(id: Id) -> bool {
let thr = Thread::implicit_reply(&id.0);
!thr.is_implicit_reply(&id.0)
}
#[quickcheck_macros::quickcheck]
fn non_implicit_thread_with_received_order_successfully_detected(id: Id) -> bool {
let mut thr = Thread::implicit_reply(&id.0);
thr.received_orders = Some(HashMap::from([("test".into(), 1)]));
!thr.is_implicit_reply(&id.0)
}
}