Skip to content

Commit 55f3527

Browse files
committed
Backport #25 to v0.1.x
* Fix setting attributes via JSON; add a test to make sure I don't miss this again * be fancy * fmt
1 parent 3986b66 commit 55f3527

File tree

2 files changed

+81
-23
lines changed

2 files changed

+81
-23
lines changed

src/controller.rs

Lines changed: 80 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::num::ParseIntError;
44
use std::str::FromStr;
55

66
use regex::Regex;
7-
use simple_error::{bail, SimpleError};
7+
use simple_error::{bail, simple_error};
88
use std::collections::HashMap;
99
use subprocess;
1010

@@ -56,26 +56,62 @@ impl AttributeType {
5656
}
5757

5858
pub fn parse_json(&self, s: &serde_json::Value) -> Result<AttributeValue, Box<dyn Error>> {
59-
Ok(match s {
60-
serde_json::Value::Number(n) => AttributeValue::UInt8(
59+
Ok(match (s, self) {
60+
(serde_json::Value::String(s), AttributeType::String) => {
61+
AttributeValue::String(s.clone())
62+
}
63+
(v, AttributeType::String) => AttributeValue::String(v.to_string()),
64+
(serde_json::Value::Number(n), AttributeType::UInt8) => AttributeValue::UInt8(
6165
n.as_u64()
62-
.ok_or(SimpleError::new(format!("{} is not a u64", n)))?
66+
.ok_or_else(|| simple_error!("{} is not a u64", n))?
6367
.try_into()?,
6468
),
65-
serde_json::Value::Bool(v) => AttributeValue::Bool(*v),
66-
v => {
69+
(serde_json::Value::Number(n), AttributeType::UInt16) => AttributeValue::UInt16(
70+
n.as_u64()
71+
.ok_or_else(|| simple_error!("{} is not a u64", n))?
72+
.try_into()?,
73+
),
74+
(serde_json::Value::Number(n), AttributeType::UInt32) => AttributeValue::UInt32(
75+
n.as_u64()
76+
.ok_or_else(|| simple_error!("{} is not a u64", n))?
77+
.try_into()?,
78+
),
79+
(serde_json::Value::Bool(v), AttributeType::Bool) => AttributeValue::Bool(*v),
80+
(v, _) => {
6781
bail!("unknown value for type {:?}: {}", self, v);
6882
}
6983
})
7084
}
7185
}
7286

7387
impl AttributeValue {
74-
pub fn or(&self, other: &AttributeValue) -> AttributeValue {
88+
pub fn attribute_type(&self) -> Option<AttributeType> {
89+
match self {
90+
AttributeValue::NoValue => None,
91+
AttributeValue::Bool(_) => Some(AttributeType::Bool),
92+
AttributeValue::String(_) => Some(AttributeType::String),
93+
AttributeValue::UInt8(_) => Some(AttributeType::UInt8),
94+
AttributeValue::UInt16(_) => Some(AttributeType::UInt16),
95+
AttributeValue::UInt32(_) => Some(AttributeType::UInt32),
96+
}
97+
}
98+
99+
pub fn or<'a>(&'a self, other: &'a AttributeValue) -> &'a AttributeValue {
75100
if *self == AttributeValue::NoValue {
76-
return other.clone();
101+
other
77102
} else {
78-
return self.clone();
103+
self
104+
}
105+
}
106+
107+
pub fn to_json(&self) -> serde_json::Value {
108+
match self {
109+
AttributeValue::NoValue => serde_json::Value::Null,
110+
AttributeValue::Bool(b) => serde_json::Value::Bool(*b),
111+
AttributeValue::UInt8(i) => serde_json::Value::Number(serde_json::Number::from(*i)),
112+
AttributeValue::UInt16(i) => serde_json::Value::Number(serde_json::Number::from(*i)),
113+
AttributeValue::UInt32(i) => serde_json::Value::Number(serde_json::Number::from(*i)),
114+
AttributeValue::String(s) => serde_json::Value::String(s.clone()),
79115
}
80116
}
81117
}
@@ -670,4 +706,39 @@ New HA Dimmable Light
670706
result.attributes[result.attributes.len() - 2].current_value
671707
);
672708
}
709+
710+
#[tokio::test]
711+
async fn test_json_serialization() {
712+
let tests = [
713+
AttributeValue::String("hi".into()),
714+
AttributeValue::String("true".into()),
715+
AttributeValue::String("false".into()),
716+
AttributeValue::String("0".into()),
717+
AttributeValue::String("".into()),
718+
AttributeValue::Bool(true),
719+
AttributeValue::Bool(false),
720+
AttributeValue::UInt8(u8::max_value()),
721+
AttributeValue::UInt16(u16::max_value()),
722+
AttributeValue::UInt32(u32::max_value()),
723+
];
724+
725+
for test in tests.iter() {
726+
let atype = test.attribute_type().unwrap();
727+
let json_output = test.to_json();
728+
assert_eq!(test, &atype.parse_json(&json_output).unwrap());
729+
assert_eq!(
730+
test,
731+
&atype
732+
.parse(
733+
&json_output
734+
.as_str()
735+
.map(String::from)
736+
.unwrap_or_else(|| json_output.to_string())
737+
)
738+
.unwrap()
739+
);
740+
}
741+
742+
assert_eq!(serde_json::Value::Null, AttributeValue::NoValue.to_json());
743+
}
673744
}

src/syncer.rs

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -298,20 +298,7 @@ where
298298
.map(|x| {
299299
(
300300
x.description,
301-
match x.setting_value.or(&x.current_value) {
302-
AttributeValue::NoValue => serde_json::Value::Null,
303-
AttributeValue::Bool(b) => serde_json::Value::Bool(b),
304-
AttributeValue::UInt8(i) => {
305-
serde_json::Value::Number(serde_json::Number::from(i))
306-
}
307-
AttributeValue::UInt16(i) => {
308-
serde_json::Value::Number(serde_json::Number::from(i))
309-
}
310-
AttributeValue::UInt32(i) => {
311-
serde_json::Value::Number(serde_json::Number::from(i))
312-
}
313-
AttributeValue::String(s) => serde_json::Value::String(s),
314-
},
301+
x.setting_value.or(&x.current_value).to_json(),
315302
)
316303
})
317304
.collect::<serde_json::Map<_, _>>();

0 commit comments

Comments
 (0)