use serde::Deserialize;
use thiserror::Error;
#[derive(Clone, Debug, PartialEq, Error)]
#[error("response did not indicate success: {0}")]
pub struct ResponseError(pub String);
#[derive(Clone, Debug, Deserialize, PartialEq)]
#[serde(tag = "status", content = "results")]
pub enum Response<T> {
#[serde(rename = "OK")]
Ok(T),
#[serde(rename = "DELAYED")]
Delayed(T),
#[serde(other)]
Err,
}
impl<T> Response<T> {
pub fn into_result(self) -> Result<T, ResponseError> {
match self {
Self::Ok(data) | Self::Delayed(data) => Ok(data),
Self::Err => Err(ResponseError("an unexpected status was reported".into())),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::from_str as from_json;
#[test]
fn decode_ok() {
let json = r#"{"status":"OK","results":["abc"]}"#;
let response = from_json::<Response<Vec<String>>>(json).unwrap();
match response {
Response::Ok(data) if data.as_slice() == ["abc"] => (),
_ => panic!("unexpected result"),
}
}
#[test]
fn decode_delayed() {
let json = r#"{"status":"DELAYED","results":["abc"]}"#;
let response = from_json::<Response<Vec<String>>>(json).unwrap();
match response {
Response::Delayed(data) if data.as_slice() == ["abc"] => (),
_ => panic!("unexpected result"),
}
}
}