@@ -4,7 +4,7 @@ use std::num::ParseIntError;
44use std:: str:: FromStr ;
55
66use regex:: Regex ;
7- use simple_error:: { bail, SimpleError } ;
7+ use simple_error:: { bail, simple_error } ;
88use std:: collections:: HashMap ;
99use 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
7387impl 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}
0 commit comments