zbus/address/transport/
ibus.rs

1use crate::{Address, Result, process::run};
2
3#[derive(Clone, Debug, PartialEq, Eq)]
4/// The transport properties of an IBus D-Bus address.
5///
6/// This transport type queries the IBus daemon for its D-Bus address using the `ibus address`
7/// command. IBus (Intelligent Input Bus) is an input method framework used primarily on Linux
8/// systems for entering text in various languages.
9///
10/// # Platform Support
11///
12/// This transport is available on Unix-like systems where IBus is installed.
13///
14/// # Example
15///
16/// ```no_run
17/// # use zbus::address::transport::{Transport, Ibus};
18/// # use zbus::Address;
19/// #
20/// // Create an IBus transport
21/// let ibus = Ibus::new();
22/// let _addr = Transport::Ibus(ibus);
23///
24/// // Or use it directly as an address
25/// let _addr = Address::from(Transport::Ibus(Ibus::new()));
26/// ```
27pub struct Ibus;
28
29impl Ibus {
30    /// Create a new IBus transport.
31    ///
32    /// This will query the IBus daemon for its D-Bus address when the connection is established.
33    #[must_use]
34    pub fn new() -> Self {
35        Self
36    }
37
38    /// Determine the actual transport details behind an IBus address.
39    ///
40    /// This method executes the `ibus address` command to retrieve the D-Bus address from the
41    /// running IBus daemon, then parses and returns the underlying transport.
42    ///
43    /// # Errors
44    ///
45    /// Returns an error if:
46    /// - The `ibus` command is not found or fails to execute
47    /// - The IBus daemon is not running
48    /// - The command output cannot be parsed as a valid D-Bus address
49    /// - The command output is not valid UTF-8
50    ///
51    /// # Example
52    ///
53    /// ```no_run
54    /// # use zbus::connection::Builder;
55    /// # use zbus::block_on;
56    /// #
57    /// # block_on(async {
58    /// // This method is used internally by the connection builder
59    /// let _conn = Builder::ibus()?.build().await?;
60    /// # Ok::<(), zbus::Error>(())
61    /// # }).unwrap();
62    /// ```
63    pub(super) async fn bus_address(&self) -> Result<Address> {
64        let output = run("ibus", ["address"])
65            .await
66            .map_err(|e| crate::Error::Address(format!("Failed to execute ibus command: {e}")))?;
67
68        if !output.status.success() {
69            return Err(crate::Error::Address(format!(
70                "ibus terminated with code: {}",
71                output.status
72            )));
73        }
74
75        let addr = String::from_utf8(output.stdout).map_err(|e| {
76            crate::Error::Address(format!("Unable to parse ibus output as UTF-8: {e}"))
77        })?;
78
79        addr.trim().parse()
80    }
81
82    /// Parse IBus transport from D-Bus address options.
83    ///
84    /// The IBus transport type does not require any options, so this method will succeed
85    /// as long as the transport type is specified as "ibus".
86    ///
87    /// # Errors
88    ///
89    /// This method does not return errors for the IBus transport, but the signature is kept
90    /// consistent with other transport types.
91    pub(super) fn from_options(_opts: std::collections::HashMap<&str, &str>) -> Result<Self> {
92        Ok(Self)
93    }
94}
95
96impl Default for Ibus {
97    fn default() -> Self {
98        Self::new()
99    }
100}
101
102impl std::fmt::Display for Ibus {
103    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104        write!(f, "ibus:")
105    }
106}
107
108#[cfg(test)]
109mod tests {
110    use super::*;
111
112    #[test]
113    fn test_ibus_new() {
114        let ibus = Ibus::new();
115        assert_eq!(ibus.to_string(), "ibus:");
116    }
117
118    #[test]
119    fn test_ibus_default() {
120        let ibus = Ibus::default();
121        assert_eq!(ibus.to_string(), "ibus:");
122    }
123
124    #[test]
125    fn test_ibus_from_options() {
126        let options = std::collections::HashMap::new();
127        let ibus = Ibus::from_options(options).unwrap();
128        assert_eq!(ibus, Ibus::new());
129    }
130
131    #[test]
132    fn test_ibus_display() {
133        let ibus = Ibus::new();
134        assert_eq!(format!("{}", ibus), "ibus:");
135    }
136}