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