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
use serde::de::{Deserialize, Deserializer, Error};
#[derive(Clone, Hash, Debug)]
pub enum UserConsoleUpdate {
Messages {
log_messages: Vec<String>,
result_messages: Vec<String>,
shard: Option<String>,
},
Error {
message: String,
shard: Option<String>,
},
}
impl UserConsoleUpdate {
pub fn shard(&self) -> Option<&str> {
match *self {
UserConsoleUpdate::Messages { ref shard, .. } => shard.as_ref().map(|s| s.as_ref()),
UserConsoleUpdate::Error { ref shard, .. } => shard.as_ref().map(|s| s.as_ref()),
}
}
}
#[derive(serde_derive::Deserialize, Debug)]
struct InnerUpdateInnerMessages {
log: Vec<String>,
results: Vec<String>,
}
#[derive(serde_derive::Deserialize, Debug)]
struct InnerUpdateRepresentation {
error: Option<String>,
messages: Option<InnerUpdateInnerMessages>,
shard: Option<String>,
}
impl<'de> Deserialize<'de> for UserConsoleUpdate {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let intermediate = InnerUpdateRepresentation::deserialize(deserializer)?;
let InnerUpdateRepresentation {
error: error_opt,
messages: messages_opt,
shard,
} = intermediate;
let parsed = match (error_opt, messages_opt) {
(Some(e), None) => UserConsoleUpdate::Error {
message: e,
shard: shard,
},
(None, Some(m)) => UserConsoleUpdate::Messages {
log_messages: m.log,
result_messages: m.results,
shard: shard,
},
(Some(_), Some(_)) => {
return Err(D::Error::custom(
"expected either 'messages' property or 'error' property, not both",
));
}
(None, None) => {
return Err(D::Error::custom(
"expected either 'messages' property or 'error' property, neither found",
));
}
};
Ok(parsed)
}
}