1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
pub trait Job {
fn encode(&self) -> Vec<u8>;
fn decode(input: &[u8]) -> Self;
fn ack(&self) -> Vec<u8>;
fn run(&self) -> std::result::Result<(), Box<dyn std::error::Error>>;
}
#[cfg(test)]
mod tests {
use super::*;
use crate::*;
use rmp_serde as rmps;
enum MsgType {
Hello,
Unknown,
}
impl From<u8> for MsgType {
fn from(t: u8) -> MsgType {
match t {
0 => MsgType::Hello,
_ => MsgType::Unknown,
}
}
}
impl From<MsgType> for u8 {
fn from(t: MsgType) -> u8 {
match t {
MsgType::Hello => 0,
MsgType::Unknown => 255,
}
}
}
#[derive(Default, Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct Hello {
name: String,
age: u8,
}
impl Job for Hello {
fn encode(&self) -> Vec<u8> {
rmps::to_vec(&self).unwrap()
}
fn decode(input: &[u8]) -> Hello {
let hello: Hello = rmps::from_read(input).unwrap();
hello
}
fn ack(&self) -> Vec<u8> {
let name = &self.name;
let age = &self.age;
let ack_string = format!("Hello from {name}, aged {age}");
Vec::from(ack_string)
}
fn run(&self) -> std::result::Result<(), Box<dyn std::error::Error>> {
self.ack();
Ok(())
}
}
#[test]
fn test_job_encode_decode() {
let hello = Hello {
name: "Anthony J. Martinez".to_owned(),
age: 38,
};
let encoded = hello.encode();
let decoded = Hello::decode(&encoded);
assert_eq!(hello, decoded)
}
#[test]
fn test_job_ack() {
let hello = Hello {
name: "Anthony J. Martinez".to_owned(),
age: 38,
};
let hello_vec = hello.ack();
assert_eq!(
hello_vec,
Vec::from("Hello from Anthony J. Martinez, aged 38")
)
}
#[test]
fn test_job_run() {
let hello = Hello {
name: "Anthony J. Martinez".to_owned(),
age: 38,
};
assert!(hello.run().is_ok())
}
}