co_didcomm/messages/headers/
decorators.rs1use serde::{Deserialize, Serialize};
14use std::collections::HashMap;
15
16#[derive(Default, Deserialize, Serialize, PartialEq, Eq, Debug, Clone)]
19pub struct Thread {
20 pub thid: String,
22
23 pub pthid: String,
28
29 #[serde(skip_serializing_if = "Option::is_none")]
32 pub sender_order: Option<usize>,
33
34 #[serde(skip_serializing_if = "Option::is_none")]
36 pub received_orders: Option<HashMap<String, usize>>,
37
38 #[serde(skip_serializing_if = "Option::is_none")]
40 pub goal_code: Option<String>,
41}
42
43impl Thread {
44 pub fn implicit(message_id: &str) -> Self {
55 Self {
56 thid: message_id.into(),
57 sender_order: Some(0),
58 ..Default::default()
59 }
60 }
61
62 pub fn implicit_reply(thid: &str) -> Self {
73 Self {
74 thid: thid.into(),
75 ..Default::default()
76 }
77 }
78
79 pub fn effective_implicit_reply(thid: &str, sender: &str) -> Self {
81 let mut thr = Self::implicit_reply(thid);
82 thr.received_orders = Some(HashMap::from([(sender.into(), 0)]));
83 thr
84 }
85
86 pub fn is_implicit_reply(&self, message_id: &str) -> bool {
88 if self.thid != message_id {
89 match self.received_orders {
90 Some(ref recv_orders) => recv_orders.values().all(|&x| x == 0),
91 None => true,
92 }
93 } else {
94 false
95 }
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102 use fake::faker::internet::en;
103 use fake::uuid::UUIDv4;
104 use fake::Fake;
105 use quickcheck::{Arbitrary, Gen};
106 use uuid::Uuid;
107
108 #[test]
109 fn default_thread_can_be_created() {
110 let thr = Thread::default();
111 assert_eq!(thr.thid, thr.thid);
112 assert_eq!(thr.thid, thr.pthid);
113 assert!(thr.sender_order.is_none());
114 assert!(thr.received_orders.is_none());
115 assert!(thr.goal_code.is_none());
116 }
117
118 #[derive(Clone, Debug)]
119 struct Id(String);
120
121 #[derive(Clone, Debug)]
122 struct Header {
123 id: String,
124 sender: String,
125 }
126
127 impl Arbitrary for Id {
128 fn arbitrary(_: &mut Gen) -> Self {
129 let s: Uuid = UUIDv4.fake();
130 Self(s.to_string())
131 }
132 }
133
134 impl Arbitrary for Header {
135 fn arbitrary(_: &mut Gen) -> Self {
136 let s: Uuid = UUIDv4.fake();
137 Self {
138 id: s.to_string(),
139 sender: en::Username().fake(),
140 }
141 }
142 }
143 #[quickcheck_macros::quickcheck]
144 fn create_implicit_thread(id: Id) -> bool {
145 let thread = Thread::implicit(&id.0);
146 thread.thid == id.0
147 }
148
149 #[quickcheck_macros::quickcheck]
150 fn create_effective_implicit_reply_thread(header: Header) -> bool {
151 let thread = Thread::effective_implicit_reply(&header.id, &header.sender);
152 thread.thid == header.id
153 }
154
155 #[quickcheck_macros::quickcheck]
156 fn implicit_thread_without_received_order_successfully_detected(id: Id) -> bool {
157 let thr = Thread::implicit_reply(&id.0);
158 !thr.is_implicit_reply(&id.0)
159 }
160
161 #[quickcheck_macros::quickcheck]
162 fn non_implicit_thread_with_received_order_successfully_detected(id: Id) -> bool {
163 let mut thr = Thread::implicit_reply(&id.0);
164 thr.received_orders = Some(HashMap::from([("test".into(), 1)]));
165 !thr.is_implicit_reply(&id.0)
166 }
167}