Skip to content

Commit 1a31e99

Browse files
committed
ui: Serialize background event as tag-value
1 parent 8cbecbe commit 1a31e99

File tree

1 file changed

+112
-7
lines changed

1 file changed

+112
-7
lines changed

credentialsd-common/src/server.rs

Lines changed: 112 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,94 @@
22
33
use std::collections::HashMap;
44

5-
use serde::{Deserialize, Serialize};
6-
use zvariant::{self, DeserializeDict, LE, Optional, OwnedValue, SerializeDict, Type, Value};
5+
use serde::{
6+
Deserialize, Serialize,
7+
de::{Error, SeqAccess, Visitor},
8+
ser::SerializeTuple,
9+
};
10+
use zvariant::{
11+
self, DeserializeDict, LE, Optional, OwnedValue, SerializeDict, Signature, Type, Value,
12+
signature::Fields,
13+
};
714

815
use crate::model::Operation;
916

10-
#[derive(Clone, Debug, Serialize, Deserialize, Type)]
17+
#[derive(Clone, Debug)]
18+
1119
pub enum BackgroundEvent {
12-
UsbStateChanged(OwnedValue),
20+
UsbStateChanged(UsbState),
1321
HybridStateChanged(OwnedValue),
1422
}
1523

24+
impl Type for BackgroundEvent {
25+
const SIGNATURE: &'static Signature = &Signature::Structure(Fields::Static {
26+
fields: &[&Signature::U8, &Signature::Variant],
27+
});
28+
}
29+
30+
impl Serialize for BackgroundEvent {
31+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
32+
where
33+
S: serde::Serializer,
34+
{
35+
let mut tuple = serializer.serialize_tuple(2)?;
36+
match self {
37+
Self::UsbStateChanged(state) => {
38+
tuple.serialize_element(&0x01)?;
39+
tuple.serialize_element(state)?;
40+
}
41+
Self::HybridStateChanged(value) => {
42+
tuple.serialize_element(&0x02)?;
43+
tuple.serialize_element(value)?;
44+
}
45+
};
46+
tuple.end()
47+
}
48+
}
49+
50+
impl<'de> Deserialize<'de> for BackgroundEvent {
51+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
52+
where
53+
D: serde::Deserializer<'de>,
54+
{
55+
struct TupleVisitor;
56+
impl<'de> Visitor<'de> for TupleVisitor {
57+
type Value = BackgroundEvent;
58+
59+
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
60+
formatter.write_str("enum BackgroundEvent")
61+
}
62+
63+
fn visit_seq<V>(self, mut seq: V) -> Result<BackgroundEvent, V::Error>
64+
where
65+
V: SeqAccess<'de>,
66+
{
67+
let tag = seq
68+
.next_element::<u8>()?
69+
.ok_or_else(|| V::Error::custom("missing tag"))?;
70+
let value = seq
71+
.next_element::<OwnedValue>()?
72+
.ok_or_else(|| V::Error::custom("enum value not found"))?;
73+
match tag {
74+
0x01 => Ok(BackgroundEvent::UsbStateChanged(
75+
Value::<'_>::from(value).try_into().map_err(|err| {
76+
V::Error::custom(format!("could not deserialize UsbState: {err}"))
77+
})?,
78+
)),
79+
0x02 => Ok(BackgroundEvent::HybridStateChanged(
80+
value.try_to_owned().unwrap(),
81+
)),
82+
_ => Err(V::Error::custom(format!(
83+
"Unknown BackgroundEvent tag: {tag}"
84+
))),
85+
}
86+
}
87+
}
88+
89+
deserializer.deserialize_tuple(2, TupleVisitor)
90+
}
91+
}
92+
1693
impl TryFrom<BackgroundEvent> for crate::model::BackgroundEvent {
1794
type Error = zvariant::Error;
1895

@@ -44,12 +121,13 @@ impl From<crate::model::BackgroundEvent> for BackgroundEvent {
44121
BackgroundEvent::HybridStateChanged(value)
45122
}
46123
crate::model::BackgroundEvent::UsbStateChanged(state) => {
124+
BackgroundEvent::UsbStateChanged(state.into())
125+
/*
47126
let state: UsbState = state.into();
48127
let value = Value::new(state)
49128
.try_to_owned()
50129
.expect("non-file descriptor value to succeed");
51-
52-
BackgroundEvent::UsbStateChanged(value)
130+
*/
53131
}
54132
}
55133
}
@@ -378,7 +456,7 @@ impl From<ServiceError> for crate::model::Error {
378456
}
379457

380458
/// Used to de-/serialize state D-Bus and model::UsbState.
381-
#[derive(Serialize, Deserialize, Type)]
459+
#[derive(Clone, Debug, Serialize, Deserialize, Type)]
382460
pub enum UsbState {
383461
Idle(OwnedValue),
384462
Waiting(OwnedValue),
@@ -639,3 +717,30 @@ fn value_to_owned(value: &Value<'_>) -> OwnedValue {
639717
.try_to_owned()
640718
.expect("non-file descriptor values to succeed")
641719
}
720+
721+
#[cfg(test)]
722+
mod test {
723+
use zvariant::{Type, Value};
724+
725+
use crate::server::{BackgroundEvent, HybridState};
726+
727+
#[test]
728+
fn test_serialize_hybrid_state() {
729+
let state: HybridState = crate::model::HybridState::Completed.into();
730+
let ctx = zvariant::serialized::Context::new_dbus(zvariant::BE, 0);
731+
let data = zvariant::to_bytes(ctx, &state).unwrap();
732+
assert_eq!("(uv)", HybridState::SIGNATURE.to_string());
733+
assert_eq!(&[0, 0, 0, 4, 1, b'b', 0, 0, 0, 0, 0, 0], data.bytes());
734+
}
735+
736+
#[test]
737+
fn test_serialize_background_hybrid_event() {
738+
let state: HybridState = crate::model::HybridState::Completed.into();
739+
let event = BackgroundEvent::HybridStateChanged(Value::from(state).try_to_owned().unwrap());
740+
let ctx = zvariant::serialized::Context::new_dbus(zvariant::BE, 0);
741+
let data = zvariant::to_bytes(ctx, &event).unwrap();
742+
assert_eq!("(yv)", BackgroundEvent::SIGNATURE.to_string());
743+
let expected = b"\x02\x04(uv)\0\0\0\0\x04\x01b\0\0\0\0\0";
744+
assert_eq!(expected, data.bytes());
745+
}
746+
}

0 commit comments

Comments
 (0)