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}