use serde::Deserialize;
use crate::error::ParseError;
use crate::types::FadeDuration;
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct FadeResponse {
fade: FadeValue,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(untagged)]
enum FadeValue {
Text(String),
Number(u8),
}
impl FadeResponse {
pub fn is_enabled(&self) -> Result<bool, ParseError> {
match &self.fade {
FadeValue::Text(s) => match s.to_uppercase().as_str() {
"ON" | "1" => Ok(true),
"OFF" | "0" => Ok(false),
_ => Err(ParseError::InvalidValue {
field: "Fade".to_string(),
message: format!("expected ON, OFF, 0, or 1, got '{s}'"),
}),
},
FadeValue::Number(n) => Ok(*n != 0),
}
}
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct FadeDurationResponse {
speed: u8,
}
impl FadeDurationResponse {
#[must_use]
pub fn raw_value(&self) -> u8 {
self.speed
}
pub fn duration(&self) -> Result<FadeDuration, ParseError> {
FadeDuration::from_raw(self.speed).map_err(|_| ParseError::InvalidValue {
field: "Speed".to_string(),
message: format!("expected 1-40, got {}", self.speed),
})
}
}
#[derive(Debug, Clone, Deserialize)]
pub struct StartupFadeResponse {
#[serde(rename = "SetOption91")]
set_option_91: SetOptionValue,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(untagged)]
enum SetOptionValue {
Text(String),
Number(u8),
}
impl StartupFadeResponse {
pub fn is_enabled(&self) -> Result<bool, ParseError> {
match &self.set_option_91 {
SetOptionValue::Text(s) => match s.to_uppercase().as_str() {
"ON" | "1" => Ok(true),
"OFF" | "0" => Ok(false),
_ => Err(ParseError::InvalidValue {
field: "SetOption91".to_string(),
message: format!("expected ON, OFF, 0, or 1, got '{s}'"),
}),
},
SetOptionValue::Number(n) => Ok(*n != 0),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn fade_response_on() {
let json = r#"{"Fade":"ON"}"#;
let response: FadeResponse = serde_json::from_str(json).unwrap();
assert!(response.is_enabled().unwrap());
}
#[test]
fn fade_response_off() {
let json = r#"{"Fade":"OFF"}"#;
let response: FadeResponse = serde_json::from_str(json).unwrap();
assert!(!response.is_enabled().unwrap());
}
#[test]
fn fade_response_numeric() {
let json = r#"{"Fade":1}"#;
let response: FadeResponse = serde_json::from_str(json).unwrap();
assert!(response.is_enabled().unwrap());
let json = r#"{"Fade":0}"#;
let response: FadeResponse = serde_json::from_str(json).unwrap();
assert!(!response.is_enabled().unwrap());
}
#[test]
fn fade_duration_response() {
let json = r#"{"Speed":20}"#;
let response: FadeDurationResponse = serde_json::from_str(json).unwrap();
assert_eq!(response.raw_value(), 20);
assert!(response.duration().is_ok());
}
#[test]
fn fade_duration_invalid() {
let json = r#"{"Speed":50}"#;
let response: FadeDurationResponse = serde_json::from_str(json).unwrap();
assert!(response.duration().is_err());
}
#[test]
fn startup_fade_response_on() {
let json = r#"{"SetOption91":"ON"}"#;
let response: StartupFadeResponse = serde_json::from_str(json).unwrap();
assert!(response.is_enabled().unwrap());
}
#[test]
fn startup_fade_response_off() {
let json = r#"{"SetOption91":"OFF"}"#;
let response: StartupFadeResponse = serde_json::from_str(json).unwrap();
assert!(!response.is_enabled().unwrap());
}
#[test]
fn startup_fade_response_numeric() {
let json = r#"{"SetOption91":1}"#;
let response: StartupFadeResponse = serde_json::from_str(json).unwrap();
assert!(response.is_enabled().unwrap());
}
}