usesuper::{Connection, Message, MessageItem, Error, TypeSig}; use std::collections::BTreeMap; use std::rc::Rc; use std::cell::{Cell, RefCell}; use std::borrow::Cow;
/// a Method has a list of Arguments. pubstruct Argument<'a> {
name: &'a str,
sig: TypeSig<'a>,
}
/// Declares that an Interface can send this signal pubstruct Signal<'a> {
name: String,
i: ISignal<'a>,
}
impl<'a> Signal<'a> { /// Create a new Signal. pubfn new<N: ToString>(name: N, args: Vec<Argument<'a>>) -> Signal<'a> {
Signal { name: name.to_string(), i: ISignal { args: args, anns: vec![] } }
}
/// Add an Annotation to the Signal. pubfn annotate<N: ToString, V: ToString>(&mutself, name: N, value: V) { self.i.anns.push(Annotation { name: name.to_string(), value: value.to_string() });
}
}
/// A method returns either a list of MessageItems, or an error - the tuple /// represents the name and message of the Error. pubtype MethodResult = Result<Vec<MessageItem>, (&'static str, String)>; /// Contains the retrieved MessageItem or an error tuple containing the /// name and message of the error. pubtype PropertyGetResult = Result<MessageItem, (&'static str, String)>; /// Contains () or an error tuple containing the name and message of /// the error. pubtype PropertySetResult = Result<(), (&'static str, String)>;
/// A boxed closure for dynamic dispatch. It is called when the method is /// called by a remote application. pubtype MethodHandler<'a> = Box<FnMut(&mut Message) -> MethodResult + 'a>;
/// Add an Annotation to the Method. pubfn annotate<N: ToString, V: ToString>(&mutself, name: N, value: V) { self.i.anns.push(Annotation { name: name.to_string(), value: value.to_string() });
}
}
/// A read/write property handler. pubtrait PropertyRWHandler { /// Get a property's value. fn get(&self) -> PropertyGetResult; /// Set a property's value. fn set(&self, &MessageItem) -> PropertySetResult;
}
/// A read-only property handler. pubtrait PropertyROHandler { /// Get a property's value. fn get(&self) -> PropertyGetResult;
}
/// A write-only property handler. pubtrait PropertyWOHandler { /// Set a property's value. fn set(&self, &MessageItem) -> PropertySetResult;
}
/// Types of access to a Property. pubenum PropertyAccess<'a> {
RO(Box<PropertyROHandler+'a>),
RW(Box<PropertyRWHandler+'a>),
WO(Box<PropertyWOHandler+'a>),
}
/// Represents a D-Bus object path, which can in turn contain Interfaces. pubstruct ObjectPath<'a> { // We need extra references for the introspector and property handlers, hence this extra boxing
i: Rc<IObjectPath<'a>>,
}
impl<'a> Drop for ObjectPath<'a> { fn drop(&mutself) { let _ = self.i.set_registered(false); self.i.interfaces.borrow_mut().clear(); // This should remove all the other references to i
}
}
fn property_get(&self, msg: &mut Message) -> MethodResult { let items = msg.get_items(); let iface_name = try!(parse_msg_str(items.get(0))); let prop_name = try!(parse_msg_str(items.get(1)));
let is = self.interfaces.borrow(); let i = try!(is.get(iface_name).ok_or_else(||
("org.freedesktop.DBus.Error.UnknownInterface", format!("Unknown interface {}", iface_name)))); let p = try!(i.properties.get(prop_name).ok_or_else(||
("org.freedesktop.DBus.Error.UnknownProperty", format!("Unknown property {}", prop_name)))); let v = try!(match p.access {
PropertyAccess::RO(ref cb) => cb.get(),
PropertyAccess::RW(ref cb) => cb.get(),
PropertyAccess::WO(_) => { return Err(("org.freedesktop.DBus.Error.Failed", format!("Property {} is write only", prop_name)))
}
});
Ok(vec!(MessageItem::Variant(Box::new(v))))
}
fn property_getall(&self, msg: &mut Message) -> MethodResult { let items = msg.get_items(); let iface_name = try!(parse_msg_str(items.get(0)));
let is = self.interfaces.borrow(); let i = try!(is.get(iface_name).ok_or_else(||
("org.freedesktop.DBus.Error.UnknownInterface", format!("Unknown interface {}", iface_name)))); letmut result = Vec::new();
result.push(try!(MessageItem::from_dict(i.properties.iter().filter_map(|(pname, pv)| { let v = match pv.access {
PropertyAccess::RO(ref cb) => cb.get(),
PropertyAccess::RW(ref cb) => cb.get(),
PropertyAccess::WO(_) => { return None }
};
Some(v.map(|vv| (pname.clone(),vv)))
}))));
Ok(result)
}
fn property_set(&self, msg: &mut Message) -> MethodResult { let items = msg.get_items(); let iface_name = try!(parse_msg_str(items.get(0))); let prop_name = try!(parse_msg_str(items.get(1))); let value = try!(parse_msg_variant(items.get(2)));
let is = self.interfaces.borrow(); let i = try!(is.get(iface_name).ok_or_else(||
("org.freedesktop.DBus.Error.UnknownInterface", format!("Unknown interface {}", iface_name)))); let p = try!(i.properties.get(prop_name).ok_or_else(||
("org.freedesktop.DBus.Error.UnknownProperty", format!("Unknown property {}", prop_name)))); try!(match p.access {
PropertyAccess::WO(ref cb) => cb.set(value),
PropertyAccess::RW(ref cb) => cb.set(value),
PropertyAccess::RO(_) => { return Err(("org.freedesktop.DBus.Error.PropertyReadOnly", format!("Property {} is read only", prop_name)))
}
});
Ok(vec!())
}
}
/// Add an Interface to this ObjectPath. pubfn insert_interface<N: ToString>(&mutself, name: N, i: Interface<'a>) { if !i.properties.is_empty() { self.add_property_handler();
} self.i.interfaces.borrow_mut().insert(name.to_string(), i);
}
/// Returns if the ObjectPath is registered. pubfn is_registered(&self) -> bool { self.i.registered.get()
}
/// Changes the registration status of the ObjectPath. pubfn set_registered(&mutself, register: bool) -> Result<(), Error> { self.i.set_registered(register)
}
/// Handles a method call if the object path matches. /// Return value: None => not handled (no match), /// Some(Err(())) => message reply send failed, /// Some(Ok()) => message reply send ok */ pubfn handle_message(&mutself, msg: &mut Message) -> Option<Result<(), ()>> { let (_, path, iface, method) = msg.headers(); if path.is_none() || path.unwrap() != self.i.path { return None; } if iface.is_none() { return None; }
let method = { // This is because we don't want to hold the refcell lock when we call the // callback - maximum flexibility for clients. iflet Some(i) = self.i.interfaces.borrow().get(&iface.unwrap()) { iflet Some(Some(m)) = method.map(|m| i.methods.get(&m)) {
m.cb.clone()
} else { return Some(self.i.conn.send(Message::new_error(
msg, "org.freedesktop.DBus.Error.UnknownMethod", "Unknown method").unwrap()).map(|_| ()));
}
} else { return Some(self.i.conn.send(Message::new_error(msg, "org.freedesktop.DBus.Error.UnknownInterface", "Unknown interface").unwrap()).map(|_| ()));
}
};
let r = { // Now call it letmut m = method.borrow_mut();
(&mut **m)(msg)
};
let reply = match r {
Ok(r) => { letmut z = Message::new_method_return(msg).unwrap();
z.append_items(&r);
z
},
Err((aa,bb)) => Message::new_error(msg, aa, &bb).unwrap(),
};
#[test] fn test_objpath() { let c = Connection::get_private(super::BusType::Session).unwrap(); letmut o = make_objpath(&c);
o.set_registered(true).unwrap(); let busname = format!("com.example.objpath.test.test_objpath");
assert_eq!(c.register_name(&busname, super::NameFlag::ReplaceExisting as u32).unwrap(), super::RequestNameReply::PrimaryOwner);
let thread = ::std::thread::spawn(move || { let c = Connection::get_private(super::BusType::Session).unwrap(); let pr = super::Props::new(&c, &*busname, "/echo", "com.example.echo", 5000);
assert_eq!(pr.get("EchoCount").unwrap(), 7i32.into()); let m = pr.get_all().unwrap();
assert_eq!(m.get("EchoCount").unwrap(), &7i32.into());
});
letmut i = 0; for n in c.iter(1000) {
println!("objpath msg {:?}", n); ifletsuper::ConnectionItem::MethodCall(mut m) = n { iflet Some(msg) = o.handle_message(&mut m) {
msg.unwrap();
i += 1; if i >= 2 { break };
}
}
}
thread.join().unwrap();
}
/// Currently commented out because it requires feature(alloc) /* #[test] fntest_refcount(){ letc=Connection::get_private(super::BusType::Session).unwrap(); leti={ leto=make_objpath(&c); o.i.clone() }; assert!(::std::rc::is_unique(&i)); }
*/
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.23Bemerkung:
(vorverarbeitet am 2026-06-18)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.