1use std::{borrow::Cow, fmt, sync::Arc};
3
4use zbus_names::{ErrorName, InterfaceName, MemberName};
5use zvariant::{Endian, serialized};
6
7use crate::{Error, Result, utils::padding_for_8_bytes, zvariant::ObjectPath};
8
9mod builder;
10pub use builder::Builder;
11
12mod field_code;
13pub(crate) use field_code::FieldCode;
14
15mod fields;
16pub(crate) use fields::Fields;
17use fields::QuickFields;
18
19mod body;
20pub use body::Body;
21
22pub(crate) mod header;
23pub use header::{EndianSig, Flags, Header, NATIVE_ENDIAN_SIG, PrimaryHeader, Type};
24use header::{MIN_MESSAGE_SIZE, PRIMARY_HEADER_SIZE};
25
26#[derive(Debug, Default, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
31pub struct Sequence {
32 recv_seq: u64,
33}
34
35impl Sequence {
36 pub(crate) const LAST: Self = Self { recv_seq: u64::MAX };
38}
39
40#[derive(Clone)]
55pub struct Message {
56 pub(super) inner: Arc<Inner>,
57}
58
59pub(super) struct Inner {
60 pub(crate) primary_header: PrimaryHeader,
61 pub(crate) quick_fields: std::sync::OnceLock<QuickFields>,
62 pub(crate) bytes: serialized::Data<'static, 'static>,
63 pub(crate) body_offset: usize,
64 pub(crate) recv_seq: Sequence,
65}
66
67impl Message {
68 pub fn method_call<'b, 'p: 'b, 'm: 'b, P, M>(path: P, method_name: M) -> Result<Builder<'b>>
70 where
71 P: TryInto<ObjectPath<'p>>,
72 M: TryInto<MemberName<'m>>,
73 P::Error: Into<Error>,
74 M::Error: Into<Error>,
75 {
76 Builder::new(Type::MethodCall)
77 .path(path)?
78 .member(method_name)
79 }
80
81 pub fn signal<'b, 'p: 'b, 'i: 'b, 'm: 'b, P, I, M>(
83 path: P,
84 iface: I,
85 signal_name: M,
86 ) -> Result<Builder<'b>>
87 where
88 P: TryInto<ObjectPath<'p>>,
89 I: TryInto<InterfaceName<'i>>,
90 M: TryInto<MemberName<'m>>,
91 P::Error: Into<Error>,
92 I::Error: Into<Error>,
93 M::Error: Into<Error>,
94 {
95 Builder::new(Type::Signal)
96 .path(path)?
97 .interface(iface)?
98 .member(signal_name)
99 }
100
101 pub fn method_return(reply_to: &Header<'_>) -> Result<Builder<'static>> {
103 Builder::new(Type::MethodReturn).reply_to(reply_to)
104 }
105
106 pub fn error<'b, 'e: 'b, E>(reply_to: &Header<'_>, name: E) -> Result<Builder<'b>>
108 where
109 E: TryInto<ErrorName<'e>>,
110 E::Error: Into<Error>,
111 {
112 Builder::new(Type::Error)
113 .reply_to(reply_to)?
114 .error_name(name)
115 }
116
117 pub unsafe fn from_bytes(bytes: serialized::Data<'static, 'static>) -> Result<Self> {
127 Self::from_raw_parts(bytes, 0)
128 }
129
130 pub(crate) fn from_raw_parts(
132 bytes: serialized::Data<'static, 'static>,
133 recv_seq: u64,
134 ) -> Result<Self> {
135 let endian = Endian::from(EndianSig::try_from(bytes[0])?);
136 if endian != bytes.context().endian() {
137 return Err(Error::IncorrectEndian);
138 }
139
140 let (primary_header, fields_len) = PrimaryHeader::read_from_data(&bytes)?;
141 let fields_bytes = bytes.slice(PRIMARY_HEADER_SIZE..);
142 let (fields, _) = fields_bytes.deserialize()?;
143 let header = Header::new(primary_header.clone(), fields);
144
145 let header_len = MIN_MESSAGE_SIZE + fields_len as usize;
146 let body_offset = header_len + padding_for_8_bytes(header_len);
147 let quick_fields = QuickFields::new(&bytes, &header).into();
148
149 Ok(Self {
150 inner: Arc::new(Inner {
151 primary_header,
152 quick_fields,
153 bytes,
154 body_offset,
155 recv_seq: Sequence { recv_seq },
156 }),
157 })
158 }
159
160 pub fn primary_header(&self) -> &PrimaryHeader {
161 &self.inner.primary_header
162 }
163
164 pub fn header(&self) -> Header<'_> {
166 let quick_fields = self.quick_fields();
167 let fields = Fields {
168 path: quick_fields.path(self),
169 interface: quick_fields.interface(self),
170 member: quick_fields.member(self),
171 error_name: quick_fields.error_name(self),
172 reply_serial: quick_fields.reply_serial(),
173 destination: quick_fields.destination(self),
174 sender: quick_fields.sender(self),
175 signature: Cow::Borrowed(quick_fields.signature()),
176 unix_fds: quick_fields.unix_fds(),
177 };
178
179 Header::new(self.inner.primary_header.clone(), fields)
180 }
181
182 pub fn message_type(&self) -> Type {
184 self.inner.primary_header.msg_type()
185 }
186
187 pub fn body(&self) -> Body {
215 Body::new(
216 self.inner.bytes.slice(self.inner.body_offset..),
217 self.clone(),
218 )
219 }
220
221 pub fn data(&self) -> &serialized::Data<'static, 'static> {
223 &self.inner.bytes
224 }
225
226 pub fn recv_position(&self) -> Sequence {
234 self.inner.recv_seq
235 }
236
237 fn quick_fields(&self) -> &QuickFields {
238 self.inner.quick_fields.get_or_init(|| {
239 let bytes = &self.inner.bytes;
240 let (header, _): (Header<'_>, _) = bytes.deserialize().unwrap();
243
244 QuickFields::new(bytes, &header)
245 })
246 }
247}
248
249impl fmt::Debug for Message {
250 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
251 let mut msg = f.debug_struct("Msg");
252 let h = self.header();
253 msg.field("type", &h.message_type());
254 msg.field("serial", &self.primary_header().serial_num());
255 if let Some(sender) = h.sender() {
256 msg.field("sender", &sender);
257 }
258 if let Some(serial) = h.reply_serial() {
259 msg.field("reply-serial", &serial);
260 }
261 if let Some(path) = h.path() {
262 msg.field("path", &path);
263 }
264 if let Some(iface) = h.interface() {
265 msg.field("iface", &iface);
266 }
267 if let Some(member) = h.member() {
268 msg.field("member", &member);
269 }
270 match self.body().signature() {
271 zvariant::Signature::Unit => (),
272 s => {
273 msg.field("body", &s);
274 }
275 }
276 #[cfg(unix)]
277 {
278 msg.field("fds", &self.data().fds());
279 }
280 msg.finish()
281 }
282}
283
284impl fmt::Display for Message {
285 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
286 let header = self.header();
287 let (ty, error_name, sender, member) = (
288 header.message_type(),
289 header.error_name(),
290 header.sender(),
291 header.member(),
292 );
293
294 match ty {
295 Type::MethodCall => {
296 write!(f, "Method call")?;
297 if let Some(m) = member {
298 write!(f, " {m}")?;
299 }
300 }
301 Type::MethodReturn => {
302 write!(f, "Method return")?;
303 }
304 Type::Error => {
305 write!(f, "Error")?;
306 if let Some(e) = error_name {
307 write!(f, " {e}")?;
308 }
309
310 let body = self.body();
311 let msg = body.deserialize_unchecked::<&str>();
312 if let Ok(msg) = msg {
313 write!(f, ": {msg}")?;
314 }
315 }
316 Type::Signal => {
317 write!(f, "Signal")?;
318 if let Some(m) = member {
319 write!(f, " {m}")?;
320 }
321 }
322 }
323
324 if let Some(s) = sender {
325 write!(f, " from {s}")?;
326 }
327
328 Ok(())
329 }
330}
331
332#[cfg(test)]
333mod tests {
334 #[cfg(unix)]
335 use std::os::fd::{AsFd, AsRawFd};
336 use test_log::test;
337 #[cfg(unix)]
338 use zvariant::Fd;
339 use zvariant::Signature;
340
341 use super::Message;
342 use crate::Error;
343
344 #[test]
345 fn test() {
346 #[cfg(unix)]
347 let stdout = std::io::stdout();
348 let m = Message::method_call("/", "do")
349 .unwrap()
350 .sender(":1.72")
351 .unwrap()
352 .build(&(
353 #[cfg(unix)]
354 Fd::from(&stdout),
355 "foo",
356 ))
357 .unwrap();
358 #[cfg(unix)]
359 assert_eq!(
360 m.body().signature(),
361 &Signature::static_structure(&[&Signature::Fd, &Signature::Str]),
362 );
363 #[cfg(not(unix))]
364 assert_eq!(m.body().signature(), &Signature::Str,);
365 #[cfg(unix)]
366 {
367 let fds = m.data().fds();
368 assert_eq!(fds.len(), 1);
369 assert_ne!(fds[0].as_fd().as_raw_fd(), stdout.as_raw_fd());
371 }
372
373 let body: Result<u32, Error> = m.body().deserialize();
374 assert!(matches!(
375 body.unwrap_err(),
376 Error::Variant(zvariant::Error::SignatureMismatch { .. })
377 ));
378
379 assert_eq!(m.to_string(), "Method call do from :1.72");
380 let r = Message::method_return(&m.header())
381 .unwrap()
382 .build(&("all fine!"))
383 .unwrap();
384 assert_eq!(r.to_string(), "Method return");
385 let e = Message::error(&m.header(), "org.freedesktop.zbus.Error")
386 .unwrap()
387 .build(&("kaboom!", 32))
388 .unwrap();
389 assert_eq!(e.to_string(), "Error org.freedesktop.zbus.Error: kaboom!");
390 }
391}