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
use crate::{
data,
error::{ApiError, Result},
EndpointResult,
};
#[derive(serde_derive::Deserialize, Clone, Hash, Debug)]
pub(crate) struct Response {
ok: i32,
room: Vec<String>,
}
#[derive(Clone, Hash, Debug)]
pub struct WorldStartRoom {
pub room_name: String,
pub shard: Option<String>,
_non_exhaustive: (),
}
impl EndpointResult for WorldStartRoom {
type RequestResult = Response;
type ErrorResult = data::ApiError;
fn from_raw(raw: Response) -> Result<WorldStartRoom> {
let Response { ok, mut room } = raw;
if ok != 1 {
return Err(ApiError::NotOk(ok).into());
}
if room.len() < 1 {
return Err(ApiError::MalformedResponse(
"expected response.room to be an array of \
length 1 or greater, found empty array"
.into(),
)
.into());
}
let room_string = room.swap_remove(0);
let (room_name, shard) = match room_string.find('/') {
Some(split_at) => (
room_string[(split_at + 1)..].to_owned(),
Some(room_string[..split_at].to_owned()),
),
None => (room_string, None),
};
Ok(WorldStartRoom {
room_name: room_name,
shard: shard,
_non_exhaustive: (),
})
}
}
#[cfg(test)]
mod tests {
use super::WorldStartRoom;
use crate::EndpointResult;
use serde_json;
fn test_parse(json: serde_json::Value, expected_room: &str, expected_shard: Option<&str>) {
let response = serde_json::from_value(json).unwrap();
let result = WorldStartRoom::from_raw(response).unwrap();
assert_eq!(&result.room_name, expected_room);
assert_eq!(result.shard.as_ref().map(AsRef::as_ref), expected_shard);
}
#[test]
fn parse_sample() {
test_parse(
json! ({
"ok": 1,
"room": [
"shard0/E4S61",
]
}),
"E4S61",
Some("shard0"),
);
}
#[test]
fn parse_sample_no_shard() {
test_parse(
json! ({
"ok": 1,
"room": [
"E0N0",
]
}),
"E0N0",
None,
);
}
}