1use std::{fmt, num::NonZeroU32, sync::Arc};
3
4use static_assertions::assert_impl_all;
5use zbus_names::{ErrorName, InterfaceName, MemberName};
6use zvariant::{serialized, Endian};
7
8use crate::{utils::padding_for_8_bytes, zvariant::ObjectPath, Error, Result};
9
10mod builder;
11pub use builder::Builder;
12
13mod field;
14pub(crate) use field::{Field, FieldCode};
15
16mod fields;
17pub(crate) use fields::Fields;
18use fields::QuickFields;
19
20mod body;
21pub use body::Body;
22
23pub(crate) mod header;
24use header::MIN_MESSAGE_SIZE;
25pub use header::{EndianSig, Flags, Header, PrimaryHeader, Type, NATIVE_ENDIAN_SIG};
26
27#[derive(Debug, Default, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
32pub struct Sequence {
33 recv_seq: u64,
34}
35
36impl Sequence {
37 pub(crate) const LAST: Self = Self { recv_seq: u64::MAX };
39}
40
41#[derive(Clone)]
57pub struct Message {
58 pub(super) inner: Arc<Inner>,
59}
60
61pub(super) struct Inner {
62 pub(crate) primary_header: PrimaryHeader,
63 pub(crate) quick_fields: QuickFields,
64 pub(crate) bytes: serialized::Data<'static, 'static>,
65 pub(crate) body_offset: usize,
66 pub(crate) recv_seq: Sequence,
67}
68
69assert_impl_all!(Message: Send, Sync, Unpin);
70
71impl Message {
72 pub fn method<'b, 'p: 'b, 'm: 'b, P, M>(path: P, method_name: M) -> Result<Builder<'b>>
74 where
75 P: TryInto<ObjectPath<'p>>,
76 M: TryInto<MemberName<'m>>,
77 P::Error: Into<Error>,
78 M::Error: Into<Error>,
79 {
80 #[allow(deprecated)]
81 Builder::method_call(path, method_name)
82 }
83
84 pub fn signal<'b, 'p: 'b, 'i: 'b, 'm: 'b, P, I, M>(
86 path: P,
87 iface: I,
88 signal_name: M,
89 ) -> Result<Builder<'b>>
90 where
91 P: TryInto<ObjectPath<'p>>,
92 I: TryInto<InterfaceName<'i>>,
93 M: TryInto<MemberName<'m>>,
94 P::Error: Into<Error>,
95 I::Error: Into<Error>,
96 M::Error: Into<Error>,
97 {
98 #[allow(deprecated)]
99 Builder::signal(path, iface, signal_name)
100 }
101
102 pub fn method_reply(call: &Self) -> Result<Builder<'_>> {
104 #[allow(deprecated)]
105 Builder::method_return(&call.header())
106 }
107
108 pub fn method_error<'b, 'e: 'b, E>(call: &Self, name: E) -> Result<Builder<'b>>
110 where
111 E: TryInto<ErrorName<'e>>,
112 E::Error: Into<Error>,
113 {
114 #[allow(deprecated)]
115 Builder::error(&call.header(), name)
116 }
117
118 pub unsafe fn from_bytes(bytes: serialized::Data<'static, 'static>) -> Result<Self> {
128 Self::from_raw_parts(bytes, 0)
129 }
130
131 pub(crate) fn from_raw_parts(
133 bytes: serialized::Data<'static, 'static>,
134 recv_seq: u64,
135 ) -> Result<Self> {
136 let endian = Endian::from(EndianSig::try_from(bytes[0])?);
137 if endian != bytes.context().endian() {
138 return Err(Error::IncorrectEndian);
139 }
140
141 let (primary_header, fields_len) = PrimaryHeader::read_from_data(&bytes)?;
142 let (header, _) = bytes.deserialize()?;
143
144 let header_len = MIN_MESSAGE_SIZE + fields_len as usize;
145 let body_offset = header_len + padding_for_8_bytes(header_len);
146 let quick_fields = QuickFields::new(&bytes, &header)?;
147
148 Ok(Self {
149 inner: Arc::new(Inner {
150 primary_header,
151 quick_fields,
152 bytes,
153 body_offset,
154 recv_seq: Sequence { recv_seq },
155 }),
156 })
157 }
158
159 pub fn primary_header(&self) -> &PrimaryHeader {
160 &self.inner.primary_header
161 }
162
163 pub fn header(&self) -> Header<'_> {
169 let mut fields = Fields::new();
170 let quick_fields = &self.inner.quick_fields;
171 if let Some(p) = quick_fields.path(self) {
172 fields.add(Field::Path(p));
173 }
174 if let Some(i) = quick_fields.interface(self) {
175 fields.add(Field::Interface(i));
176 }
177 if let Some(m) = quick_fields.member(self) {
178 fields.add(Field::Member(m));
179 }
180 if let Some(e) = quick_fields.error_name(self) {
181 fields.add(Field::ErrorName(e));
182 }
183 if let Some(r) = quick_fields.reply_serial() {
184 fields.add(Field::ReplySerial(r));
185 }
186 if let Some(d) = quick_fields.destination(self) {
187 fields.add(Field::Destination(d));
188 }
189 if let Some(s) = quick_fields.sender(self) {
190 fields.add(Field::Sender(s));
191 }
192 if let Some(s) = quick_fields.signature(self) {
193 fields.add(Field::Signature(s));
194 }
195 if let Some(u) = quick_fields.unix_fds() {
196 fields.add(Field::UnixFDs(u));
197 }
198
199 Header::new(self.inner.primary_header.clone(), fields)
200 }
201
202 pub fn message_type(&self) -> Type {
204 self.inner.primary_header.msg_type()
205 }
206
207 #[deprecated(
209 since = "4.0.0",
210 note = "Use `Message::header` with `message::Header::path` instead"
211 )]
212 pub fn path(&self) -> Option<ObjectPath<'_>> {
213 self.inner.quick_fields.path(self)
214 }
215
216 #[deprecated(
218 since = "4.0.0",
219 note = "Use `Message::header` with `message::Header::interface` instead"
220 )]
221 pub fn interface(&self) -> Option<InterfaceName<'_>> {
222 self.inner.quick_fields.interface(self)
223 }
224
225 #[deprecated(
227 since = "4.0.0",
228 note = "Use `Message::header` with `message::Header::member` instead"
229 )]
230 pub fn member(&self) -> Option<MemberName<'_>> {
231 self.inner.quick_fields.member(self)
232 }
233
234 #[deprecated(
236 since = "4.0.0",
237 note = "Use `Message::header` with `message::Header::reply_serial` instead"
238 )]
239 pub fn reply_serial(&self) -> Option<NonZeroU32> {
240 self.inner.quick_fields.reply_serial()
241 }
242
243 pub fn body(&self) -> Body {
270 Body::new(
271 self.inner.bytes.slice(self.inner.body_offset..),
272 self.clone(),
273 )
274 }
275
276 pub fn data(&self) -> &serialized::Data<'static, 'static> {
278 &self.inner.bytes
279 }
280
281 pub fn recv_position(&self) -> Sequence {
289 self.inner.recv_seq
290 }
291}
292
293impl fmt::Debug for Message {
294 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
295 let mut msg = f.debug_struct("Msg");
296 let h = self.header();
297 msg.field("type", &h.message_type());
298 msg.field("serial", &self.primary_header().serial_num());
299 if let Some(sender) = h.sender() {
300 msg.field("sender", &sender);
301 }
302 if let Some(serial) = h.reply_serial() {
303 msg.field("reply-serial", &serial);
304 }
305 if let Some(path) = h.path() {
306 msg.field("path", &path);
307 }
308 if let Some(iface) = h.interface() {
309 msg.field("iface", &iface);
310 }
311 if let Some(member) = h.member() {
312 msg.field("member", &member);
313 }
314 if let Some(s) = self.body().signature() {
315 msg.field("body", &s);
316 }
317 #[cfg(unix)]
318 {
319 msg.field("fds", &self.data().fds());
320 }
321 msg.finish()
322 }
323}
324
325impl fmt::Display for Message {
326 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
327 let header = self.header();
328 let (ty, error_name, sender, member) = (
329 header.message_type(),
330 header.error_name(),
331 header.sender(),
332 header.member(),
333 );
334
335 match ty {
336 Type::MethodCall => {
337 write!(f, "Method call")?;
338 if let Some(m) = member {
339 write!(f, " {m}")?;
340 }
341 }
342 Type::MethodReturn => {
343 write!(f, "Method return")?;
344 }
345 Type::Error => {
346 write!(f, "Error")?;
347 if let Some(e) = error_name {
348 write!(f, " {e}")?;
349 }
350
351 let body = self.body();
352 let msg = body.deserialize_unchecked::<&str>();
353 if let Ok(msg) = msg {
354 write!(f, ": {msg}")?;
355 }
356 }
357 Type::Signal => {
358 write!(f, "Signal")?;
359 if let Some(m) = member {
360 write!(f, " {m}")?;
361 }
362 }
363 }
364
365 if let Some(s) = sender {
366 write!(f, " from {s}")?;
367 }
368
369 Ok(())
370 }
371}
372
373#[cfg(test)]
374mod tests {
375 #[cfg(unix)]
376 use std::os::fd::{AsFd, AsRawFd};
377 use test_log::test;
378 #[cfg(unix)]
379 use zvariant::Fd;
380
381 use super::Message;
382 use crate::Error;
383
384 #[test]
385 fn test() {
386 #[cfg(unix)]
387 let stdout = std::io::stdout();
388 let m = Message::method("/", "do")
389 .unwrap()
390 .sender(":1.72")
391 .unwrap()
392 .build(&(
393 #[cfg(unix)]
394 Fd::from(&stdout),
395 "foo",
396 ))
397 .unwrap();
398 assert_eq!(
399 m.body().signature().unwrap().to_string(),
400 if cfg!(unix) { "hs" } else { "s" }
401 );
402 #[cfg(unix)]
403 {
404 let fds = m.data().fds();
405 assert_eq!(fds.len(), 1);
406 assert_ne!(fds[0].as_fd().as_raw_fd(), stdout.as_raw_fd());
408 }
409
410 let body: Result<u32, Error> = m.body().deserialize();
411 assert!(matches!(
412 body.unwrap_err(),
413 Error::Variant(zvariant::Error::SignatureMismatch { .. })
414 ));
415
416 assert_eq!(m.to_string(), "Method call do from :1.72");
417 let r = Message::method_reply(&m)
418 .unwrap()
419 .build(&("all fine!"))
420 .unwrap();
421 assert_eq!(r.to_string(), "Method return");
422 let e = Message::method_error(&m, "org.freedesktop.zbus.Error")
423 .unwrap()
424 .build(&("kaboom!", 32))
425 .unwrap();
426 assert_eq!(e.to_string(), "Error org.freedesktop.zbus.Error: kaboom!");
427 }
428}