Nushell plugin for interacting with D-Bus
at main 107 lines 3.9 kB view raw
1use std::time::Duration; 2 3use nu_plugin::EvaluatedCall; 4use nu_protocol::{LabeledError, Span, Spanned}; 5 6/// General configuration related to the D-Bus client connection 7#[derive(Debug, Clone)] 8pub struct DbusClientConfig { 9 pub span: Span, 10 /// Which bus should we connect to? 11 pub bus_choice: Spanned<DbusBusChoice>, 12 /// How long to wait for a method call to return 13 pub timeout: Spanned<Duration>, 14 /// Enable introspection if signature unknown (default true) 15 pub introspect: bool, 16} 17 18/// Where to connect to the D-Bus server 19#[derive(Debug, Clone, Default)] 20pub enum DbusBusChoice { 21 /// Connect to the session bus 22 #[default] 23 Session, 24 /// Connect to the system bus 25 System, 26 /// Connect to the bus that started this process 27 Started, 28 /// Connect to a bus instance at the given address 29 Bus(String), 30 /// Connect to a non-bus D-Bus server at the given address (will not send Hello) 31 Peer(String), 32} 33 34impl TryFrom<&EvaluatedCall> for DbusClientConfig { 35 type Error = LabeledError; 36 37 fn try_from(call: &EvaluatedCall) -> Result<Self, Self::Error> { 38 let mut config = DbusClientConfig { 39 span: call.head, 40 bus_choice: Spanned { 41 item: DbusBusChoice::default(), 42 span: call.head, 43 }, 44 timeout: Spanned { 45 item: Duration::from_secs(2), 46 span: call.head, 47 }, 48 introspect: true, 49 }; 50 51 // Handle recognized config args 52 for (name, value) in &call.named { 53 match &name.item[..] { 54 r#type @ ("session" | "system" | "started") => { 55 if value.is_none() || value.as_ref().is_some_and(|v| v.is_true()) { 56 let dest = match r#type { 57 "session" => DbusBusChoice::Session, 58 "system" => DbusBusChoice::System, 59 "started" => DbusBusChoice::Started, 60 _ => unreachable!(), 61 }; 62 config.bus_choice = Spanned { 63 item: dest, 64 span: name.span, 65 }; 66 } 67 } 68 r#type @ ("bus" | "peer") => { 69 if let Some(value) = value { 70 let address = value.as_str()?; 71 let dest = match r#type { 72 "bus" => DbusBusChoice::Bus(address.to_owned()), 73 "peer" => DbusBusChoice::Peer(address.to_owned()), 74 _ => unreachable!(), 75 }; 76 config.bus_choice = Spanned { 77 item: dest, 78 span: value.span(), 79 }; 80 } 81 } 82 "timeout" => { 83 if let Some(value) = value { 84 let nanos: u64 = value.as_duration()?.try_into().map_err(|_| { 85 LabeledError::new("Timeout must be a positive duration") 86 .with_label("invalid timeout specified here", value.span()) 87 })?; 88 let item = Duration::from_nanos(nanos); 89 config.timeout = Spanned { 90 item, 91 span: value.span(), 92 }; 93 } 94 } 95 "no-introspect" => { 96 config.introspect = !value 97 .as_ref() 98 .and_then(|v| v.as_bool().ok()) 99 .unwrap_or(false); 100 } 101 _ => (), 102 } 103 } 104 105 Ok(config) 106 } 107}