@@ -4,12 +4,12 @@ use std::collections::HashMap;
44
55use serde:: {
66 Deserialize , Serialize ,
7- de:: { DeserializeSeed , Error , SeqAccess , Visitor } ,
7+ de:: { DeserializeSeed , Error } ,
88 ser:: { Error as _, SerializeTuple } ,
99} ;
1010use zvariant:: {
11- self , DeserializeDict , DynamicDeserialize , LE , Optional , OwnedValue , SerializeDict , Signature ,
12- Structure , StructureBuilder , Type , Value , signature:: Fields ,
11+ self , Array , DeserializeDict , DynamicDeserialize , LE , Optional , OwnedValue , SerializeDict ,
12+ Signature , Structure , StructureBuilder , Type , Value , signature:: Fields ,
1313} ;
1414
1515use crate :: model:: Operation ;
@@ -61,43 +61,46 @@ impl<'de> Deserialize<'de> for BackgroundEvent {
6161 where
6262 D : serde:: Deserializer < ' de > ,
6363 {
64- struct TupleVisitor ;
65- impl < ' de > Visitor < ' de > for TupleVisitor {
66- type Value = BackgroundEvent ;
67-
68- fn expecting ( & self , formatter : & mut std:: fmt:: Formatter ) -> std:: fmt:: Result {
69- formatter. write_str ( "enum BackgroundEvent" )
64+ let d = Structure :: deserializer_for_signature ( TAG_VALUE_SIGNATURE ) . map_err ( |err| {
65+ D :: Error :: custom ( format ! (
66+ "could not create deserializer for tag-value struct: {err}"
67+ ) )
68+ } ) ?;
69+ let structure = d. deserialize ( deserializer) ?;
70+ let ( tag, value) = parse_tag_value_struct ( & structure) . map_err ( |err| {
71+ D :: Error :: custom ( format ! ( "could not parse structure as tag-value: {err}" ) )
72+ } ) ?;
73+ match tag {
74+ 0x01 => {
75+ let inner: Structure = value. downcast_ref ( ) . map_err ( |err| {
76+ D :: Error :: custom ( format ! (
77+ "could not deserialize inner value {value} as struct: {err}"
78+ ) )
79+ } ) ?;
80+ let state = crate :: model:: UsbState :: try_from ( & inner) . map_err ( |err| {
81+ D :: Error :: custom ( format ! (
82+ "could not deserialize UsbState from structure: {err}"
83+ ) )
84+ } ) ?;
85+ Ok ( BackgroundEvent :: UsbStateChanged ( state) )
7086 }
71-
72- fn visit_seq < V > ( self , mut seq : V ) -> Result < BackgroundEvent , V :: Error >
73- where
74- V : SeqAccess < ' de > ,
75- {
76- let tag = seq
77- . next_element :: < u8 > ( ) ?
78- . ok_or_else ( || V :: Error :: custom ( "missing tag" ) ) ?;
79- match tag {
80- 0x01 => {
81- let value = seq
82- . next_element :: < OwnedValue > ( ) ?
83- . ok_or_else ( || V :: Error :: custom ( "enum value not found" ) ) ?;
84- Ok ( BackgroundEvent :: UsbStateChanged (
85- Value :: < ' _ > :: from ( value) . try_into ( ) . map_err ( |err| {
86- V :: Error :: custom ( format ! ( "could not deserialize UsbState: {err}" ) )
87- } ) ?,
88- ) )
89- }
90- 0x02 => Ok ( BackgroundEvent :: HybridStateChanged (
91- seq. next_element :: < crate :: model:: HybridState > ( ) ?
92- . ok_or_else ( || V :: Error :: custom ( "could not deserialize HybridState" ) ) ?,
93- ) ) ,
94- _ => Err ( V :: Error :: custom ( format ! (
95- "Unknown BackgroundEvent tag: {tag}"
96- ) ) ) ,
97- }
87+ 0x02 => {
88+ let inner: Structure = value. downcast_ref ( ) . map_err ( |err| {
89+ D :: Error :: custom ( format ! (
90+ "could not deserialize inner value {value} as struct: {err}"
91+ ) )
92+ } ) ?;
93+ let state = crate :: model:: HybridState :: try_from ( & inner) . map_err ( |err| {
94+ D :: Error :: custom ( format ! (
95+ "could not deserialize HybridState from structure: {err}"
96+ ) )
97+ } ) ?;
98+ Ok ( BackgroundEvent :: HybridStateChanged ( state) )
9899 }
100+ _ => Err ( D :: Error :: custom ( format ! (
101+ "Unknown BackgroundEvent tag : {tag}"
102+ ) ) ) ,
99103 }
100- deserializer. deserialize_tuple ( 2 , TupleVisitor )
101104 }
102105}
103106
@@ -436,41 +439,24 @@ impl Serialize for crate::model::HybridState {
436439
437440impl From < & crate :: model:: HybridState > for Structure < ' _ > {
438441 fn from ( value : & crate :: model:: HybridState ) -> Self {
439- let ( tag, value) = match value {
440- crate :: model:: HybridState :: Idle => ( & 0x01_u8 , None ) ,
441- crate :: model:: HybridState :: Started ( value) => ( & 0x02_u8 , Some ( Value :: Str ( value. into ( ) ) ) ) ,
442- crate :: model:: HybridState :: Connecting => ( & 0x03_u8 , None ) ,
443- crate :: model:: HybridState :: Connected => ( & 0x04_u8 , None ) ,
444- crate :: model:: HybridState :: Completed => ( & 0x05_u8 , None ) ,
445- crate :: model:: HybridState :: UserCancelled => ( & 0x06_u8 , None ) ,
446- crate :: model:: HybridState :: Failed => ( & 0x07_u8 , None ) ,
442+ let ( tag, value) : ( u8 , Option < Value > ) = match value {
443+ crate :: model:: HybridState :: Idle => ( 0x01 , None ) ,
444+ crate :: model:: HybridState :: Started ( value) => ( 0x02 , Some ( Value :: Str ( value. into ( ) ) ) ) ,
445+ crate :: model:: HybridState :: Connecting => ( 0x03 , None ) ,
446+ crate :: model:: HybridState :: Connected => ( 0x04 , None ) ,
447+ crate :: model:: HybridState :: Completed => ( 0x05 , None ) ,
448+ crate :: model:: HybridState :: UserCancelled => ( 0x06 , None ) ,
449+ crate :: model:: HybridState :: Failed => ( 0x07 , None ) ,
447450 } ;
448- StructureBuilder :: new ( )
449- . add_field ( * tag)
450- . append_field (
451- value
452- . unwrap_or_else ( || Value :: new ( Value :: U8 ( 0 ) ) )
453- . try_to_owned ( )
454- . unwrap ( )
455- . into ( ) ,
456- )
457- . build ( )
458- . expect ( "create a struct" )
451+ tag_value_to_struct ( tag, value)
459452 }
460453}
461454
462455impl TryFrom < & Structure < ' _ > > for crate :: model:: HybridState {
463456 type Error = zvariant:: Error ;
464457
465458 fn try_from ( structure : & Structure < ' _ > ) -> Result < Self , Self :: Error > {
466- let fields = structure. fields ( ) ;
467- let tag: u8 = fields
468- . get ( 0 )
469- . ok_or_else ( || zvariant:: Error :: IncorrectType ) ?
470- . downcast_ref ( ) ?;
471- let value = & fields
472- . get ( 1 )
473- . ok_or_else ( || zvariant:: Error :: IncorrectType ) ?;
459+ let ( tag, value) = parse_tag_value_struct ( structure) ?;
474460 return match tag {
475461 0x01 => Ok ( Self :: Idle ) ,
476462 0x02 => {
@@ -731,33 +717,15 @@ impl From<&crate::model::UsbState> for Structure<'_> {
731717 ( 0x0A , Some ( value) )
732718 }
733719 } ;
734- StructureBuilder :: new ( )
735- . add_field ( tag)
736- . append_field ( value_to_owned ( & Value :: new ( value. unwrap_or_else ( || Value :: U8 ( 0 ) ) ) ) . into ( ) )
737- . build ( )
738- . expect ( "valid signature" )
720+ tag_value_to_struct ( tag, value)
739721 }
740722}
741723
742724impl TryFrom < & Structure < ' _ > > for crate :: model:: UsbState {
743725 type Error = zvariant:: Error ;
744726
745727 fn try_from ( structure : & Structure < ' _ > ) -> Result < Self , Self :: Error > {
746- if structure. signature ( ) != TAG_VALUE_SIGNATURE {
747- return Err ( zvariant:: Error :: SignatureMismatch (
748- structure. signature ( ) . clone ( ) ,
749- TAG_VALUE_SIGNATURE . to_string ( ) ,
750- ) ) ;
751- }
752- let tag: u8 = structure
753- . fields ( )
754- . get ( 0 )
755- . ok_or_else ( || zvariant:: Error :: IncorrectType )
756- . and_then ( |f| f. downcast_ref ( ) ) ?;
757- let value = structure
758- . fields ( )
759- . get ( 1 )
760- . ok_or_else ( || zvariant:: Error :: IncorrectType ) ?;
728+ let ( tag, value) = parse_tag_value_struct ( structure) ?;
761729 match tag {
762730 0x01 => Ok ( Self :: Idle ) ,
763731 0x02 => Ok ( Self :: Waiting ) ,
@@ -987,6 +955,46 @@ fn value_to_owned(value: &Value<'_>) -> OwnedValue {
987955 . expect ( "non-file descriptor values to succeed" )
988956}
989957
958+ fn parse_tag_value_struct < ' a > ( s : & ' a Structure ) -> Result < ( u8 , Value < ' a > ) , zvariant:: Error > {
959+ if s. signature ( ) != TAG_VALUE_SIGNATURE {
960+ return Err ( zvariant:: Error :: SignatureMismatch (
961+ s. signature ( ) . clone ( ) ,
962+ TAG_VALUE_SIGNATURE . to_string ( ) ,
963+ ) ) ;
964+ }
965+ let tag: u8 = s
966+ . fields ( )
967+ . get ( 0 )
968+ . ok_or_else ( || {
969+ zvariant:: Error :: SignatureMismatch (
970+ Signature :: U8 ,
971+ "expected a single-byte tag" . to_string ( ) ,
972+ )
973+ } )
974+ . and_then ( |f| f. downcast_ref ( ) ) ?;
975+ let value = s
976+ . fields ( )
977+ . get ( 1 )
978+ . ok_or_else ( || {
979+ zvariant:: Error :: SignatureMismatch (
980+ Signature :: Variant ,
981+ "expected a variant value" . to_string ( ) ,
982+ )
983+ } ) ?
984+ . clone ( ) ;
985+ Ok ( ( tag, value) )
986+ }
987+
988+ fn tag_value_to_struct ( tag : u8 , value : Option < Value < ' _ > > ) -> Structure < ' static > {
989+ StructureBuilder :: new ( )
990+ . add_field ( tag)
991+ . append_field ( Value :: new ( value_to_owned (
992+ & value. unwrap_or_else ( || Value :: U8 ( 0 ) ) ,
993+ ) ) )
994+ . build ( )
995+ . expect ( "create a struct" )
996+ }
997+
990998#[ cfg( test) ]
991999mod test {
9921000 use zvariant:: {
@@ -1007,12 +1015,12 @@ mod test {
10071015
10081016 #[ test]
10091017 fn test_serialize_background_hybrid_event ( ) {
1010- let state = crate :: model:: HybridState :: Completed ;
1018+ let state = crate :: model:: HybridState :: Started ( "FIDO:/1234" . to_string ( ) ) ;
10111019 let event = BackgroundEvent :: HybridStateChanged ( state) ;
10121020 let ctx = zvariant:: serialized:: Context :: new_dbus ( zvariant:: BE , 0 ) ;
10131021 assert_eq ! ( "(yv)" , BackgroundEvent :: SIGNATURE . to_string( ) ) ;
10141022 let data = zvariant:: to_bytes ( ctx, & event) . unwrap ( ) ;
1015- let expected = b"\x02 \x04 (yv)\0 \0 \x05 \x01 y \0 \0 " ;
1023+ let expected = b"\x02 \x04 (yv)\0 \0 \x02 \x01 s \0 \0 \0 \0 \x0a FIDO:/1234 \0 " ;
10161024 assert_eq ! ( expected, data. bytes( ) ) ;
10171025 }
10181026
0 commit comments