Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions zbus/src/object_server/interface/interface_deref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ where
type Target = I;

fn deref(&self) -> &I {
self.iface.downcast_ref::<I>().unwrap()
let any_ref: &dyn std::any::Any = &*self.iface;
any_ref
.downcast_ref::<I>()
.expect("Unexpected interface type")
}
}

Expand All @@ -37,7 +40,10 @@ where
type Target = I;

fn deref(&self) -> &I {
self.iface.downcast_ref::<I>().unwrap()
let any_ref: &dyn std::any::Any = &*self.iface;
any_ref
.downcast_ref::<I>()
.expect("Unexpected interface type")
}
}

Expand All @@ -46,6 +52,9 @@ where
I: Interface,
{
fn deref_mut(&mut self) -> &mut Self::Target {
self.iface.downcast_mut::<I>().unwrap()
let any_ref: &mut dyn std::any::Any = &mut *self.iface;
any_ref
.downcast_mut::<I>()
.expect("Unexpected interface type")
}
}
13 changes: 1 addition & 12 deletions zbus/src/object_server/interface/interface_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@ where
pub async fn get(&self) -> InterfaceDeref<'_, I> {
let iface = self.lock.read().await;

iface
.downcast_ref::<I>()
.expect("Unexpected interface type");

InterfaceDeref {
iface,
phantom: PhantomData,
Expand Down Expand Up @@ -80,14 +76,7 @@ where
/// # Ok::<_, Box<dyn Error + Send + Sync>>(())
/// ```
pub async fn get_mut(&self) -> InterfaceDerefMut<'_, I> {
let mut iface = self.lock.write().await;

iface
.downcast_ref::<I>()
.expect("Unexpected interface type");
iface
.downcast_mut::<I>()
.expect("Unexpected interface type");
let iface = self.lock.write().await;

InterfaceDerefMut {
iface,
Expand Down
31 changes: 1 addition & 30 deletions zbus/src/object_server/interface/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ mod interface_deref;
pub use interface_deref::*;

use std::{
any::{Any, TypeId},
any::Any,
collections::HashMap,
fmt::{self, Write},
sync::Arc,
Expand Down Expand Up @@ -167,32 +167,3 @@ impl fmt::Debug for ArcInterface {
.finish_non_exhaustive()
}
}

// Note: while it is possible to implement this without `unsafe`, it currently requires a helper
// trait with a blanket impl that creates `dyn Any` refs. It's simpler (and more performant) to
// just check the type ID and do the downcast ourself.
//
// See https://github.com/rust-lang/rust/issues/65991 for a rustc feature that will make it
// possible to get a `dyn Any` ref directly from a `dyn Interface` ref; once that is stable, we can
// remove this unsafe code.
impl dyn Interface {
/// Return Any of self
pub(crate) fn downcast_ref<T: Any>(&self) -> Option<&T> {
if <dyn Interface as Any>::type_id(self) == TypeId::of::<T>() {
// SAFETY: If type ID matches, it means object is of type T
Some(unsafe { &*(self as *const dyn Interface as *const T) })
} else {
None
}
}

/// Return Any of self
pub(crate) fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
if <dyn Interface as Any>::type_id(self) == TypeId::of::<T>() {
// SAFETY: If type ID matches, it means object is of type T
Some(unsafe { &mut *(self as *mut dyn Interface as *mut T) })
} else {
None
}
}
}
12 changes: 6 additions & 6 deletions zbus/src/object_server/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! The object server API.

use std::{collections::HashMap, marker::PhantomData, sync::Arc};
use std::{any::Any, collections::HashMap, marker::PhantomData, sync::Arc};
use tracing::{Instrument, debug, instrument, trace, trace_span};

use zbus_names::InterfaceName;
Expand Down Expand Up @@ -274,11 +274,11 @@ impl ObjectServer {
.instance
.clone();

// Ensure what we return can later be dowcasted safely.
lock.read()
.await
.downcast_ref::<I>()
.ok_or(Error::InterfaceNotFound)?;
{
// Ensure what we return can later be downcasted safely.
let iface: &dyn Any = &*lock.read().await;
iface.downcast_ref::<I>().ok_or(Error::InterfaceNotFound)?;
}

let conn = self.connection();
// SAFETY: We know that there is a valid path on the node as we already converted w/o error.
Expand Down
Loading