Skip to content

Commit

Permalink
core, subscriber: more downcast_ref & is methods (#2160)
Browse files Browse the repository at this point in the history
Adds inherent `downcast_ref` and `is` inherent methods to:
  - `dyn Subscriber + Send`
  - `dyn Subscriber + Sync`
  - `dyn Subscriber + Send + Sync`
  - `Layered`

These additional implementations reduce the circumstances in which one
must cast to `dyn Subscriber` (which, previously, was the only type for
which `downcast_ref` and `is` were available).
  • Loading branch information
jswrenn authored and hawkw committed Jun 22, 2022
1 parent e793b0b commit 0d41b37
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 1 deletion.
60 changes: 60 additions & 0 deletions tracing-core/src/subscriber.rs
Expand Up @@ -484,6 +484,66 @@ impl dyn Subscriber {
}
}

impl dyn Subscriber + Send {
/// Returns `true` if this [`Subscriber`] is the same type as `T`.
pub fn is<T: Any>(&self) -> bool {
self.downcast_ref::<T>().is_some()
}

/// Returns some reference to this [`Subscriber`] value if it is of type `T`,
/// or `None` if it isn't.
pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
unsafe {
let raw = self.downcast_raw(TypeId::of::<T>())?;
if raw.is_null() {
None
} else {
Some(&*(raw as *const _))
}
}
}
}

impl dyn Subscriber + Sync {
/// Returns `true` if this [`Subscriber`] is the same type as `T`.
pub fn is<T: Any>(&self) -> bool {
self.downcast_ref::<T>().is_some()
}

/// Returns some reference to this `[`Subscriber`] value if it is of type `T`,
/// or `None` if it isn't.
pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
unsafe {
let raw = self.downcast_raw(TypeId::of::<T>())?;
if raw.is_null() {
None
} else {
Some(&*(raw as *const _))
}
}
}
}

impl dyn Subscriber + Send + Sync {
/// Returns `true` if this [`Subscriber`] is the same type as `T`.
pub fn is<T: Any>(&self) -> bool {
self.downcast_ref::<T>().is_some()
}

/// Returns some reference to this [`Subscriber`] value if it is of type `T`,
/// or `None` if it isn't.
pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
unsafe {
let raw = self.downcast_raw(TypeId::of::<T>())?;
if raw.is_null() {
None
} else {
Some(&*(raw as *const _))
}
}
}
}

/// Indicates a [`Subscriber`]'s interest in a particular callsite.
///
/// `Subscriber`s return an `Interest` from their [`register_callsite`] methods
Expand Down
30 changes: 29 additions & 1 deletion tracing-subscriber/src/layer/layered.rs
Expand Up @@ -12,7 +12,11 @@ use crate::{
};
#[cfg(all(feature = "registry", feature = "std"))]
use crate::{filter::FilterId, registry::Registry};
use core::{any::TypeId, cmp, fmt, marker::PhantomData};
use core::{
any::{Any, TypeId},
cmp, fmt,
marker::PhantomData,
};

/// A [`Subscriber`] composed of a `Subscriber` wrapped by one or more
/// [`Layer`]s.
Expand Down Expand Up @@ -63,6 +67,30 @@ pub struct Layered<L, I, S = I> {

// === impl Layered ===

impl<L, S> Layered<L, S>
where
L: Layer<S>,
S: Subscriber,
{
/// Returns `true` if this [`Subscriber`] is the same type as `T`.
pub fn is<T: Any>(&self) -> bool {
self.downcast_ref::<T>().is_some()
}

/// Returns some reference to this [`Subscriber`] value if it is of type `T`,
/// or `None` if it isn't.
pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
unsafe {
let raw = self.downcast_raw(TypeId::of::<T>())?;
if raw.is_null() {
None
} else {
Some(&*(raw as *const T))
}
}
}
}

impl<L, S> Subscriber for Layered<L, S>
where
L: Layer<S>,
Expand Down

0 comments on commit 0d41b37

Please sign in to comment.