use crate::{
data::{self, RoomName, RoomState},
decoders::optional_timespec_seconds,
error::{ApiError, Result},
EndpointResult,
};
#[derive(serde_derive::Deserialize, Clone, Hash, Debug)]
pub(crate) struct Response {
ok: i32,
room: Option<InnerRoom>,
}
#[derive(serde_derive::Deserialize, Clone, Hash, Debug)]
struct InnerRoom {
_id: String,
status: String,
#[serde(with = "optional_timespec_seconds")]
#[serde(default)]
novice: Option<time::Timespec>,
#[serde(rename = "openTime")]
#[serde(with = "optional_timespec_seconds")]
#[serde(default)]
open_time: Option<time::Timespec>,
}
#[derive(Serialize, Deserialize, Clone, Hash, Debug)]
pub struct RoomStatus {
pub room_name: Option<RoomName>,
pub state: RoomState,
#[serde(skip)]
_non_exhaustive: (),
}
impl EndpointResult for RoomStatus {
type RequestResult = Response;
type ErrorResult = data::ApiError;
fn from_raw(raw: Response) -> Result<RoomStatus> {
let Response { ok, room } = raw;
if ok != 1 {
return Err(ApiError::NotOk(ok).into());
}
let InnerRoom {
_id: room_name,
status,
novice,
open_time,
} = match room {
Some(v) => v,
None => {
return Ok(RoomStatus {
room_name: None,
state: RoomState::non_existant(),
_non_exhaustive: (),
});
}
};
if status != "normal" {
return Err(ApiError::MalformedResponse(format!(
"expected room status to be \"normal\", \
found \"{}\".",
&status
))
.into());
}
let state = RoomState::from_data(time::get_time(), novice, open_time)?;
Ok(RoomStatus {
room_name: Some(RoomName::new(&room_name)?),
state: state,
_non_exhaustive: (),
})
}
}
#[cfg(test)]
mod tests {
use super::RoomStatus;
use crate::EndpointResult;
use serde_json;
fn test_parse(json: serde_json::Value) {
let response = serde_json::from_value(json).unwrap();
let _ = RoomStatus::from_raw(response).unwrap();
}
#[test]
fn parse_sample_novice_room() {
test_parse(json! ({
"ok": 1,
"room": {
"_id": "W6S83",
"status": "normal",
"novice": 1488394267175i64
}
}));
}
#[test]
fn parse_sample_highway_room() {
test_parse(json! ({
"ok": 1,
"room": {
"_id": "E0N0",
"status": "normal"
}
}));
}
#[test]
fn parse_sample_center_novice_room() {
test_parse(json! ({
"ok": 1,
"room": {
"_id": "E15N51",
"status": "normal",
"openTime": "1474674699273",
"novice": 1475538699273i64
}
}));
}
}