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
177impl core::fmt::Display for ErrorKind {
178 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
179 match self {
180 Self::ActorGone => write!(f, "expected actor is unreachable"),
181 Self::ReplyErr => write!(f, "actor replied with an error"),
182 Self::MailboxFull => write!(f, "actor's mailbox was full"),
183 Self::Timeout => write!(f, "operation timed out"),
184 Self::UnsupportedInTunMode => {
185 write!(f, "netstack operation unsupported in TUN transport mode")
186 }
187 Self::TunUnavailable => write!(f, "TUN transport unavailable"),
188 }
189 }
190}
191
192impl<M, E> From<SendError<M, E>> for ErrorKind {
193 fn from(err: SendError<M, E>) -> Self {
194 match err {
195 SendError::ActorNotRunning(_) | SendError::ActorStopped => ErrorKind::ActorGone,
196 SendError::HandlerError(_) => ErrorKind::ReplyErr,
197 SendError::MailboxFull(..) => ErrorKind::MailboxFull,
198 SendError::Timeout(_) => ErrorKind::Timeout,
199 }
200 }
201}