From fc3b89ebf6bde412533fe0093e72a92c35f2fe7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Fri, 4 Oct 2024 17:44:05 +0400 Subject: [PATCH 01/13] =?UTF-8?q?=F0=9F=9A=9A=20zb:=20rename=20a=20functio?= =?UTF-8?q?n=20parameter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As requested by Zeeshan. --- zbus/src/connection/connect/win32.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zbus/src/connection/connect/win32.rs b/zbus/src/connection/connect/win32.rs index eea290a43..66dbb3740 100644 --- a/zbus/src/connection/connect/win32.rs +++ b/zbus/src/connection/connect/win32.rs @@ -9,10 +9,10 @@ use crate::{ use std::{future::Future, pin::Pin}; pub(crate) fn connect<'l>( - l: &'l crate::address::transport::Autolaunch<'_>, + autolaunch: &'l crate::address::transport::Autolaunch<'_>, ) -> Pin + 'l>> { Box::pin(async move { - if l.scope().is_some() { + if autolaunch.scope().is_some() { return Err(Error::Address( "autolaunch with scope isn't supported yet".into(), )); From 59d49d589d2fe135cf2ae40a38286c3222d73697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Fri, 4 Oct 2024 17:56:17 +0400 Subject: [PATCH 02/13] =?UTF-8?q?=F0=9F=9A=9A=20zb:=20replace=20TryFrom<&A?= =?UTF-8?q?ddress>=20with=20a=20TransportImpl?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As requested by Zeeshan. --- zbus/src/address/mod.rs | 3 ++- zbus/src/address/transport/autolaunch.rs | 8 +++---- zbus/src/address/transport/launchd.rs | 10 ++++----- zbus/src/address/transport/mod.rs | 28 ++++++++++++++---------- zbus/src/address/transport/nonce_tcp.rs | 8 +++---- zbus/src/address/transport/systemd.rs | 8 +++---- zbus/src/address/transport/tcp.rs | 10 ++++----- zbus/src/address/transport/unix.rs | 8 +++---- zbus/src/address/transport/unixexec.rs | 8 +++---- zbus/src/address/transport/vsock.rs | 10 ++++----- 10 files changed, 48 insertions(+), 53 deletions(-) diff --git a/zbus/src/address/mod.rs b/zbus/src/address/mod.rs index c50eb056b..87e3d9604 100644 --- a/zbus/src/address/mod.rs +++ b/zbus/src/address/mod.rs @@ -33,6 +33,7 @@ pub use address_list::{AddressList, AddressListIter}; mod percent; pub use percent::*; +use transport::TransportImpl; #[cfg(test)] mod tests; @@ -140,7 +141,7 @@ impl<'a> Address<'a> { /// Transport connection details pub fn transport(&self) -> Result> { - self.try_into() + transport::Transport::for_address(self) } pub(super) fn key_val_iter(&'a self) -> KeyValIter<'a> { diff --git a/zbus/src/address/transport/autolaunch.rs b/zbus/src/address/transport/autolaunch.rs index 3d56a907f..76526a63b 100644 --- a/zbus/src/address/transport/autolaunch.rs +++ b/zbus/src/address/transport/autolaunch.rs @@ -4,7 +4,7 @@ use std::{borrow::Cow, fmt}; #[cfg(target_os = "windows")] use super::percent::decode_percents_str; -use super::{Address, Error, KeyValFmt, KeyValFmtAdd, Result}; +use super::{Address, KeyValFmt, KeyValFmtAdd, Result, TransportImpl}; /// Scope of autolaunch (Windows only) #[cfg(target_os = "windows")] @@ -61,10 +61,8 @@ impl<'a> Autolaunch<'a> { } } -impl<'a> TryFrom<&'a Address<'a>> for Autolaunch<'a> { - type Error = Error; - - fn try_from(s: &'a Address<'a>) -> Result { +impl<'a> TransportImpl<'a> for Autolaunch<'a> { + fn for_address(s: &'a Address<'a>) -> Result { #[allow(unused_mut)] let mut res = Autolaunch::default(); diff --git a/zbus/src/address/transport/launchd.rs b/zbus/src/address/transport/launchd.rs index 4f44486eb..578752774 100644 --- a/zbus/src/address/transport/launchd.rs +++ b/zbus/src/address/transport/launchd.rs @@ -1,6 +1,8 @@ use std::borrow::Cow; -use super::{percent::decode_percents_str, Address, Error, KeyValFmt, KeyValFmtAdd, Result}; +use super::{ + percent::decode_percents_str, Address, Error, KeyValFmt, KeyValFmtAdd, Result, TransportImpl, +}; /// `launchd:` D-Bus transport. /// @@ -20,10 +22,8 @@ impl<'a> Launchd<'a> { } } -impl<'a> TryFrom<&'a Address<'a>> for Launchd<'a> { - type Error = Error; - - fn try_from(s: &'a Address<'a>) -> Result { +impl<'a> TransportImpl<'a> for Launchd<'a> { + fn for_address(s: &'a Address<'a>) -> Result { for (k, v) in s.key_val_iter() { match (k, v) { ("env", Some(v)) => { diff --git a/zbus/src/address/transport/mod.rs b/zbus/src/address/transport/mod.rs index 3d8a2585d..e98cf570c 100644 --- a/zbus/src/address/transport/mod.rs +++ b/zbus/src/address/transport/mod.rs @@ -75,6 +75,12 @@ impl fmt::Display for Transport<'_> { } } +pub(crate) trait TransportImpl<'a> { + fn for_address(s: &'a Address<'a>) -> Result + where + Self: Sized; +} + impl KeyValFmtAdd for Transport<'_> { fn key_val_fmt_add<'a: 'b, 'b>(&'a self, kv: KeyValFmt<'b>) -> KeyValFmt<'b> { match self { @@ -92,22 +98,20 @@ impl KeyValFmtAdd for Transport<'_> { } } -impl<'a> TryFrom<&'a Address<'a>> for Transport<'a> { - type Error = Error; - - fn try_from(s: &'a Address<'a>) -> Result { +impl<'a> TransportImpl<'a> for Transport<'a> { + fn for_address(s: &'a Address<'a>) -> Result { let col = s.addr.find(':').ok_or(Error::MissingTransport)?; match &s.addr[..col] { - "unix" => Ok(Self::Unix(s.try_into()?)), + "unix" => Ok(Self::Unix(Unix::for_address(s)?)), #[cfg(target_os = "macos")] - "launchd" => Ok(Self::Launchd(s.try_into()?)), + "launchd" => Ok(Self::Launchd(Launchd::for_address(s)?)), #[cfg(target_os = "linux")] - "systemd" => Ok(Self::Systemd(s.try_into()?)), - "tcp" => Ok(Self::Tcp(s.try_into()?)), - "nonce-tcp" => Ok(Self::NonceTcp(s.try_into()?)), - "unixexec" => Ok(Self::Unixexec(s.try_into()?)), - "autolaunch" => Ok(Self::Autolaunch(s.try_into()?)), - "vsock" => Ok(Self::Vsock(s.try_into()?)), + "systemd" => Ok(Self::Systemd(Systemd::for_address(s)?)), + "tcp" => Ok(Self::Tcp(Tcp::for_address(s)?)), + "nonce-tcp" => Ok(Self::NonceTcp(NonceTcp::for_address(s)?)), + "unixexec" => Ok(Self::Unixexec(Unixexec::for_address(s)?)), + "autolaunch" => Ok(Self::Autolaunch(Autolaunch::for_address(s)?)), + "vsock" => Ok(Self::Vsock(Vsock::for_address(s)?)), _ => Err(Error::UnknownTransport), } } diff --git a/zbus/src/address/transport/nonce_tcp.rs b/zbus/src/address/transport/nonce_tcp.rs index f0240f50d..fe3684756 100644 --- a/zbus/src/address/transport/nonce_tcp.rs +++ b/zbus/src/address/transport/nonce_tcp.rs @@ -3,7 +3,7 @@ use std::{borrow::Cow, ffi::OsStr}; use super::{ percent::{decode_percents_os_str, decode_percents_str, EncOsStr}, tcp::TcpFamily, - Address, Error, KeyValFmt, KeyValFmtAdd, Result, + Address, Error, KeyValFmt, KeyValFmtAdd, Result, TransportImpl, }; /// `nonce-tcp:` D-Bus transport. @@ -65,10 +65,8 @@ impl KeyValFmtAdd for NonceTcp<'_> { } } -impl<'a> TryFrom<&'a Address<'a>> for NonceTcp<'a> { - type Error = Error; - - fn try_from(s: &'a Address<'a>) -> Result { +impl<'a> TransportImpl<'a> for NonceTcp<'a> { + fn for_address(s: &'a Address<'a>) -> Result { let mut res = NonceTcp::default(); for (k, v) in s.key_val_iter() { match (k, v) { diff --git a/zbus/src/address/transport/systemd.rs b/zbus/src/address/transport/systemd.rs index 5f6350f86..89a844d00 100644 --- a/zbus/src/address/transport/systemd.rs +++ b/zbus/src/address/transport/systemd.rs @@ -1,6 +1,6 @@ use std::marker::PhantomData; -use super::{Address, Error, KeyValFmt, KeyValFmtAdd, Result}; +use super::{Address, KeyValFmt, KeyValFmtAdd, Result, TransportImpl}; /// `systemd:` D-Bus transport. /// @@ -11,10 +11,8 @@ pub struct Systemd<'a> { phantom: PhantomData<&'a ()>, } -impl<'a> TryFrom<&'a Address<'a>> for Systemd<'a> { - type Error = Error; - - fn try_from(_s: &'a Address<'a>) -> Result { +impl<'a> TransportImpl<'a> for Systemd<'a> { + fn for_address(_addr: &'a Address<'a>) -> Result { Ok(Systemd { phantom: PhantomData, }) diff --git a/zbus/src/address/transport/tcp.rs b/zbus/src/address/transport/tcp.rs index 2f1969e2d..acaa5cb05 100644 --- a/zbus/src/address/transport/tcp.rs +++ b/zbus/src/address/transport/tcp.rs @@ -1,6 +1,8 @@ use std::{borrow::Cow, fmt}; -use super::{percent::decode_percents_str, Address, Error, KeyValFmt, KeyValFmtAdd, Result}; +use super::{ + percent::decode_percents_str, Address, Error, KeyValFmt, KeyValFmtAdd, Result, TransportImpl, +}; /// TCP IP address family #[derive(Debug, PartialEq, Eq, Clone, Copy)] @@ -83,10 +85,8 @@ impl KeyValFmtAdd for Tcp<'_> { } } -impl<'a> TryFrom<&'a Address<'a>> for Tcp<'a> { - type Error = Error; - - fn try_from(s: &'a Address<'a>) -> Result { +impl<'a> TransportImpl<'a> for Tcp<'a> { + fn for_address(s: &'a Address<'a>) -> Result { let mut res = Tcp::default(); for (k, v) in s.key_val_iter() { match (k, v) { diff --git a/zbus/src/address/transport/unix.rs b/zbus/src/address/transport/unix.rs index d105ce18b..c466aaa57 100644 --- a/zbus/src/address/transport/unix.rs +++ b/zbus/src/address/transport/unix.rs @@ -2,7 +2,7 @@ use std::{borrow::Cow, ffi::OsStr}; use super::{ percent::{decode_percents, decode_percents_os_str, decode_percents_str, EncData, EncOsStr}, - Address, Error, KeyValFmt, KeyValFmtAdd, Result, + Address, Error, KeyValFmt, KeyValFmtAdd, Result, TransportImpl, }; /// A sub-type of `unix:` transport. @@ -52,10 +52,8 @@ impl<'a> Unix<'a> { } } -impl<'a> TryFrom<&'a Address<'a>> for Unix<'a> { - type Error = Error; - - fn try_from(s: &'a Address<'a>) -> Result { +impl<'a> TransportImpl<'a> for Unix<'a> { + fn for_address(s: &'a Address<'a>) -> Result { let mut kind = None; let mut iter = s.key_val_iter(); for (k, v) in &mut iter { diff --git a/zbus/src/address/transport/unixexec.rs b/zbus/src/address/transport/unixexec.rs index a74137049..df0c95b02 100644 --- a/zbus/src/address/transport/unixexec.rs +++ b/zbus/src/address/transport/unixexec.rs @@ -2,7 +2,7 @@ use std::{borrow::Cow, ffi::OsStr, fmt}; use super::{ percent::{decode_percents_os_str, decode_percents_str, EncOsStr}, - Address, Error, KeyValFmt, KeyValFmtAdd, Result, + Address, Error, KeyValFmt, KeyValFmtAdd, Result, TransportImpl, }; #[derive(Debug, PartialEq, Eq)] @@ -43,10 +43,8 @@ impl<'a> Unixexec<'a> { } } -impl<'a> TryFrom<&'a Address<'a>> for Unixexec<'a> { - type Error = Error; - - fn try_from(s: &'a Address<'a>) -> Result { +impl<'a> TransportImpl<'a> for Unixexec<'a> { + fn for_address(s: &'a Address<'a>) -> Result { let mut path = None; let mut argv = Vec::new(); diff --git a/zbus/src/address/transport/vsock.rs b/zbus/src/address/transport/vsock.rs index a160f00ba..e69504754 100644 --- a/zbus/src/address/transport/vsock.rs +++ b/zbus/src/address/transport/vsock.rs @@ -1,6 +1,8 @@ use std::marker::PhantomData; -use super::{percent::decode_percents_str, Address, Error, KeyValFmt, KeyValFmtAdd, Result}; +use super::{ + percent::decode_percents_str, Address, Error, KeyValFmt, KeyValFmtAdd, Result, TransportImpl, +}; /// `vsock:` D-Bus transport. #[derive(Debug, PartialEq, Eq)] @@ -25,10 +27,8 @@ impl<'a> Vsock<'a> { } } -impl<'a> TryFrom<&'a Address<'a>> for Vsock<'a> { - type Error = Error; - - fn try_from(s: &'a Address<'a>) -> Result { +impl<'a> TransportImpl<'a> for Vsock<'a> { + fn for_address(s: &'a Address<'a>) -> Result { let mut port = None; let mut cid = None; From f771394a9d42ab12f2c6e2bbe397a15aa24eb9a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 7 Oct 2024 12:46:10 +0400 Subject: [PATCH 03/13] =?UTF-8?q?=F0=9F=9A=9A=20zb:=20merge=20KeyValFmtAdd?= =?UTF-8?q?=20trait=20in=20TransportImpl?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As requested by Zeeshan. --- zbus/src/address/mod.rs | 10 +++---- zbus/src/address/transport/autolaunch.rs | 8 ++---- zbus/src/address/transport/launchd.rs | 8 ++---- zbus/src/address/transport/mod.rs | 35 ++++++++++++------------ zbus/src/address/transport/nonce_tcp.rs | 20 ++++++-------- zbus/src/address/transport/systemd.rs | 6 ++-- zbus/src/address/transport/tcp.rs | 20 ++++++-------- zbus/src/address/transport/unix.rs | 12 ++++---- zbus/src/address/transport/unixexec.rs | 6 ++-- zbus/src/address/transport/vsock.rs | 8 ++---- 10 files changed, 56 insertions(+), 77 deletions(-) diff --git a/zbus/src/address/mod.rs b/zbus/src/address/mod.rs index 87e3d9604..b48dfab61 100644 --- a/zbus/src/address/mod.rs +++ b/zbus/src/address/mod.rs @@ -223,7 +223,7 @@ impl fmt::Display for Address<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let kv = KeyValFmt::new().add("guid", self.guid()); let t = self.transport().map_err(|_| fmt::Error)?; - let kv = t.key_val_fmt_add(kv); + let kv = t.fmt_key_val(kv); write!(f, "{t}:{kv}")?; Ok(()) } @@ -266,10 +266,10 @@ impl<'a> Iterator for KeyValIter<'a> { } } -pub(crate) trait KeyValFmtAdd { - fn key_val_fmt_add<'a: 'b, 'b>(&'a self, kv: KeyValFmt<'b>) -> KeyValFmt<'b>; -} - +// A structure for formatting key-value pairs. +// +// This struct allows for the dynamic collection and formatting of key-value pairs, +// where keys implement `fmt::Display` and values implement `Encodable`. pub(crate) struct KeyValFmt<'a> { fields: Vec<(Box, Box)>, } diff --git a/zbus/src/address/transport/autolaunch.rs b/zbus/src/address/transport/autolaunch.rs index 76526a63b..c27bf0731 100644 --- a/zbus/src/address/transport/autolaunch.rs +++ b/zbus/src/address/transport/autolaunch.rs @@ -4,7 +4,7 @@ use std::{borrow::Cow, fmt}; #[cfg(target_os = "windows")] use super::percent::decode_percents_str; -use super::{Address, KeyValFmt, KeyValFmtAdd, Result, TransportImpl}; +use super::{Address, KeyValFmt, Result, TransportImpl}; /// Scope of autolaunch (Windows only) #[cfg(target_os = "windows")] @@ -32,7 +32,7 @@ impl fmt::Display for AutolaunchScope<'_> { #[cfg(target_os = "windows")] impl<'a> TryFrom> for AutolaunchScope<'a> { - type Error = Error; + type Error = super::Error; fn try_from(s: Cow<'a, str>) -> Result { match s.as_ref() { @@ -78,10 +78,8 @@ impl<'a> TransportImpl<'a> for Autolaunch<'a> { Ok(res) } -} -impl KeyValFmtAdd for Autolaunch<'_> { - fn key_val_fmt_add<'a: 'b, 'b>(&'a self, kv: KeyValFmt<'b>) -> KeyValFmt<'b> { + fn fmt_key_val<'s: 'b, 'b>(&'s self, kv: KeyValFmt<'b>) -> KeyValFmt<'b> { #[cfg(target_os = "windows")] let kv = kv.add("scope", self.scope()); kv diff --git a/zbus/src/address/transport/launchd.rs b/zbus/src/address/transport/launchd.rs index 578752774..f3800b45f 100644 --- a/zbus/src/address/transport/launchd.rs +++ b/zbus/src/address/transport/launchd.rs @@ -1,8 +1,6 @@ use std::borrow::Cow; -use super::{ - percent::decode_percents_str, Address, Error, KeyValFmt, KeyValFmtAdd, Result, TransportImpl, -}; +use super::{percent::decode_percents_str, Address, Error, KeyValFmt, Result, TransportImpl}; /// `launchd:` D-Bus transport. /// @@ -37,10 +35,8 @@ impl<'a> TransportImpl<'a> for Launchd<'a> { Err(Error::MissingKey("env".into())) } -} -impl KeyValFmtAdd for Launchd<'_> { - fn key_val_fmt_add<'a: 'b, 'b>(&'a self, kv: KeyValFmt<'b>) -> KeyValFmt<'b> { + fn fmt_key_val<'s: 'b, 'b>(&'s self, kv: KeyValFmt<'b>) -> KeyValFmt<'b> { kv.add("env", Some(self.env())) } } diff --git a/zbus/src/address/transport/mod.rs b/zbus/src/address/transport/mod.rs index e98cf570c..3954eed40 100644 --- a/zbus/src/address/transport/mod.rs +++ b/zbus/src/address/transport/mod.rs @@ -2,7 +2,7 @@ use std::fmt; -use super::{percent, Address, Error, KeyValFmt, KeyValFmtAdd, Result}; +use super::{percent, Address, Error, KeyValFmt, Result}; mod autolaunch; pub use autolaunch::Autolaunch; @@ -79,23 +79,9 @@ pub(crate) trait TransportImpl<'a> { fn for_address(s: &'a Address<'a>) -> Result where Self: Sized; -} -impl KeyValFmtAdd for Transport<'_> { - fn key_val_fmt_add<'a: 'b, 'b>(&'a self, kv: KeyValFmt<'b>) -> KeyValFmt<'b> { - match self { - Self::Unix(t) => t.key_val_fmt_add(kv), - #[cfg(target_os = "macos")] - Self::Launchd(t) => t.key_val_fmt_add(kv), - #[cfg(target_os = "linux")] - Self::Systemd(t) => t.key_val_fmt_add(kv), - Self::Tcp(t) => t.key_val_fmt_add(kv), - Self::NonceTcp(t) => t.key_val_fmt_add(kv), - Self::Unixexec(t) => t.key_val_fmt_add(kv), - Self::Autolaunch(t) => t.key_val_fmt_add(kv), - Self::Vsock(t) => t.key_val_fmt_add(kv), - } - } + // add() the transport (key,val) pairs to KeyValFmt + fn fmt_key_val<'s: 'b, 'b>(&'s self, kv: KeyValFmt<'b>) -> KeyValFmt<'b>; } impl<'a> TransportImpl<'a> for Transport<'a> { @@ -115,4 +101,19 @@ impl<'a> TransportImpl<'a> for Transport<'a> { _ => Err(Error::UnknownTransport), } } + + fn fmt_key_val<'s: 'b, 'b>(&'s self, kv: KeyValFmt<'b>) -> KeyValFmt<'b> { + match self { + Self::Unix(t) => t.fmt_key_val(kv), + #[cfg(target_os = "macos")] + Self::Launchd(t) => t.fmt_key_val(kv), + #[cfg(target_os = "linux")] + Self::Systemd(t) => t.fmt_key_val(kv), + Self::Tcp(t) => t.fmt_key_val(kv), + Self::NonceTcp(t) => t.fmt_key_val(kv), + Self::Unixexec(t) => t.fmt_key_val(kv), + Self::Autolaunch(t) => t.fmt_key_val(kv), + Self::Vsock(t) => t.fmt_key_val(kv), + } + } } diff --git a/zbus/src/address/transport/nonce_tcp.rs b/zbus/src/address/transport/nonce_tcp.rs index fe3684756..1b6485acb 100644 --- a/zbus/src/address/transport/nonce_tcp.rs +++ b/zbus/src/address/transport/nonce_tcp.rs @@ -3,7 +3,7 @@ use std::{borrow::Cow, ffi::OsStr}; use super::{ percent::{decode_percents_os_str, decode_percents_str, EncOsStr}, tcp::TcpFamily, - Address, Error, KeyValFmt, KeyValFmtAdd, Result, TransportImpl, + Address, Error, KeyValFmt, Result, TransportImpl, }; /// `nonce-tcp:` D-Bus transport. @@ -55,16 +55,6 @@ impl<'a> NonceTcp<'a> { } } -impl KeyValFmtAdd for NonceTcp<'_> { - fn key_val_fmt_add<'a: 'b, 'b>(&'a self, kv: KeyValFmt<'b>) -> KeyValFmt<'b> { - kv.add("host", self.host()) - .add("bind", self.bind()) - .add("port", self.port()) - .add("family", self.family()) - .add("noncefile", self.noncefile().map(EncOsStr)) - } -} - impl<'a> TransportImpl<'a> for NonceTcp<'a> { fn for_address(s: &'a Address<'a>) -> Result { let mut res = NonceTcp::default(); @@ -95,4 +85,12 @@ impl<'a> TransportImpl<'a> for NonceTcp<'a> { Ok(res) } + + fn fmt_key_val<'s: 'b, 'b>(&'s self, kv: KeyValFmt<'b>) -> KeyValFmt<'b> { + kv.add("host", self.host()) + .add("bind", self.bind()) + .add("port", self.port()) + .add("family", self.family()) + .add("noncefile", self.noncefile().map(EncOsStr)) + } } diff --git a/zbus/src/address/transport/systemd.rs b/zbus/src/address/transport/systemd.rs index 89a844d00..bd3f2ff5c 100644 --- a/zbus/src/address/transport/systemd.rs +++ b/zbus/src/address/transport/systemd.rs @@ -1,6 +1,6 @@ use std::marker::PhantomData; -use super::{Address, KeyValFmt, KeyValFmtAdd, Result, TransportImpl}; +use super::{Address, KeyValFmt, Result, TransportImpl}; /// `systemd:` D-Bus transport. /// @@ -17,10 +17,8 @@ impl<'a> TransportImpl<'a> for Systemd<'a> { phantom: PhantomData, }) } -} -impl KeyValFmtAdd for Systemd<'_> { - fn key_val_fmt_add<'a: 'b, 'b>(&'a self, kv: KeyValFmt<'b>) -> KeyValFmt<'b> { + fn fmt_key_val<'s: 'b, 'b>(&'s self, kv: KeyValFmt<'b>) -> KeyValFmt<'b> { kv } } diff --git a/zbus/src/address/transport/tcp.rs b/zbus/src/address/transport/tcp.rs index acaa5cb05..feace18c3 100644 --- a/zbus/src/address/transport/tcp.rs +++ b/zbus/src/address/transport/tcp.rs @@ -1,8 +1,6 @@ use std::{borrow::Cow, fmt}; -use super::{ - percent::decode_percents_str, Address, Error, KeyValFmt, KeyValFmtAdd, Result, TransportImpl, -}; +use super::{percent::decode_percents_str, Address, Error, KeyValFmt, Result, TransportImpl}; /// TCP IP address family #[derive(Debug, PartialEq, Eq, Clone, Copy)] @@ -76,15 +74,6 @@ impl<'a> Tcp<'a> { } } -impl KeyValFmtAdd for Tcp<'_> { - fn key_val_fmt_add<'a: 'b, 'b>(&'a self, kv: KeyValFmt<'b>) -> KeyValFmt<'b> { - kv.add("host", self.host()) - .add("bind", self.bind()) - .add("port", self.port()) - .add("family", self.family()) - } -} - impl<'a> TransportImpl<'a> for Tcp<'a> { fn for_address(s: &'a Address<'a>) -> Result { let mut res = Tcp::default(); @@ -112,4 +101,11 @@ impl<'a> TransportImpl<'a> for Tcp<'a> { Ok(res) } + + fn fmt_key_val<'s: 'b, 'b>(&'s self, kv: KeyValFmt<'b>) -> KeyValFmt<'b> { + kv.add("host", self.host()) + .add("bind", self.bind()) + .add("port", self.port()) + .add("family", self.family()) + } } diff --git a/zbus/src/address/transport/unix.rs b/zbus/src/address/transport/unix.rs index c466aaa57..e9095ac0b 100644 --- a/zbus/src/address/transport/unix.rs +++ b/zbus/src/address/transport/unix.rs @@ -2,7 +2,7 @@ use std::{borrow::Cow, ffi::OsStr}; use super::{ percent::{decode_percents, decode_percents_os_str, decode_percents_str, EncData, EncOsStr}, - Address, Error, KeyValFmt, KeyValFmtAdd, Result, TransportImpl, + Address, Error, KeyValFmt, Result, TransportImpl, }; /// A sub-type of `unix:` transport. @@ -25,8 +25,8 @@ pub enum UnixAddrKind<'a> { Runtime, } -impl KeyValFmtAdd for UnixAddrKind<'_> { - fn key_val_fmt_add<'a: 'b, 'b>(&'a self, kv: KeyValFmt<'b>) -> KeyValFmt<'b> { +impl UnixAddrKind<'_> { + fn fmt_key_val<'s: 'b, 'b>(&'s self, kv: KeyValFmt<'b>) -> KeyValFmt<'b> { match self { UnixAddrKind::Path(p) => kv.add("path", Some(EncOsStr(p))), UnixAddrKind::Dir(p) => kv.add("dir", Some(EncOsStr(p))), @@ -107,10 +107,8 @@ impl<'a> TransportImpl<'a> for Unix<'a> { Ok(Unix { kind }) } -} -impl KeyValFmtAdd for Unix<'_> { - fn key_val_fmt_add<'a: 'b, 'b>(&'a self, kv: KeyValFmt<'b>) -> KeyValFmt<'b> { - self.kind().key_val_fmt_add(kv) + fn fmt_key_val<'s: 'b, 'b>(&'s self, kv: KeyValFmt<'b>) -> KeyValFmt<'b> { + self.kind().fmt_key_val(kv) } } diff --git a/zbus/src/address/transport/unixexec.rs b/zbus/src/address/transport/unixexec.rs index df0c95b02..fe15f3c1a 100644 --- a/zbus/src/address/transport/unixexec.rs +++ b/zbus/src/address/transport/unixexec.rs @@ -2,7 +2,7 @@ use std::{borrow::Cow, ffi::OsStr, fmt}; use super::{ percent::{decode_percents_os_str, decode_percents_str, EncOsStr}, - Address, Error, KeyValFmt, KeyValFmtAdd, Result, TransportImpl, + Address, Error, KeyValFmt, Result, TransportImpl, }; #[derive(Debug, PartialEq, Eq)] @@ -70,10 +70,8 @@ impl<'a> TransportImpl<'a> for Unixexec<'a> { Ok(Self { path, argv }) } -} -impl KeyValFmtAdd for Unixexec<'_> { - fn key_val_fmt_add<'a: 'b, 'b>(&'a self, mut kv: KeyValFmt<'b>) -> KeyValFmt<'b> { + fn fmt_key_val<'s: 'b, 'b>(&'s self, mut kv: KeyValFmt<'b>) -> KeyValFmt<'b> { kv = kv.add("path", Some(EncOsStr(self.path()))); for (n, arg) in self.argv() { kv = kv.add(Argv(*n), Some(arg)); diff --git a/zbus/src/address/transport/vsock.rs b/zbus/src/address/transport/vsock.rs index e69504754..289314e52 100644 --- a/zbus/src/address/transport/vsock.rs +++ b/zbus/src/address/transport/vsock.rs @@ -1,8 +1,6 @@ use std::marker::PhantomData; -use super::{ - percent::decode_percents_str, Address, Error, KeyValFmt, KeyValFmtAdd, Result, TransportImpl, -}; +use super::{percent::decode_percents_str, Address, Error, KeyValFmt, Result, TransportImpl}; /// `vsock:` D-Bus transport. #[derive(Debug, PartialEq, Eq)] @@ -58,10 +56,8 @@ impl<'a> TransportImpl<'a> for Vsock<'a> { phantom: PhantomData, }) } -} -impl KeyValFmtAdd for Vsock<'_> { - fn key_val_fmt_add<'a: 'b, 'b>(&'a self, kv: KeyValFmt<'b>) -> KeyValFmt<'b> { + fn fmt_key_val<'s: 'b, 'b>(&'s self, kv: KeyValFmt<'b>) -> KeyValFmt<'b> { kv.add("cid", self.cid()).add("port", self.port()) } } From cccbac2f7cb49ef721e8b3da03d5007a01aaf74e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 8 Oct 2024 17:54:21 +0400 Subject: [PATCH 04/13] =?UTF-8?q?=F0=9F=8E=A8=20zb:=20move=20top-level=20p?= =?UTF-8?q?ublic=20stuff=20before=20lower-level=20&=20private?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As requested by Zeeshan. --- zbus/src/address/percent.rs | 66 ++++++++++----------- zbus/src/address/transport/autolaunch.rs | 74 ++++++++++++------------ zbus/src/address/transport/tcp.rs | 62 ++++++++++---------- zbus/src/address/transport/unix.rs | 64 ++++++++++---------- zbus/src/address/transport/unixexec.rs | 22 +++---- 5 files changed, 144 insertions(+), 144 deletions(-) diff --git a/zbus/src/address/percent.rs b/zbus/src/address/percent.rs index ccd2c6310..a65c1891a 100644 --- a/zbus/src/address/percent.rs +++ b/zbus/src/address/percent.rs @@ -6,39 +6,6 @@ use std::{ use super::{Error, Result}; -// A trait for types that can be percent-encoded and written to a [`fmt::Formatter`]. -pub(crate) trait Encodable { - fn encode(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result; -} - -impl Encodable for T { - fn encode(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result { - encode_percents(f, self.to_string().as_bytes()) - } -} - -pub(crate) struct EncData(pub T); - -impl> Encodable for EncData { - fn encode(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result { - encode_percents(f, self.0.as_ref()) - } -} - -pub(crate) struct EncOsStr(pub T); - -impl Encodable for EncOsStr<&Cow<'_, OsStr>> { - fn encode(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result { - encode_percents(f, self.0.to_string_lossy().as_bytes()) - } -} - -impl Encodable for EncOsStr<&OsStr> { - fn encode(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result { - encode_percents(f, self.0.to_string_lossy().as_bytes()) - } -} - /// Percent-encode the value. pub fn encode_percents(f: &mut dyn fmt::Write, value: &[u8]) -> std::fmt::Result { for &byte in value { @@ -86,6 +53,39 @@ pub fn decode_percents(value: &str) -> Result> { Ok(Cow::Owned(decoded)) } +// A trait for types that can be percent-encoded and written to a [`fmt::Formatter`]. +pub(crate) trait Encodable { + fn encode(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result; +} + +impl Encodable for T { + fn encode(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result { + encode_percents(f, self.to_string().as_bytes()) + } +} + +pub(crate) struct EncData(pub T); + +impl> Encodable for EncData { + fn encode(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result { + encode_percents(f, self.0.as_ref()) + } +} + +pub(crate) struct EncOsStr(pub T); + +impl Encodable for EncOsStr<&Cow<'_, OsStr>> { + fn encode(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result { + encode_percents(f, self.0.to_string_lossy().as_bytes()) + } +} + +impl Encodable for EncOsStr<&OsStr> { + fn encode(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result { + encode_percents(f, self.0.to_string_lossy().as_bytes()) + } +} + fn is_allowed_char(c: char) -> bool { matches!(c, '-' | '0'..='9' | 'A'..='Z' | 'a'..='z' | '_' | '/' | '.' | '\\' | '*') } diff --git a/zbus/src/address/transport/autolaunch.rs b/zbus/src/address/transport/autolaunch.rs index c27bf0731..75ce71847 100644 --- a/zbus/src/address/transport/autolaunch.rs +++ b/zbus/src/address/transport/autolaunch.rs @@ -6,43 +6,6 @@ use std::{borrow::Cow, fmt}; use super::percent::decode_percents_str; use super::{Address, KeyValFmt, Result, TransportImpl}; -/// Scope of autolaunch (Windows only) -#[cfg(target_os = "windows")] -#[derive(Debug, PartialEq, Eq)] -#[non_exhaustive] -pub enum AutolaunchScope<'a> { - /// Limit session bus to dbus installation path. - InstallPath, - /// Limit session bus to the recent user. - User, - /// other values - specify dedicated session bus like "release", "debug" or other. - Other(Cow<'a, str>), -} - -#[cfg(target_os = "windows")] -impl fmt::Display for AutolaunchScope<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::InstallPath => write!(f, "*install-path"), - Self::User => write!(f, "*user"), - Self::Other(o) => write!(f, "{o}"), - } - } -} - -#[cfg(target_os = "windows")] -impl<'a> TryFrom> for AutolaunchScope<'a> { - type Error = super::Error; - - fn try_from(s: Cow<'a, str>) -> Result { - match s.as_ref() { - "*install-path" => Ok(Self::InstallPath), - "*user" => Ok(Self::User), - _ => Ok(Self::Other(s)), - } - } -} - /// `autolaunch:` D-Bus transport. /// /// @@ -85,3 +48,40 @@ impl<'a> TransportImpl<'a> for Autolaunch<'a> { kv } } + +/// Scope of autolaunch (Windows only) +#[cfg(target_os = "windows")] +#[derive(Debug, PartialEq, Eq)] +#[non_exhaustive] +pub enum AutolaunchScope<'a> { + /// Limit session bus to dbus installation path. + InstallPath, + /// Limit session bus to the recent user. + User, + /// other values - specify dedicated session bus like "release", "debug" or other. + Other(Cow<'a, str>), +} + +#[cfg(target_os = "windows")] +impl fmt::Display for AutolaunchScope<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::InstallPath => write!(f, "*install-path"), + Self::User => write!(f, "*user"), + Self::Other(o) => write!(f, "{o}"), + } + } +} + +#[cfg(target_os = "windows")] +impl<'a> TryFrom> for AutolaunchScope<'a> { + type Error = super::Error; + + fn try_from(s: Cow<'a, str>) -> Result { + match s.as_ref() { + "*install-path" => Ok(Self::InstallPath), + "*user" => Ok(Self::User), + _ => Ok(Self::Other(s)), + } + } +} diff --git a/zbus/src/address/transport/tcp.rs b/zbus/src/address/transport/tcp.rs index feace18c3..ee287cd45 100644 --- a/zbus/src/address/transport/tcp.rs +++ b/zbus/src/address/transport/tcp.rs @@ -2,37 +2,6 @@ use std::{borrow::Cow, fmt}; use super::{percent::decode_percents_str, Address, Error, KeyValFmt, Result, TransportImpl}; -/// TCP IP address family -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -#[non_exhaustive] -pub enum TcpFamily { - /// IPv4 - IPv4, - /// IPv6 - IPv6, -} - -impl fmt::Display for TcpFamily { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::IPv4 => write!(f, "ipv4"), - Self::IPv6 => write!(f, "ipv6"), - } - } -} - -impl TryFrom<&str> for TcpFamily { - type Error = Error; - - fn try_from(s: &str) -> Result { - match s { - "ipv4" => Ok(Self::IPv4), - "ipv6" => Ok(Self::IPv6), - _ => Err(Error::UnknownTcpFamily(s.into())), - } - } -} - /// `tcp:` D-Bus transport. /// /// @@ -109,3 +78,34 @@ impl<'a> TransportImpl<'a> for Tcp<'a> { .add("family", self.family()) } } + +/// TCP IP address family +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[non_exhaustive] +pub enum TcpFamily { + /// IPv4 + IPv4, + /// IPv6 + IPv6, +} + +impl fmt::Display for TcpFamily { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::IPv4 => write!(f, "ipv4"), + Self::IPv6 => write!(f, "ipv6"), + } + } +} + +impl TryFrom<&str> for TcpFamily { + type Error = Error; + + fn try_from(s: &str) -> Result { + match s { + "ipv4" => Ok(Self::IPv4), + "ipv6" => Ok(Self::IPv6), + _ => Err(Error::UnknownTcpFamily(s.into())), + } + } +} diff --git a/zbus/src/address/transport/unix.rs b/zbus/src/address/transport/unix.rs index e9095ac0b..f0a9f8b92 100644 --- a/zbus/src/address/transport/unix.rs +++ b/zbus/src/address/transport/unix.rs @@ -5,38 +5,6 @@ use super::{ Address, Error, KeyValFmt, Result, TransportImpl, }; -/// A sub-type of `unix:` transport. -#[derive(Debug, PartialEq, Eq)] -#[non_exhaustive] -pub enum UnixAddrKind<'a> { - /// Path of the unix domain socket. - Path(Cow<'a, OsStr>), - /// Directory in which a socket file with a random file name starting with 'dbus-' should be - /// created by a server. - Dir(Cow<'a, OsStr>), - /// The same as "dir", except that on platforms with abstract sockets, a server may attempt to - /// create an abstract socket whose name starts with this directory instead of a path-based - /// socket. - Tmpdir(Cow<'a, OsStr>), - /// Unique string in the abstract namespace, often syntactically resembling a path but - /// unconnected to the filesystem namespace - Abstract(Cow<'a, [u8]>), - /// Listen on $XDG_RUNTIME_DIR/bus. - Runtime, -} - -impl UnixAddrKind<'_> { - fn fmt_key_val<'s: 'b, 'b>(&'s self, kv: KeyValFmt<'b>) -> KeyValFmt<'b> { - match self { - UnixAddrKind::Path(p) => kv.add("path", Some(EncOsStr(p))), - UnixAddrKind::Dir(p) => kv.add("dir", Some(EncOsStr(p))), - UnixAddrKind::Tmpdir(p) => kv.add("tmpdir", Some(EncOsStr(p))), - UnixAddrKind::Abstract(p) => kv.add("abstract", Some(EncData(p))), - UnixAddrKind::Runtime => kv.add("runtime", Some("yes")), - } - } -} - /// `unix:` D-Bus transport. /// /// @@ -112,3 +80,35 @@ impl<'a> TransportImpl<'a> for Unix<'a> { self.kind().fmt_key_val(kv) } } + +/// A sub-type of `unix:` transport. +#[derive(Debug, PartialEq, Eq)] +#[non_exhaustive] +pub enum UnixAddrKind<'a> { + /// Path of the unix domain socket. + Path(Cow<'a, OsStr>), + /// Directory in which a socket file with a random file name starting with 'dbus-' should be + /// created by a server. + Dir(Cow<'a, OsStr>), + /// The same as "dir", except that on platforms with abstract sockets, a server may attempt to + /// create an abstract socket whose name starts with this directory instead of a path-based + /// socket. + Tmpdir(Cow<'a, OsStr>), + /// Unique string in the abstract namespace, often syntactically resembling a path but + /// unconnected to the filesystem namespace + Abstract(Cow<'a, [u8]>), + /// Listen on $XDG_RUNTIME_DIR/bus. + Runtime, +} + +impl UnixAddrKind<'_> { + fn fmt_key_val<'s: 'b, 'b>(&'s self, kv: KeyValFmt<'b>) -> KeyValFmt<'b> { + match self { + UnixAddrKind::Path(p) => kv.add("path", Some(EncOsStr(p))), + UnixAddrKind::Dir(p) => kv.add("dir", Some(EncOsStr(p))), + UnixAddrKind::Tmpdir(p) => kv.add("tmpdir", Some(EncOsStr(p))), + UnixAddrKind::Abstract(p) => kv.add("abstract", Some(EncData(p))), + UnixAddrKind::Runtime => kv.add("runtime", Some("yes")), + } + } +} diff --git a/zbus/src/address/transport/unixexec.rs b/zbus/src/address/transport/unixexec.rs index fe15f3c1a..9501cfe49 100644 --- a/zbus/src/address/transport/unixexec.rs +++ b/zbus/src/address/transport/unixexec.rs @@ -5,17 +5,6 @@ use super::{ Address, Error, KeyValFmt, Result, TransportImpl, }; -#[derive(Debug, PartialEq, Eq)] -struct Argv(usize); - -impl fmt::Display for Argv { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let n = self.0; - - write!(f, "argv{n}") - } -} - /// `unixexec:` D-Bus transport. /// /// @@ -80,3 +69,14 @@ impl<'a> TransportImpl<'a> for Unixexec<'a> { kv } } + +#[derive(Debug, PartialEq, Eq)] +struct Argv(usize); + +impl fmt::Display for Argv { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let n = self.0; + + write!(f, "argv{n}") + } +} From d61763f5596ea69ba1594dc732c1cd42136b9ba7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 8 Oct 2024 19:26:34 +0400 Subject: [PATCH 05/13] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20=20zb:=20use=20more?= =?UTF-8?q?=20appropriate=20address=20errors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use address::Error::MissingValue for missing address fields. Use zbus::Error for errors that are not related to address handling as such, but rather higher-level. --- zbus/src/connection/connect/macos.rs | 14 +++++++++----- zbus/src/connection/connect/mod.rs | 5 +++-- zbus/src/connection/connect/win32.rs | 7 +++---- zbus/src/connection/socket/tcp.rs | 26 ++++++++++++++------------ zbus/src/connection/socket/unix.rs | 2 +- zbus/src/connection/socket/vsock.rs | 9 +++++---- zbus/src/win32.rs | 9 +++++---- 7 files changed, 40 insertions(+), 32 deletions(-) diff --git a/zbus/src/connection/connect/macos.rs b/zbus/src/connection/connect/macos.rs index 21db9b20c..85e7bbc63 100644 --- a/zbus/src/connection/connect/macos.rs +++ b/zbus/src/connection/connect/macos.rs @@ -2,7 +2,7 @@ use super::socket; use crate::{ - address::{transport::Transport, Address}, + address::{self, transport::Transport, Address}, process::run, Error, Result, }; @@ -13,14 +13,15 @@ async fn launchd_bus_address(env_key: &str) -> Result> { .expect("failed to wait on launchctl output"); if !output.status.success() { - return Err(Error::Address(format!( + return Err(Error::Failure(format!( "launchctl terminated with code: {}", output.status ))); } - let addr = String::from_utf8(output.stdout) - .map_err(|e| Error::Address(format!("Unable to parse launchctl output as UTF-8: {}", e)))?; + let addr = String::from_utf8(output.stdout).map_err(|e| { + address::Error::Encoding(format!("Unable to parse launchctl output as UTF-8: {}", e)) + })?; Ok(format!("unix:path={}", addr.trim()).try_into()?) } @@ -32,7 +33,10 @@ pub(crate) async fn connect( match addr.transport()? { Transport::Unix(t) => socket::unix::connect(&t).await, - _ => Err(Error::Address(format!("Address is unsupported: {}", addr))), + _ => { + tracing::debug!("Address is unsupported: {}", addr); + Err(Error::Unsupported) + } } } diff --git a/zbus/src/connection/connect/mod.rs b/zbus/src/connection/connect/mod.rs index 34e25b9f6..50f93ed70 100644 --- a/zbus/src/connection/connect/mod.rs +++ b/zbus/src/connection/connect/mod.rs @@ -24,7 +24,7 @@ pub(crate) async fn connect_address( } } } - Err(Error::Address("No connectable address".into())) + Err(Error::Failure("No connectable address".into())) } async fn connect(addr: &Address<'_>) -> ConnectResult { @@ -50,7 +50,8 @@ async fn connect(addr: &Address<'_>) -> ConnectResult { return win32::connect(&l).await; } _ => { - return Err(Error::Address(format!("Unhandled address: {}", addr))); + tracing::debug!("Unsupported address: {addr}"); + return Err(Error::Unsupported); } }; Ok((split, guid)) diff --git a/zbus/src/connection/connect/win32.rs b/zbus/src/connection/connect/win32.rs index 66dbb3740..989b1b043 100644 --- a/zbus/src/connection/connect/win32.rs +++ b/zbus/src/connection/connect/win32.rs @@ -13,15 +13,14 @@ pub(crate) fn connect<'l>( ) -> Pin + 'l>> { Box::pin(async move { if autolaunch.scope().is_some() { - return Err(Error::Address( - "autolaunch with scope isn't supported yet".into(), - )); + tracing::debug!("autolaunch with scope isn't supported yet"); + return Err(Error::Unsupported); } let addr: Address<'_> = autolaunch_bus_address()?.try_into()?; if let Transport::Autolaunch(_) = addr.transport()? { - return Err(Error::Address("Recursive autolaunch: address".into())); + return Err(Error::Failure("Recursive autolaunch: address".into())); } super::connect(&addr).await diff --git a/zbus/src/connection/socket/tcp.rs b/zbus/src/connection/socket/tcp.rs index 80c62a0da..7616bc9aa 100644 --- a/zbus/src/connection/socket/tcp.rs +++ b/zbus/src/connection/socket/tcp.rs @@ -6,7 +6,10 @@ use std::os::fd::BorrowedFd; #[cfg(not(feature = "tokio"))] use std::{net::TcpStream, sync::Arc}; -use crate::{address::transport::TcpFamily, Error, Result}; +use crate::{ + address::{self, transport::TcpFamily}, + Result, +}; use super::{ReadHalf, RecvmsgResult, WriteHalf}; #[cfg(feature = "tokio")] @@ -211,19 +214,18 @@ async fn connect_with(host: &str, port: u16, family: Option) -> Resul }, "connect tcp", ) - .await - .map_err(|e| Error::Address(format!("Failed to receive TCP addresses: {e}")))?; + .await?; // we could attempt connections in parallel? - let mut last_err = Error::Address("Failed to connect".into()); + let mut last_err = io::Error::other("No address"); for addr in addrs { match Stream::connect(addr).await { Ok(stream) => return Ok(stream), - Err(e) => last_err = e.into(), + Err(e) => last_err = e, } } - Err(last_err) + Err(last_err.into()) } #[cfg(feature = "tokio")] @@ -232,16 +234,16 @@ async fn connect_with(host: &str, port: u16, family: Option) -> Resul let _ = family; Stream::connect((host, port)) .await - .map_err(|e| Error::InputOutput(e.into())) + .map_err(|e| crate::Error::InputOutput(e.into())) } } pub(crate) async fn connect(addr: &crate::address::transport::Tcp<'_>) -> Result { let Some(host) = addr.host() else { - return Err(Error::Address("No host in address".into())); + return Err(address::Error::MissingValue("host".into()).into()); }; let Some(port) = addr.port() else { - return Err(Error::Address("No port in address".into())); + return Err(address::Error::MissingValue("port".into()).into()); }; connect_with(host, port, addr.family()).await @@ -251,13 +253,13 @@ pub(crate) async fn connect_nonce( addr: &crate::address::transport::NonceTcp<'_>, ) -> Result { let Some(host) = addr.host() else { - return Err(Error::Address("No host in address".into())); + return Err(address::Error::MissingValue("host".into()).into()); }; let Some(port) = addr.port() else { - return Err(Error::Address("No port in address".into())); + return Err(address::Error::MissingValue("port".into()).into()); }; let Some(noncefile) = addr.noncefile() else { - return Err(Error::Address("No noncefile in address".into())); + return Err(address::Error::MissingValue("noncefile".into()).into()); }; #[allow(unused_mut)] diff --git a/zbus/src/connection/socket/unix.rs b/zbus/src/connection/socket/unix.rs index 72edff430..48c212800 100644 --- a/zbus/src/connection/socket/unix.rs +++ b/zbus/src/connection/socket/unix.rs @@ -405,7 +405,7 @@ pub(crate) async fn connect(addr: &crate::address::transport::Unix<'_>) -> Resul UnixAddrKind::Path(p) => p.clone().into_owned(), #[cfg(target_os = "linux")] UnixAddrKind::Abstract(name) => SocketAddr::from_abstract_name(name)?, - _ => return Err(Error::Address("Address is not connectable".into())), + _ => return Err(Error::Failure("Address is not connectable".into())), }; let stream = crate::Task::spawn_blocking( diff --git a/zbus/src/connection/socket/vsock.rs b/zbus/src/connection/socket/vsock.rs index 5b138a0e5..e1cc1aefc 100644 --- a/zbus/src/connection/socket/vsock.rs +++ b/zbus/src/connection/socket/vsock.rs @@ -133,11 +133,13 @@ type Stream = tokio_vsock::VsockStream; feature = "tokio-vsock" ))] pub(crate) async fn connect(addr: &crate::address::transport::Vsock<'_>) -> Result { + use crate::address; + let Some(cid) = addr.cid() else { - return Err(Error::Address("No cid in address".into())); + return Err(address::Error::MissingValue("cid".into()).into()); }; let Some(port) = addr.port() else { - return Err(Error::Address("No port in address".into())); + return Err(address::Error::MissingValue("port".into()).into()); }; #[cfg(all(feature = "vsock", not(feature = "tokio")))] @@ -146,8 +148,7 @@ pub(crate) async fn connect(addr: &crate::address::transport::Vsock<'_>) -> Resu move || vsock::VsockStream::connect_with_cid_port(cid, port), "connect vsock", ) - .await - .map_err(|e| Error::Address(format!("Failed to connect: {e}")))?; + .await?; Ok(Async::new(stream).map_err(|e| Error::InputOutput(e.into()))?) } diff --git a/zbus/src/win32.rs b/zbus/src/win32.rs index 2d4d47653..ec391a667 100644 --- a/zbus/src/win32.rs +++ b/zbus/src/win32.rs @@ -288,7 +288,7 @@ fn read_shm(name: &str) -> Result, crate::Error> { // SAFETY: We have exclusive ownership over the file mapping handle unsafe { OwnedHandle::from_raw_handle(res as RawHandle) } } else { - return Err(crate::Error::Address( + return Err(crate::Error::Failure( "Unable to open shared memory".to_owned(), )); } @@ -297,7 +297,7 @@ fn read_shm(name: &str) -> Result, crate::Error> { let addr = unsafe { MapViewOfFile(handle.as_raw_handle(), FILE_MAP_READ, 0, 0, 0) }; if addr.Value.is_null() { - return Err(crate::Error::Address("MapViewOfFile() failed".to_owned())); + return Err(crate::Error::Failure("MapViewOfFile() failed".to_owned())); } let data = unsafe { CStr::from_ptr(addr.Value.cast()) }; @@ -309,8 +309,9 @@ pub fn autolaunch_bus_address() -> Result { let _guard = mutex.lock(); let addr = read_shm("DBusDaemonAddressInfo")?; - let addr = String::from_utf8(addr) - .map_err(|e| crate::Error::Address(format!("Unable to parse address as UTF-8: {}", e)))?; + let addr = String::from_utf8(addr).map_err(|e| { + crate::address::Error::Encoding(format!("Unable to parse address as UTF-8: {}", e)) + })?; Ok(addr) } From 341de4f605504bf9f0b169c48fb676992c8d2ef3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 8 Oct 2024 19:33:28 +0400 Subject: [PATCH 06/13] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20=20zb:=20change=20er?= =?UTF-8?q?ror::Address=20to=20be=20address::Error?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow users to catch specific error kinds. --- zbus/src/error.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/zbus/src/error.rs b/zbus/src/error.rs index 4adb4ed30..3c0cf204b 100644 --- a/zbus/src/error.rs +++ b/zbus/src/error.rs @@ -4,7 +4,7 @@ use zbus_names::{Error as NamesError, InterfaceName, OwnedErrorName}; use zvariant::{Error as VariantError, ObjectPath}; use crate::{ - fdo, + address, fdo, message::{Message, Type}, }; @@ -18,7 +18,7 @@ pub enum Error { /// Interface not found. InterfaceNotFound, /// Invalid D-Bus address. - Address(String), + Address(address::Error), /// An I/O error. InputOutput(Arc), /// Invalid message field. @@ -68,7 +68,7 @@ assert_impl_all!(Error: Send, Sync, Unpin); impl PartialEq for Error { fn eq(&self, other: &Self) -> bool { match (self, other) { - (Self::Address(_), Self::Address(_)) => true, + (Self::Address(s), Self::Address(o)) => s == o, (Self::InterfaceNotFound, Self::InterfaceNotFound) => true, (Self::Handshake(_), Self::Handshake(_)) => true, (Self::InvalidReply, Self::InvalidReply) => true, @@ -97,7 +97,7 @@ impl error::Error for Error { fn source(&self) -> Option<&(dyn error::Error + 'static)> { match self { Error::InterfaceNotFound => None, - Error::Address(_) => None, + Error::Address(s) => Some(s), Error::InputOutput(e) => Some(e), Error::ExcessData => None, Error::Handshake(_) => None, @@ -125,7 +125,7 @@ impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Error::InterfaceNotFound => write!(f, "Interface not found"), - Error::Address(e) => write!(f, "address error: {e}"), + Error::Address(e) => write!(f, "{e}"), Error::ExcessData => write!(f, "excess data"), Error::InputOutput(e) => write!(f, "I/O error: {e}"), Error::Handshake(e) => write!(f, "D-Bus handshake failed: {e}"), @@ -199,9 +199,9 @@ impl From for Error { } } -impl From for Error { - fn from(val: crate::address::Error) -> Self { - Error::Address(val.to_string()) +impl From for Error { + fn from(val: address::Error) -> Self { + Error::Address(val) } } From 2c48f1a4af89cb41c07965c998e2cbce4f842dea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 14 Oct 2024 12:30:59 +0400 Subject: [PATCH 07/13] =?UTF-8?q?=E2=9C=A8=20zb:=20add=20Transport::into?= =?UTF-8?q?=5Fowned()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- zbus/src/address/transport/autolaunch.rs | 20 ++++++++++++++++++++ zbus/src/address/transport/launchd.rs | 7 +++++++ zbus/src/address/transport/mod.rs | 18 ++++++++++++++++++ zbus/src/address/transport/nonce_tcp.rs | 19 +++++++++++++++++++ zbus/src/address/transport/systemd.rs | 9 +++++++++ zbus/src/address/transport/tcp.rs | 10 ++++++++++ zbus/src/address/transport/unix.rs | 17 +++++++++++++++++ zbus/src/address/transport/unixexec.rs | 13 +++++++++++++ zbus/src/address/transport/vsock.rs | 9 +++++++++ 9 files changed, 122 insertions(+) diff --git a/zbus/src/address/transport/autolaunch.rs b/zbus/src/address/transport/autolaunch.rs index 75ce71847..b5ede613e 100644 --- a/zbus/src/address/transport/autolaunch.rs +++ b/zbus/src/address/transport/autolaunch.rs @@ -22,6 +22,15 @@ impl<'a> Autolaunch<'a> { pub fn scope(&self) -> Option<&AutolaunchScope<'a>> { self.scope.as_ref() } + + /// Convert into owned version, with 'static lifetime. + pub fn into_owned(self) -> Autolaunch<'static> { + Autolaunch { + #[cfg(target_os = "windows")] + scope: self.scope.map(|s| s.into_owned()), + phantom: PhantomData, + } + } } impl<'a> TransportImpl<'a> for Autolaunch<'a> { @@ -62,6 +71,17 @@ pub enum AutolaunchScope<'a> { Other(Cow<'a, str>), } +#[cfg(target_os = "windows")] +impl<'a> AutolaunchScope<'a> { + fn into_owned(self) -> AutolaunchScope<'static> { + match self { + AutolaunchScope::InstallPath => AutolaunchScope::InstallPath, + AutolaunchScope::User => AutolaunchScope::User, + AutolaunchScope::Other(other) => AutolaunchScope::Other(other.into_owned().into()), + } + } +} + #[cfg(target_os = "windows")] impl fmt::Display for AutolaunchScope<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/zbus/src/address/transport/launchd.rs b/zbus/src/address/transport/launchd.rs index f3800b45f..f06e0f030 100644 --- a/zbus/src/address/transport/launchd.rs +++ b/zbus/src/address/transport/launchd.rs @@ -18,6 +18,13 @@ impl<'a> Launchd<'a> { pub fn env(&self) -> &str { self.env.as_ref() } + + /// Convert into owned version, with 'static lifetime. + pub fn into_owned(self) -> Launchd<'static> { + Launchd { + env: self.env.into_owned().into(), + } + } } impl<'a> TransportImpl<'a> for Launchd<'a> { diff --git a/zbus/src/address/transport/mod.rs b/zbus/src/address/transport/mod.rs index 3954eed40..f277b95ab 100644 --- a/zbus/src/address/transport/mod.rs +++ b/zbus/src/address/transport/mod.rs @@ -58,6 +58,24 @@ pub enum Transport<'a> { Vsock(vsock::Vsock<'a>), } +impl<'a> Transport<'a> { + /// Convert into owned version, with 'static lifetime. + pub fn into_owned(self) -> Transport<'static> { + match self { + Transport::Unix(unix) => Transport::Unix(unix.into_owned()), + #[cfg(target_os = "macos")] + Transport::Launchd(launchd) => Transport::Launchd(launchd.into_owned()), + #[cfg(target_os = "linux")] + Transport::Systemd(systemd) => Transport::Systemd(systemd.into_owned()), + Transport::Tcp(tcp) => Transport::Tcp(tcp.into_owned()), + Transport::NonceTcp(nonce_tcp) => Transport::NonceTcp(nonce_tcp.into_owned()), + Transport::Unixexec(unixexec) => Transport::Unixexec(unixexec.into_owned()), + Transport::Autolaunch(autolaunch) => Transport::Autolaunch(autolaunch.into_owned()), + Transport::Vsock(vsock) => Transport::Vsock(vsock.into_owned()), + } + } +} + impl fmt::Display for Transport<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { diff --git a/zbus/src/address/transport/nonce_tcp.rs b/zbus/src/address/transport/nonce_tcp.rs index 1b6485acb..0115db071 100644 --- a/zbus/src/address/transport/nonce_tcp.rs +++ b/zbus/src/address/transport/nonce_tcp.rs @@ -53,6 +53,25 @@ impl<'a> NonceTcp<'a> { pub fn noncefile(&self) -> Option<&OsStr> { self.noncefile.as_ref().map(|v| v.as_ref()) } + + /// Convert into owned version, with 'static lifetime. + pub fn into_owned(self) -> NonceTcp<'static> { + let Self { + host, + bind, + port, + family, + noncefile, + } = self; + + NonceTcp { + host: host.map(|h| h.into_owned().into()), + bind: bind.map(|b| b.into_owned().into()), + port, + family, + noncefile: noncefile.map(|n| n.into_owned().into()), + } + } } impl<'a> TransportImpl<'a> for NonceTcp<'a> { diff --git a/zbus/src/address/transport/systemd.rs b/zbus/src/address/transport/systemd.rs index bd3f2ff5c..15e52e504 100644 --- a/zbus/src/address/transport/systemd.rs +++ b/zbus/src/address/transport/systemd.rs @@ -11,6 +11,15 @@ pub struct Systemd<'a> { phantom: PhantomData<&'a ()>, } +impl<'a> Systemd<'a> { + /// Convert into owned version, with 'static lifetime. + pub fn into_owned(&self) -> Systemd<'static> { + Systemd { + phantom: PhantomData, + } + } +} + impl<'a> TransportImpl<'a> for Systemd<'a> { fn for_address(_addr: &'a Address<'a>) -> Result { Ok(Systemd { diff --git a/zbus/src/address/transport/tcp.rs b/zbus/src/address/transport/tcp.rs index ee287cd45..0181de25f 100644 --- a/zbus/src/address/transport/tcp.rs +++ b/zbus/src/address/transport/tcp.rs @@ -41,6 +41,16 @@ impl<'a> Tcp<'a> { pub fn family(&self) -> Option { self.family } + + /// Convert into owned version, with 'static lifetime. + pub fn into_owned(self) -> Tcp<'static> { + Tcp { + host: self.host.map(|h| h.into_owned().into()), + bind: self.bind.map(|b| b.into_owned().into()), + port: self.port, + family: self.family, + } + } } impl<'a> TransportImpl<'a> for Tcp<'a> { diff --git a/zbus/src/address/transport/unix.rs b/zbus/src/address/transport/unix.rs index f0a9f8b92..6b9c0588a 100644 --- a/zbus/src/address/transport/unix.rs +++ b/zbus/src/address/transport/unix.rs @@ -18,6 +18,13 @@ impl<'a> Unix<'a> { pub fn kind(&self) -> &UnixAddrKind<'a> { &self.kind } + + /// Convert into owned version, with 'static lifetime. + pub fn into_owned(self) -> Unix<'static> { + Unix { + kind: self.kind.into_owned(), + } + } } impl<'a> TransportImpl<'a> for Unix<'a> { @@ -111,4 +118,14 @@ impl UnixAddrKind<'_> { UnixAddrKind::Runtime => kv.add("runtime", Some("yes")), } } + + fn into_owned(self) -> UnixAddrKind<'static> { + match self { + UnixAddrKind::Path(cow) => UnixAddrKind::Path(cow.into_owned().into()), + UnixAddrKind::Dir(cow) => UnixAddrKind::Dir(cow.into_owned().into()), + UnixAddrKind::Tmpdir(cow) => UnixAddrKind::Tmpdir(cow.into_owned().into()), + UnixAddrKind::Abstract(cow) => UnixAddrKind::Abstract(cow.into_owned().into()), + UnixAddrKind::Runtime => UnixAddrKind::Runtime, + } + } } diff --git a/zbus/src/address/transport/unixexec.rs b/zbus/src/address/transport/unixexec.rs index 9501cfe49..15e0072bc 100644 --- a/zbus/src/address/transport/unixexec.rs +++ b/zbus/src/address/transport/unixexec.rs @@ -30,6 +30,19 @@ impl<'a> Unixexec<'a> { pub fn argv(&self) -> &[(usize, Cow<'a, str>)] { self.argv.as_ref() } + + /// Convert into owned version, with 'static lifetime. + pub fn into_owned(self) -> Unixexec<'static> { + let argv = self + .argv + .into_iter() + .map(|(index, cow)| (index, cow.into_owned().into())) + .collect(); + Unixexec { + path: self.path.into_owned().into(), + argv, + } + } } impl<'a> TransportImpl<'a> for Unixexec<'a> { diff --git a/zbus/src/address/transport/vsock.rs b/zbus/src/address/transport/vsock.rs index 289314e52..f5e7b6a4e 100644 --- a/zbus/src/address/transport/vsock.rs +++ b/zbus/src/address/transport/vsock.rs @@ -23,6 +23,15 @@ impl<'a> Vsock<'a> { pub fn cid(&self) -> Option { self.cid } + + /// Convert into owned version, with 'static lifetime. + pub fn into_owned(self) -> Vsock<'static> { + Vsock { + cid: self.cid, + port: self.port, + phantom: PhantomData, + } + } } impl<'a> TransportImpl<'a> for Vsock<'a> { From 9e52f8d4d2129761ef9cf45d70827ff5c71b2a34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 14 Oct 2024 12:35:28 +0400 Subject: [PATCH 08/13] =?UTF-8?q?=E2=9C=A8=20zb:=20implement=20Clone=20for?= =?UTF-8?q?=20Transport?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- zbus/src/address/transport/autolaunch.rs | 4 ++-- zbus/src/address/transport/launchd.rs | 2 +- zbus/src/address/transport/mod.rs | 2 +- zbus/src/address/transport/nonce_tcp.rs | 2 +- zbus/src/address/transport/systemd.rs | 2 +- zbus/src/address/transport/tcp.rs | 2 +- zbus/src/address/transport/unix.rs | 4 ++-- zbus/src/address/transport/unixexec.rs | 2 +- zbus/src/address/transport/vsock.rs | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/zbus/src/address/transport/autolaunch.rs b/zbus/src/address/transport/autolaunch.rs index b5ede613e..8573968db 100644 --- a/zbus/src/address/transport/autolaunch.rs +++ b/zbus/src/address/transport/autolaunch.rs @@ -9,7 +9,7 @@ use super::{Address, KeyValFmt, Result, TransportImpl}; /// `autolaunch:` D-Bus transport. /// /// -#[derive(Debug, PartialEq, Eq, Default)] +#[derive(Clone, Debug, PartialEq, Eq, Default)] pub struct Autolaunch<'a> { #[cfg(target_os = "windows")] scope: Option>, @@ -60,7 +60,7 @@ impl<'a> TransportImpl<'a> for Autolaunch<'a> { /// Scope of autolaunch (Windows only) #[cfg(target_os = "windows")] -#[derive(Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq)] #[non_exhaustive] pub enum AutolaunchScope<'a> { /// Limit session bus to dbus installation path. diff --git a/zbus/src/address/transport/launchd.rs b/zbus/src/address/transport/launchd.rs index f06e0f030..882aa58b0 100644 --- a/zbus/src/address/transport/launchd.rs +++ b/zbus/src/address/transport/launchd.rs @@ -5,7 +5,7 @@ use super::{percent::decode_percents_str, Address, Error, KeyValFmt, Result, Tra /// `launchd:` D-Bus transport. /// /// -#[derive(Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct Launchd<'a> { env: Cow<'a, str>, } diff --git a/zbus/src/address/transport/mod.rs b/zbus/src/address/transport/mod.rs index f277b95ab..6d1e4fe8d 100644 --- a/zbus/src/address/transport/mod.rs +++ b/zbus/src/address/transport/mod.rs @@ -35,7 +35,7 @@ mod vsock; pub use vsock::Vsock; /// A D-Bus transport. -#[derive(Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq)] #[non_exhaustive] pub enum Transport<'a> { /// Unix Domain Sockets transport. diff --git a/zbus/src/address/transport/nonce_tcp.rs b/zbus/src/address/transport/nonce_tcp.rs index 0115db071..78755d31b 100644 --- a/zbus/src/address/transport/nonce_tcp.rs +++ b/zbus/src/address/transport/nonce_tcp.rs @@ -9,7 +9,7 @@ use super::{ /// `nonce-tcp:` D-Bus transport. /// /// -#[derive(Debug, Default, PartialEq, Eq)] +#[derive(Clone, Debug, Default, PartialEq, Eq)] pub struct NonceTcp<'a> { host: Option>, bind: Option>, diff --git a/zbus/src/address/transport/systemd.rs b/zbus/src/address/transport/systemd.rs index 15e52e504..65b5f566c 100644 --- a/zbus/src/address/transport/systemd.rs +++ b/zbus/src/address/transport/systemd.rs @@ -5,7 +5,7 @@ use super::{Address, KeyValFmt, Result, TransportImpl}; /// `systemd:` D-Bus transport. /// /// -#[derive(Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct Systemd<'a> { // use a phantom lifetime for eventually future fields and consistency phantom: PhantomData<&'a ()>, diff --git a/zbus/src/address/transport/tcp.rs b/zbus/src/address/transport/tcp.rs index 0181de25f..203fa818f 100644 --- a/zbus/src/address/transport/tcp.rs +++ b/zbus/src/address/transport/tcp.rs @@ -5,7 +5,7 @@ use super::{percent::decode_percents_str, Address, Error, KeyValFmt, Result, Tra /// `tcp:` D-Bus transport. /// /// -#[derive(Debug, Default, PartialEq, Eq)] +#[derive(Clone, Debug, Default, PartialEq, Eq)] pub struct Tcp<'a> { host: Option>, bind: Option>, diff --git a/zbus/src/address/transport/unix.rs b/zbus/src/address/transport/unix.rs index 6b9c0588a..d8d0f2bf4 100644 --- a/zbus/src/address/transport/unix.rs +++ b/zbus/src/address/transport/unix.rs @@ -8,7 +8,7 @@ use super::{ /// `unix:` D-Bus transport. /// /// -#[derive(Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct Unix<'a> { kind: UnixAddrKind<'a>, } @@ -89,7 +89,7 @@ impl<'a> TransportImpl<'a> for Unix<'a> { } /// A sub-type of `unix:` transport. -#[derive(Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq)] #[non_exhaustive] pub enum UnixAddrKind<'a> { /// Path of the unix domain socket. diff --git a/zbus/src/address/transport/unixexec.rs b/zbus/src/address/transport/unixexec.rs index 15e0072bc..77576b35c 100644 --- a/zbus/src/address/transport/unixexec.rs +++ b/zbus/src/address/transport/unixexec.rs @@ -8,7 +8,7 @@ use super::{ /// `unixexec:` D-Bus transport. /// /// -#[derive(Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct Unixexec<'a> { path: Cow<'a, OsStr>, argv: Vec<(usize, Cow<'a, str>)>, diff --git a/zbus/src/address/transport/vsock.rs b/zbus/src/address/transport/vsock.rs index f5e7b6a4e..eb3b347e8 100644 --- a/zbus/src/address/transport/vsock.rs +++ b/zbus/src/address/transport/vsock.rs @@ -3,7 +3,7 @@ use std::marker::PhantomData; use super::{percent::decode_percents_str, Address, Error, KeyValFmt, Result, TransportImpl}; /// `vsock:` D-Bus transport. -#[derive(Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct Vsock<'a> { // no cid means ANY cid: Option, From 50993f9e9f82755e6ed1fccae0e2fb181451d9e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 14 Oct 2024 12:34:18 +0400 Subject: [PATCH 09/13] =?UTF-8?q?=E2=9C=A8=20zb:=20add=20OwnedAddress?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- zbus/src/address/mod.rs | 81 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 2 deletions(-) diff --git a/zbus/src/address/mod.rs b/zbus/src/address/mod.rs index b48dfab61..70605b734 100644 --- a/zbus/src/address/mod.rs +++ b/zbus/src/address/mod.rs @@ -120,7 +120,10 @@ pub fn system() -> Result> { } } -/// A bus address. +/// A parsed bus address. +/// +/// The fields of this structure are references to the source. Using an [`OwnedAddress`] may be more +/// convenient or if your context requires 'static lifetime. /// /// Example: /// ``` @@ -229,6 +232,65 @@ impl fmt::Display for Address<'_> { } } +/// An owned bus address. +/// +/// Example: +/// ``` +/// use zbus::address::OwnedAddress; +/// +/// let _: OwnedAddress = "unix:path=/tmp/dbus.sock".try_into().unwrap(); +/// ``` +#[derive(Debug, PartialEq, Eq, Clone)] +pub struct OwnedAddress { + transport: transport::Transport<'static>, + guid: Option, +} + +impl OwnedAddress { + /// The connection GUID if any. + pub fn guid(&self) -> Option<&str> { + self.guid.as_ref().map(|g| g.as_ref()) + } + + /// Transport connection details + pub fn transport(&self) -> &transport::Transport<'static> { + &self.transport + } + + fn new(addr: &str) -> Result { + let addr = Address { addr: addr.into() }; + let transport = addr.transport()?.into_owned(); + let guid = addr.guid().map(|c| c.into_owned()); + Ok(Self { transport, guid }) + } +} + +impl fmt::Display for OwnedAddress { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let kv = KeyValFmt::new().add("guid", self.guid.as_ref()); + let t = &self.transport; + let kv = t.fmt_key_val(kv); + write!(f, "{t}:{kv}")?; + Ok(()) + } +} + +impl TryFrom<&str> for OwnedAddress { + type Error = Error; + + fn try_from(addr: &str) -> Result { + Self::new(addr) + } +} + +impl TryFrom for OwnedAddress { + type Error = Error; + + fn try_from(addr: String) -> Result { + Self::new(&addr) + } +} + pub(super) struct KeyValIter<'a> { data: &'a str, next_index: usize, @@ -343,8 +405,23 @@ impl<'a> ToAddresses<'a> for String { impl<'a> ToAddresses<'a> for Vec>> { type Iter = std::iter::Cloned>>>; - /// Get an iterator over the D-Bus addresses. fn to_addresses(&'a self) -> Self::Iter { self.iter().cloned() } } + +/// A trait for objects which can be converted or resolved to one or more [`OwnedAddress`] values. +pub trait ToOwnedAddresses<'a> { + type Iter: Iterator>; + + /// Get an iterator over the D-Bus addresses. + fn to_owned_addresses(&'a self) -> Self::Iter; +} + +impl<'a> ToOwnedAddresses<'a> for str { + type Iter = std::iter::Once>; + + fn to_owned_addresses(&'a self) -> Self::Iter { + std::iter::once(self.try_into()) + } +} From 9953ac069702bdd2cbad1412fff68d0fa8f8733c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 14 Oct 2024 12:36:29 +0400 Subject: [PATCH 10/13] =?UTF-8?q?=E2=9C=A8=20zb:=20add=20OwnedAddressListI?= =?UTF-8?q?ter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- zbus/src/address/address_list.rs | 46 +++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/zbus/src/address/address_list.rs b/zbus/src/address/address_list.rs index 8d7d0f8f0..16659c1f2 100644 --- a/zbus/src/address/address_list.rs +++ b/zbus/src/address/address_list.rs @@ -1,6 +1,6 @@ use std::{borrow::Cow, fmt}; -use super::{Address, Error, Result, ToAddresses}; +use super::{Address, Error, OwnedAddress, Result, ToAddresses, ToOwnedAddresses}; /// A bus address list. /// @@ -79,3 +79,47 @@ impl fmt::Display for AddressList<'_> { write!(f, "{}", self.addr) } } + +/// An iterator of D-Bus addresses. +pub struct OwnedAddressListIter<'a> { + data: &'a str, + next_index: usize, +} + +impl<'a> ToOwnedAddresses<'a> for AddressList<'a> { + type Iter = OwnedAddressListIter<'a>; + + /// Get an iterator over the D-Bus addresses. + fn to_owned_addresses(&'a self) -> Self::Iter { + OwnedAddressListIter::new(self) + } +} + +impl<'a> OwnedAddressListIter<'a> { + fn new(list: &'a AddressList<'_>) -> Self { + Self { + data: list.addr.as_ref(), + next_index: 0, + } + } +} + +impl<'a> Iterator for OwnedAddressListIter<'a> { + type Item = Result; + + fn next(&mut self) -> Option { + if self.next_index >= self.data.len() { + return None; + } + + let mut addr = &self.data[self.next_index..]; + if let Some(end) = addr.find(';') { + addr = &addr[..end]; + self.next_index += end + 1; + } else { + self.next_index = self.data.len(); + } + + Some(OwnedAddress::try_from(addr)) + } +} From fe002de7d079b21b5422746072ef41f01e4d319d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 14 Oct 2024 13:05:12 +0400 Subject: [PATCH 11/13] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20=20zb:=20Builder::ad?= =?UTF-8?q?dress()=20to=20take=20ToOwnedAddress?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Because the builder doesn't hold a reference to the address source, it has to use an owned version. We can thus drop Address:to_owned(), and go directly to OwnedAddress version. --- zbus/src/address/mod.rs | 7 ------- zbus/src/blocking/connection/builder.rs | 4 ++-- zbus/src/connection/builder.rs | 11 +++++------ zbus/src/connection/connect/mod.rs | 23 +++++++++++------------ zbus/src/connection/connect/win32.rs | 6 +++--- 5 files changed, 21 insertions(+), 30 deletions(-) diff --git a/zbus/src/address/mod.rs b/zbus/src/address/mod.rs index 70605b734..fc2c05fe7 100644 --- a/zbus/src/address/mod.rs +++ b/zbus/src/address/mod.rs @@ -199,13 +199,6 @@ fn validate_guid(value: &[u8]) -> Result<()> { Ok(()) } -impl Address<'_> { - pub fn to_owned(&self) -> Address<'static> { - let addr = self.addr.to_string(); - Address { addr: addr.into() } - } -} - impl<'a> TryFrom for Address<'a> { type Error = Error; diff --git a/zbus/src/blocking/connection/builder.rs b/zbus/src/blocking/connection/builder.rs index 4efd47cbf..5bb2e3a9f 100644 --- a/zbus/src/blocking/connection/builder.rs +++ b/zbus/src/blocking/connection/builder.rs @@ -15,7 +15,7 @@ use zvariant::ObjectPath; #[cfg(feature = "p2p")] use crate::Guid; use crate::{ - address::ToAddresses, blocking::Connection, conn::AuthMechanism, + address::ToOwnedAddresses, blocking::Connection, conn::AuthMechanism, connection::socket::BoxedSplit, names::WellKnownName, object_server::Interface, utils::block_on, Error, Result, }; @@ -43,7 +43,7 @@ impl<'a> Builder<'a> { /// [D-Bus bus address]: https://dbus.freedesktop.org/doc/dbus-specification.html#addresses pub fn address<'t, A>(address: &'t A) -> Result where - A: ToAddresses<'t> + ?Sized, + A: ToOwnedAddresses<'t> + ?Sized, { crate::connection::Builder::address(address).map(Self) } diff --git a/zbus/src/connection/builder.rs b/zbus/src/connection/builder.rs index 78218efe8..1295e9d69 100644 --- a/zbus/src/connection/builder.rs +++ b/zbus/src/connection/builder.rs @@ -24,7 +24,7 @@ use vsock::VsockStream; use zvariant::ObjectPath; use crate::{ - address::{Address, ToAddresses}, + address::{OwnedAddress, ToOwnedAddresses}, names::{InterfaceName, WellKnownName}, object_server::{ArcInterface, Interface}, Connection, Error, Executor, Guid, OwnedGuid, Result, @@ -48,7 +48,7 @@ enum Target { feature = "tokio-vsock" ))] VsockStream(VsockStream), - Address(Vec>), + Address(Vec), Socket(Split, Box>), AuthenticatedSocket(Split, Box>), } @@ -119,12 +119,11 @@ impl<'a> Builder<'a> { /// [D-Bus bus address]: https://dbus.freedesktop.org/doc/dbus-specification.html#addresses pub fn address<'t, A>(address: &'t A) -> Result where - A: ToAddresses<'t> + ?Sized, + A: ToOwnedAddresses<'t> + ?Sized, { let addr = address - .to_addresses() + .to_owned_addresses() .filter_map(std::result::Result::ok) - .map(|a| a.to_owned()) .collect(); Ok(Builder::new(Target::Address(addr))) @@ -492,7 +491,7 @@ impl<'a> Builder<'a> { #[cfg(feature = "tokio-vsock")] Target::VsockStream(stream) => stream.into(), Target::Address(address) => { - return connect_address(&address) + return connect_address(address.as_slice()) .await .map(|(split, guid)| (split, guid, false)); } diff --git a/zbus/src/connection/connect/mod.rs b/zbus/src/connection/connect/mod.rs index 50f93ed70..3d0940c81 100644 --- a/zbus/src/connection/connect/mod.rs +++ b/zbus/src/connection/connect/mod.rs @@ -1,7 +1,7 @@ use tracing::debug; use crate::{ - address::{transport::Transport, Address}, + address::{transport::Transport, OwnedAddress}, Error, Guid, OwnedGuid, Result, }; @@ -11,7 +11,7 @@ mod macos; mod win32; pub(crate) async fn connect_address( - address: &[Address<'_>], + address: &[OwnedAddress], ) -> Result<(BoxedSplit, Option)> { for addr in address { match connect(addr).await { @@ -27,27 +27,26 @@ pub(crate) async fn connect_address( Err(Error::Failure("No connectable address".into())) } -async fn connect(addr: &Address<'_>) -> ConnectResult { - let addr = addr.to_owned(); +async fn connect(addr: &OwnedAddress) -> ConnectResult { let guid = match addr.guid() { - Some(g) => Some(Guid::try_from(g.as_ref())?.into()), + Some(g) => Some(Guid::try_from(g)?.into()), _ => None, }; - let split = match addr.transport()? { - Transport::Tcp(t) => socket::tcp::connect(&t).await?.into(), - Transport::NonceTcp(t) => socket::tcp::connect_nonce(&t).await?.into(), + let split = match addr.transport() { + Transport::Tcp(t) => socket::tcp::connect(t).await?.into(), + Transport::NonceTcp(t) => socket::tcp::connect_nonce(t).await?.into(), #[cfg(any(unix, not(feature = "tokio")))] - Transport::Unix(u) => socket::unix::connect(&u).await?.into(), + Transport::Unix(u) => socket::unix::connect(u).await?.into(), #[cfg(any( all(feature = "vsock", not(feature = "tokio")), feature = "tokio-vsock" ))] - Transport::Vsock(v) => socket::vsock::connect(&v).await?.into(), + Transport::Vsock(v) => socket::vsock::connect(v).await?.into(), #[cfg(target_os = "macos")] - Transport::Launchd(l) => macos::connect(&l).await?.into(), + Transport::Launchd(l) => macos::connect(l).await?.into(), #[cfg(target_os = "windows")] Transport::Autolaunch(l) => { - return win32::connect(&l).await; + return win32::connect(l).await; } _ => { tracing::debug!("Unsupported address: {addr}"); diff --git a/zbus/src/connection/connect/win32.rs b/zbus/src/connection/connect/win32.rs index 989b1b043..72096fc59 100644 --- a/zbus/src/connection/connect/win32.rs +++ b/zbus/src/connection/connect/win32.rs @@ -2,7 +2,7 @@ use super::ConnectResult; use crate::{ - address::{transport::Transport, Address}, + address::{transport::Transport, OwnedAddress}, win32::autolaunch_bus_address, Error, }; @@ -17,9 +17,9 @@ pub(crate) fn connect<'l>( return Err(Error::Unsupported); } - let addr: Address<'_> = autolaunch_bus_address()?.try_into()?; + let addr: OwnedAddress = autolaunch_bus_address()?.try_into()?; - if let Transport::Autolaunch(_) = addr.transport()? { + if let Transport::Autolaunch(_) = addr.transport() { return Err(Error::Failure("Recursive autolaunch: address".into())); } From e786f63cf3007200c24959d51edf0d3b8766ef80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 14 Oct 2024 15:02:08 +0400 Subject: [PATCH 12/13] =?UTF-8?q?=E2=9C=A8=20zb:=20add=20address:Guid?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This basic Guid type differs from zb::Guid, since it simply holds a parsed bytes value. --- zbus/src/address/guid.rs | 45 ++++++++++++++++++++++++++++++++++++++++ zbus/src/address/mod.rs | 3 +++ 2 files changed, 48 insertions(+) create mode 100644 zbus/src/address/guid.rs diff --git a/zbus/src/address/guid.rs b/zbus/src/address/guid.rs new file mode 100644 index 000000000..b4b73dbdb --- /dev/null +++ b/zbus/src/address/guid.rs @@ -0,0 +1,45 @@ +use std::fmt; + +use super::{Error, Result}; + +/// Universally-unique IDs for D-Bus addresses. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Guid([u8; 16]); + +impl Guid { + /// Create a Guid from the given bytes. + pub fn new(bytes: [u8; 16]) -> Self { + Guid(bytes) + } + + /// Returns a byte slice of this Guid’s contents + pub fn as_bytes(&self) -> &[u8; 16] { + &self.0 + } +} + +impl fmt::Display for Guid { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}", + self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5], self.0[6], self.0[7], + self.0[8], self.0[9], self.0[10], self.0[11], self.0[12], self.0[13], self.0[14], self.0[15]) + } +} + +impl TryFrom<&str> for Guid { + type Error = Error; + + fn try_from(s: &str) -> Result { + if s.len() != 32 { + return Err(Error::InvalidValue("guid".into())); + } + + let mut bytes = [0u8; 16]; + for (i, chunk) in s.as_bytes().chunks(2).enumerate() { + bytes[i] = u8::from_str_radix(std::str::from_utf8(chunk).unwrap(), 16) + .map_err(|_| Error::InvalidValue("guid".into()))?; + } + + Ok(Guid(bytes)) + } +} diff --git a/zbus/src/address/mod.rs b/zbus/src/address/mod.rs index fc2c05fe7..a8fe54f4e 100644 --- a/zbus/src/address/mod.rs +++ b/zbus/src/address/mod.rs @@ -35,6 +35,9 @@ mod percent; pub use percent::*; use transport::TransportImpl; +pub mod guid; +use guid::Guid; + #[cfg(test)] mod tests; From 1e7608df8226423b194e685578f92d086ed419e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 14 Oct 2024 15:06:52 +0400 Subject: [PATCH 13/13] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20=20zb:=20make=20guid?= =?UTF-8?q?()=20->=20Guid?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- zbus/src/address/mod.rs | 40 ++++++++++++++---------------- zbus/src/connection/connect/mod.rs | 7 ++---- zbus/src/guid.rs | 6 +++++ 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/zbus/src/address/mod.rs b/zbus/src/address/mod.rs index a8fe54f4e..a90f20629 100644 --- a/zbus/src/address/mod.rs +++ b/zbus/src/address/mod.rs @@ -141,8 +141,12 @@ pub struct Address<'a> { impl<'a> Address<'a> { /// The connection GUID if any. - pub fn guid(&self) -> Option> { - self.get_string("guid").and_then(|res| res.ok()) + pub fn guid(&self) -> Result> { + if let Some(guid) = self.get_string("guid") { + Ok(Some(guid?.as_ref().try_into()?)) + } else { + Ok(None) + } } /// Transport connection details @@ -170,12 +174,14 @@ impl<'a> Address<'a> { fn validate(&self) -> Result<()> { self.transport()?; for (k, v) in self.key_val_iter() { - let v = match v { - Some(v) => decode_percents(v)?, - _ => Cow::from(b"" as &[_]), - }; - if k == "guid" { - validate_guid(v.as_ref())?; + match (k, v) { + ("guid", Some(v)) => { + guid::Guid::try_from(decode_percents_str(v)?.as_ref())?; + } + (_, Some(v)) => { + decode_percents(v)?; + } + _ => {} } } @@ -194,14 +200,6 @@ impl<'a> Address<'a> { } } -fn validate_guid(value: &[u8]) -> Result<()> { - if value.len() != 32 || value.iter().any(|&c| !c.is_ascii_hexdigit()) { - return Err(Error::InvalidValue("guid".into())); - } - - Ok(()) -} - impl<'a> TryFrom for Address<'a> { type Error = Error; @@ -220,7 +218,7 @@ impl<'a> TryFrom<&'a str> for Address<'a> { impl fmt::Display for Address<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let kv = KeyValFmt::new().add("guid", self.guid()); + let kv = KeyValFmt::new().add("guid", self.guid().map_err(|_| fmt::Error)?); let t = self.transport().map_err(|_| fmt::Error)?; let kv = t.fmt_key_val(kv); write!(f, "{t}:{kv}")?; @@ -239,13 +237,13 @@ impl fmt::Display for Address<'_> { #[derive(Debug, PartialEq, Eq, Clone)] pub struct OwnedAddress { transport: transport::Transport<'static>, - guid: Option, + guid: Option, } impl OwnedAddress { /// The connection GUID if any. - pub fn guid(&self) -> Option<&str> { - self.guid.as_ref().map(|g| g.as_ref()) + pub fn guid(&self) -> Option<&Guid> { + self.guid.as_ref() } /// Transport connection details @@ -256,7 +254,7 @@ impl OwnedAddress { fn new(addr: &str) -> Result { let addr = Address { addr: addr.into() }; let transport = addr.transport()?.into_owned(); - let guid = addr.guid().map(|c| c.into_owned()); + let guid = addr.guid()?; Ok(Self { transport, guid }) } } diff --git a/zbus/src/connection/connect/mod.rs b/zbus/src/connection/connect/mod.rs index 3d0940c81..4ca9e8d0f 100644 --- a/zbus/src/connection/connect/mod.rs +++ b/zbus/src/connection/connect/mod.rs @@ -2,7 +2,7 @@ use tracing::debug; use crate::{ address::{transport::Transport, OwnedAddress}, - Error, Guid, OwnedGuid, Result, + Error, OwnedGuid, Result, }; use super::socket::{self, BoxedSplit}; @@ -28,10 +28,7 @@ pub(crate) async fn connect_address( } async fn connect(addr: &OwnedAddress) -> ConnectResult { - let guid = match addr.guid() { - Some(g) => Some(Guid::try_from(g)?.into()), - _ => None, - }; + let guid = addr.guid().map(OwnedGuid::from); let split = match addr.transport() { Transport::Tcp(t) => socket::tcp::connect(t).await?.into(), Transport::NonceTcp(t) => socket::tcp::connect_nonce(t).await?.into(), diff --git a/zbus/src/guid.rs b/zbus/src/guid.rs index 3e9ca5b2b..c0b9933c6 100644 --- a/zbus/src/guid.rs +++ b/zbus/src/guid.rs @@ -218,6 +218,12 @@ impl From for Str<'_> { } } +impl From<&crate::address::guid::Guid> for OwnedGuid { + fn from(value: &crate::address::guid::Guid) -> Self { + Guid(value.to_string().into()).into() + } +} + impl<'de> Deserialize<'de> for OwnedGuid { fn deserialize(deserializer: D) -> std::result::Result where