zbus/message/
fields.rs

1use serde::{
2    de::{Error, SeqAccess, Visitor},
3    ser::{SerializeSeq, SerializeStruct},
4    Deserialize, Deserializer, Serialize, Serializer,
5};
6use std::{borrow::Cow, num::NonZeroU32};
7use zbus_names::{BusName, ErrorName, InterfaceName, MemberName, UniqueName};
8use zvariant::{ObjectPath, Signature, Type, Value};
9
10use crate::message::{FieldCode, Header, Message};
11
12/// A collection of [`Field`] instances.
13///
14/// [`Field`]: enum.Field.html
15#[derive(Debug, Default, Clone, Type)]
16#[zvariant(signature = "a(yv)")]
17pub(crate) struct Fields<'f> {
18    pub path: Option<ObjectPath<'f>>,
19    pub interface: Option<InterfaceName<'f>>,
20    pub member: Option<MemberName<'f>>,
21    pub error_name: Option<ErrorName<'f>>,
22    pub reply_serial: Option<NonZeroU32>,
23    pub destination: Option<BusName<'f>>,
24    pub sender: Option<UniqueName<'f>>,
25    pub signature: Cow<'f, Signature>,
26    pub unix_fds: Option<u32>,
27}
28
29impl Fields<'_> {
30    /// Create an empty collection of fields.
31    pub fn new() -> Self {
32        Self::default()
33    }
34}
35
36impl Serialize for Fields<'_> {
37    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
38    where
39        S: Serializer,
40    {
41        let mut seq = serializer.serialize_seq(None)?;
42        if let Some(path) = &self.path {
43            seq.serialize_element(&(FieldCode::Path, Value::from(path)))?;
44        }
45        if let Some(interface) = &self.interface {
46            seq.serialize_element(&(FieldCode::Interface, Value::from(interface.as_str())))?;
47        }
48        if let Some(member) = &self.member {
49            seq.serialize_element(&(FieldCode::Member, Value::from(member.as_str())))?;
50        }
51        if let Some(error_name) = &self.error_name {
52            seq.serialize_element(&(FieldCode::ErrorName, Value::from(error_name.as_str())))?;
53        }
54        if let Some(reply_serial) = self.reply_serial {
55            seq.serialize_element(&(FieldCode::ReplySerial, Value::from(reply_serial.get())))?;
56        }
57        if let Some(destination) = &self.destination {
58            seq.serialize_element(&(FieldCode::Destination, Value::from(destination.as_str())))?;
59        }
60        if let Some(sender) = &self.sender {
61            seq.serialize_element(&(FieldCode::Sender, Value::from(sender.as_str())))?;
62        }
63        if !matches!(&*self.signature, Signature::Unit) {
64            seq.serialize_element(&(FieldCode::Signature, SignatureSerializer(&self.signature)))?;
65        }
66        if let Some(unix_fds) = self.unix_fds {
67            seq.serialize_element(&(FieldCode::UnixFDs, Value::from(unix_fds)))?;
68        }
69        seq.end()
70    }
71}
72
73/// Our special serializer for [`Value::Signature`].
74///
75/// Normally `Value` would use the default serializer for `Signature`, which will include the `()`
76/// for strucutures but for body signature, that's what what the D-Bus expects so we do the same as
77/// `Value` here, except we serialize signature value as string w/o the `()`.
78#[derive(Debug, Type)]
79#[zvariant(signature = "v")]
80struct SignatureSerializer<'a>(&'a Signature);
81
82impl Serialize for SignatureSerializer<'_> {
83    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
84    where
85        S: Serializer,
86    {
87        let mut structure = serializer.serialize_struct("Variant", 2)?;
88
89        structure.serialize_field("signature", &Signature::Signature)?;
90
91        let signature_str = self.0.to_string_no_parens();
92        structure.serialize_field("value", &signature_str)?;
93
94        structure.end()
95    }
96}
97
98impl<'de: 'f, 'f> Deserialize<'de> for Fields<'f> {
99    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
100    where
101        D: Deserializer<'de>,
102    {
103        deserializer.deserialize_seq(FieldsVisitor)
104    }
105}
106
107struct FieldsVisitor;
108
109impl<'de> Visitor<'de> for FieldsVisitor {
110    type Value = Fields<'de>;
111
112    fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
113        formatter.write_str("D-Bus message header fields")
114    }
115
116    fn visit_seq<V>(self, mut visitor: V) -> Result<Fields<'de>, V::Error>
117    where
118        V: SeqAccess<'de>,
119    {
120        let mut fields = Fields::new();
121        while let Some((code, value)) = visitor.next_element::<(FieldCode, Value<'de>)>()? {
122            match code {
123                FieldCode::Path => {
124                    fields.path = Some(ObjectPath::try_from(value).map_err(V::Error::custom)?)
125                }
126                FieldCode::Interface => {
127                    fields.interface =
128                        Some(InterfaceName::try_from(value).map_err(V::Error::custom)?)
129                }
130                FieldCode::Member => {
131                    fields.member = Some(MemberName::try_from(value).map_err(V::Error::custom)?)
132                }
133                FieldCode::ErrorName => {
134                    fields.error_name = Some(ErrorName::try_from(value).map_err(V::Error::custom)?)
135                }
136                FieldCode::ReplySerial => {
137                    let value = u32::try_from(value)
138                        .map_err(V::Error::custom)
139                        .and_then(|v| v.try_into().map_err(V::Error::custom))?;
140                    fields.reply_serial = Some(value)
141                }
142                FieldCode::Destination => {
143                    fields.destination = Some(BusName::try_from(value).map_err(V::Error::custom)?)
144                }
145                FieldCode::Sender => {
146                    fields.sender = Some(UniqueName::try_from(value).map_err(V::Error::custom)?)
147                }
148                FieldCode::Signature => {
149                    fields.signature =
150                        Cow::Owned(Signature::try_from(value).map_err(V::Error::custom)?)
151                }
152                FieldCode::UnixFDs => {
153                    fields.unix_fds = Some(u32::try_from(value).map_err(V::Error::custom)?)
154                }
155            }
156        }
157
158        Ok(fields)
159    }
160}
161
162/// A byte range of a field in a Message, used in [`QuickFields`].
163///
164/// Some invalid encodings (end = 0) are used to indicate "not cached" and "not present".
165#[derive(Debug, Default, Clone, Copy)]
166pub(crate) struct FieldPos {
167    start: u32,
168    end: u32,
169}
170
171impl FieldPos {
172    pub fn new_not_present() -> Self {
173        Self { start: 1, end: 0 }
174    }
175
176    pub fn build(msg_buf: &[u8], field_buf: &str) -> Option<Self> {
177        let buf_start = msg_buf.as_ptr() as usize;
178        let field_start = field_buf.as_ptr() as usize;
179        let offset = field_start.checked_sub(buf_start)?;
180        if offset <= msg_buf.len() && offset + field_buf.len() <= msg_buf.len() {
181            Some(Self {
182                start: offset.try_into().ok()?,
183                end: (offset + field_buf.len()).try_into().ok()?,
184            })
185        } else {
186            None
187        }
188    }
189
190    pub fn new<T>(msg_buf: &[u8], field: Option<&T>) -> Self
191    where
192        T: std::ops::Deref<Target = str>,
193    {
194        field
195            .and_then(|f| Self::build(msg_buf, f.deref()))
196            .unwrap_or_else(Self::new_not_present)
197    }
198
199    /// Reassemble a previously cached field.
200    ///
201    /// **NOTE**: The caller must ensure that the `msg_buff` is the same one `build` was called for.
202    /// Otherwise, you'll get a panic.
203    pub fn read<'m, T>(&self, msg_buf: &'m [u8]) -> Option<T>
204    where
205        T: TryFrom<&'m str>,
206        T::Error: std::fmt::Debug,
207    {
208        match self {
209            Self {
210                start: 0..=1,
211                end: 0,
212            } => None,
213            Self { start, end } => {
214                let s = std::str::from_utf8(&msg_buf[(*start as usize)..(*end as usize)])
215                    .expect("Invalid utf8 when reconstructing string");
216                // We already check the fields during the construction of `Self`.
217                T::try_from(s)
218                    .map(Some)
219                    .expect("Invalid field reconstruction")
220            }
221        }
222    }
223}
224
225/// A cache of the Message header fields.
226#[derive(Debug, Default, Clone)]
227pub(crate) struct QuickFields {
228    path: FieldPos,
229    interface: FieldPos,
230    member: FieldPos,
231    error_name: FieldPos,
232    reply_serial: Option<NonZeroU32>,
233    destination: FieldPos,
234    sender: FieldPos,
235    signature: Signature,
236    unix_fds: Option<u32>,
237}
238
239impl QuickFields {
240    pub fn new(buf: &[u8], header: &Header<'_>) -> Self {
241        Self {
242            path: FieldPos::new(buf, header.path()),
243            interface: FieldPos::new(buf, header.interface()),
244            member: FieldPos::new(buf, header.member()),
245            error_name: FieldPos::new(buf, header.error_name()),
246            reply_serial: header.reply_serial(),
247            destination: FieldPos::new(buf, header.destination()),
248            sender: FieldPos::new(buf, header.sender()),
249            signature: header.signature().clone(),
250            unix_fds: header.unix_fds(),
251        }
252    }
253
254    pub fn path<'m>(&self, msg: &'m Message) -> Option<ObjectPath<'m>> {
255        self.path.read(msg.data())
256    }
257
258    pub fn interface<'m>(&self, msg: &'m Message) -> Option<InterfaceName<'m>> {
259        self.interface.read(msg.data())
260    }
261
262    pub fn member<'m>(&self, msg: &'m Message) -> Option<MemberName<'m>> {
263        self.member.read(msg.data())
264    }
265
266    pub fn error_name<'m>(&self, msg: &'m Message) -> Option<ErrorName<'m>> {
267        self.error_name.read(msg.data())
268    }
269
270    pub fn reply_serial(&self) -> Option<NonZeroU32> {
271        self.reply_serial
272    }
273
274    pub fn destination<'m>(&self, msg: &'m Message) -> Option<BusName<'m>> {
275        self.destination.read(msg.data())
276    }
277
278    pub fn sender<'m>(&self, msg: &'m Message) -> Option<UniqueName<'m>> {
279        self.sender.read(msg.data())
280    }
281
282    pub fn signature(&self) -> &Signature {
283        &self.signature
284    }
285
286    pub fn unix_fds(&self) -> Option<u32> {
287        self.unix_fds
288    }
289}