diff --git a/src/address.rs b/src/address.rs
index 3699cd54..9435b1ab 100644
--- a/src/address.rs
+++ b/src/address.rs
@@ -1,7 +1,7 @@
//! An address to an actor is a way to send it a message. An address allows an actor to be sent any
//! kind of message that it can receive.
-use std::fmt::{self, Display, Formatter};
+use std::fmt::{self, Debug, Display, Formatter};
use std::future::Future;
use std::{cmp::Ordering, error::Error, hash::Hash};
@@ -44,6 +44,14 @@ pub struct Address {
pub(crate) ref_counter: Rc,
}
+impl Debug for Address {
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ f.debug_struct(&format!("Address<{}>", std::any::type_name::()))
+ .field("ref_counter", &self.ref_counter)
+ .finish()
+ }
+}
+
/// A `WeakAddress` is a reference to an actor through which [`Message`s](../trait.Message.html) can be
/// sent. It can be cloned. Unlike [`Address`](struct.Address.html), a `WeakAddress` will not inhibit
/// the dropping of an actor. It is created by the [`Address::downgrade`](struct.Address.html#method.downgrade)
diff --git a/src/message_channel.rs b/src/message_channel.rs
index 9d2ad186..8c962c8d 100644
--- a/src/message_channel.rs
+++ b/src/message_channel.rs
@@ -2,6 +2,8 @@
//! any actor that can handle it. It is like [`Address`](../address/struct.Address.html), but associated with
//! the message type rather than the actor type.
+use std::fmt::Debug;
+
use futures_core::future::BoxFuture;
use futures_core::stream::BoxStream;
@@ -77,10 +79,9 @@ use crate::{Handler, KeepRunning};
/// })
/// }
/// ```
-pub trait MessageChannel: Sealed + Unpin + Send + Sync {
+pub trait MessageChannel: Sealed + Unpin + Debug + Send + Sync {
/// The return value of the handler for `M`.
type Return: Send + 'static;
-
/// Returns whether the actor referred to by this address is running and accepting messages.
fn is_connected(&self) -> bool;
diff --git a/src/refcount.rs b/src/refcount.rs
index 0603191c..e883cf1e 100644
--- a/src/refcount.rs
+++ b/src/refcount.rs
@@ -1,10 +1,9 @@
-use crate::drop_notice;
-use crate::drop_notice::DropNotice;
+use crate::drop_notice::{self, DropNotice};
+use crate::private::Sealed;
+use std::fmt::{Debug, Formatter};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, RwLock, Weak as ArcWeak};
-use crate::private::Sealed;
-
/// The reference count of a strong address. Strong addresses will prevent the actor from being
/// dropped as long as they live. Read the docs of [`Address`](../address/struct.Address.html) to find
/// out more.
@@ -18,6 +17,16 @@ pub struct Strong {
lock: Arc>,
}
+impl Debug for Strong {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("Strong")
+ .field("connected", &self.is_connected())
+ .field("strong_count", &self.strong_count())
+ .field("weak_count", &self.weak_count())
+ .finish()
+ }
+}
+
#[doc(hidden)]
pub struct Shared {
connected: AtomicBool,
@@ -35,6 +44,10 @@ impl Strong {
}
}
+ fn weak_count(&self) -> usize {
+ Arc::weak_count(&self.shared)
+ }
+
pub(crate) fn downgrade(&self) -> Weak {
Weak {
shared: Arc::downgrade(&self.shared),
@@ -55,6 +68,16 @@ pub struct Weak {
lock: Arc>,
}
+impl Debug for Weak {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("Weak")
+ .field("connected", &self.is_connected())
+ .field("strong_count", &self.strong_count())
+ .field("weak_count", &self.weak_count())
+ .finish()
+ }
+}
+
impl Weak {
pub(crate) fn upgrade(&self) -> Option {
ArcWeak::upgrade(&self.shared).map(|shared| Strong {
@@ -62,10 +85,14 @@ impl Weak {
lock: self.lock.clone(),
})
}
+
+ fn weak_count(&self) -> usize {
+ ArcWeak::weak_count(&self.shared)
+ }
}
/// A reference counter that can be dynamically either strong or weak.
-#[derive(Clone)]
+#[derive(Clone, Debug)]
pub enum Either {
/// A strong reference counter.
Strong(Strong),
@@ -87,7 +114,7 @@ impl Either {
/// [`Strong`](struct.Weak.html). These can be provided as the second type argument to
/// [`Address`](../address/struct.Address.html) in order to change how the address affects the actor's
/// dropping. Read the docs of [`Address`](../address/struct.Address.html) to find out more.
-pub trait RefCounter: Sealed + Clone + Unpin + Send + Sync + 'static {
+pub trait RefCounter: Sealed + Clone + Unpin + Debug + Send + Sync + 'static {
#[doc(hidden)]
fn is_connected(&self) -> bool;
#[doc(hidden)]
diff --git a/tests/basic.rs b/tests/basic.rs
index 1ca3de08..09648048 100644
--- a/tests/basic.rs
+++ b/tests/basic.rs
@@ -273,3 +273,25 @@ async fn address_send_exercises_backpressure() {
.now_or_never()
.expect("be able to queue another message because the mailbox is empty again");
}
+
+#[test]
+fn address_debug() {
+ let (addr1, _ctx) = Context::::new(None);
+
+ let addr2 = addr1.clone();
+ let weak_addr = addr2.downgrade();
+
+ assert_eq!(
+ format!("{:?}", addr1),
+ "Address { \
+ ref_counter: Strong { connected: true, strong_count: 2, weak_count: 2 } }"
+ );
+
+ assert_eq!(format!("{:?}", addr1), format!("{:?}", addr2));
+
+ assert_eq!(
+ format!("{:?}", weak_addr),
+ "Address { \
+ ref_counter: Weak { connected: true, strong_count: 2, weak_count: 2 } }"
+ );
+}