1use core::fmt::{Formatter, Write};
2
3use kameo::{
4 Actor,
5 actor::{ActorRef, WeakActorRef},
6 error::SendError,
7};
8
9pub(crate) trait ResultExt {
10 type T;
11
12 fn with_actor_info(self, aref: impl Into<ActorInfo>) -> Result<Self::T, Error>;
14}
15
16impl<T, E> ResultExt for Result<T, E>
17where
18 E: Into<Error>,
19{
20 type T = T;
21
22 fn with_actor_info(self, aref: impl Into<ActorInfo>) -> Result<T, Error> {
23 self.map_err(|e| e.into().with_actor_info(aref))
24 }
25}
26
27#[derive(Debug, Copy, Clone, PartialEq, Eq)]
29pub struct Error {
30 pub kind: ErrorKind,
32
33 pub message_ty: Option<&'static str>,
37
38 pub target_actor: Option<ActorInfo>,
43}
44
45impl Error {
46 pub fn with_actor_info(self, aref: impl Into<ActorInfo>) -> Self {
50 Self {
51 target_actor: Some(aref.into()),
52 ..self
53 }
54 }
55}
56
57impl core::fmt::Display for Error {
58 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
59 if let Some(ty) = self.message_ty {
63 write!(f, "sending {ty}")?;
64
65 if self.target_actor.is_some() {
66 f.write_char(' ')?;
67 }
68 }
69
70 if let Some(actor) = &self.target_actor {
71 write!(f, "{actor}")?;
72 }
73
74 if self.message_ty.is_some() || self.target_actor.is_some() {
75 f.write_str(": ")?;
76 }
77
78 self.kind.fmt(f)
79 }
80}
81
82impl core::error::Error for Error {}
83
84impl<M, E> From<SendError<M, E>> for Error {
85 fn from(err: SendError<M, E>) -> Self {
86 Self {
87 kind: err.into(),
88 message_ty: Some(core::any::type_name::<M>()),
89 target_actor: None,
90 }
91 }
92}
93
94#[derive(Debug, Copy, Clone, PartialEq, Eq)]
96pub struct ActorInfo {
97 pub ty: &'static str,
99
100 pub id: kameo::actor::ActorId,
102}
103
104impl<A> From<&ActorRef<A>> for ActorInfo
105where
106 A: Actor,
107{
108 fn from(aref: &ActorRef<A>) -> Self {
109 Self {
110 ty: core::any::type_name::<A>(),
111 id: aref.id(),
112 }
113 }
114}
115
116impl<A> From<ActorRef<A>> for ActorInfo
117where
118 A: Actor,
119{
120 fn from(aref: ActorRef<A>) -> Self {
121 Self::from(&aref)
122 }
123}
124
125impl<A> From<&WeakActorRef<A>> for ActorInfo
126where
127 A: Actor,
128{
129 fn from(aref: &WeakActorRef<A>) -> Self {
130 Self {
131 ty: core::any::type_name::<A>(),
132 id: aref.id(),
133 }
134 }
135}
136
137impl<A> From<WeakActorRef<A>> for ActorInfo
138where
139 A: Actor,
140{
141 fn from(aref: WeakActorRef<A>) -> Self {
142 Self::from(&aref)
143 }
144}
145
146impl core::fmt::Display for ActorInfo {
147 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
148 write!(f, "{}({})", self.ty, self.id)
149 }
150}
151
152#[derive(Debug, Copy, Clone, PartialEq, Eq)]
154pub enum ErrorKind {
155 ActorGone,
158
159 ReplyErr,
161
162 MailboxFull,
164
165 Timeout,
167
168 UnsupportedInTunMode,
171
172 TunUnavailable,
175
176 NetworkMonitorUnavailable,
181}
182
183impl core::fmt::Display for ErrorKind {
184 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
185 match self {
186 Self::ActorGone => write!(f, "expected actor is unreachable"),
187 Self::ReplyErr => write!(f, "actor replied with an error"),
188 Self::MailboxFull => write!(f, "actor's mailbox was full"),
189 Self::Timeout => write!(f, "operation timed out"),
190 Self::UnsupportedInTunMode => {
191 write!(f, "netstack operation unsupported in TUN transport mode")
192 }
193 Self::TunUnavailable => write!(f, "TUN transport unavailable"),
194 Self::NetworkMonitorUnavailable => write!(
195 f,
196 "network monitor requested but the `network-monitor` feature is not enabled"
197 ),
198 }
199 }
200}
201
202impl<M, E> From<SendError<M, E>> for ErrorKind {
203 fn from(err: SendError<M, E>) -> Self {
204 match err {
205 SendError::ActorNotRunning(_) | SendError::ActorStopped => ErrorKind::ActorGone,
206 SendError::HandlerError(_) => ErrorKind::ReplyErr,
207 SendError::MailboxFull(..) => ErrorKind::MailboxFull,
208 SendError::Timeout(_) => ErrorKind::Timeout,
209 }
210 }
211}