playit_agent_core/agent_control/
errors.rs1use std::{
2 error::Error,
3 fmt::{Display, Formatter},
4 future::Future,
5 net::SocketAddr,
6 panic::Location,
7 time::Duration,
8};
9
10use futures_util::TryFutureExt;
11use playit_api_client::{
12 api::{ApiError, ApiErrorNoFail, ApiResponseError},
13 http_client::HttpClientError,
14};
15
16#[derive(Debug)]
17pub enum SetupError {
18 IoError(std::io::Error),
19 FailedToConnect,
20 ApiFail(String),
21 ApiError(ApiResponseError),
22 RequestError(HttpClientError),
23 AttemptingToAuthWithOldFlow,
24 FailedToDecodeSignedAgentRegisterHex,
25 NoResponseFromAuthenticate,
26 RegisterInvalidSignature,
27 RegisterUnauthorized,
28 Timeout(TimeoutSource),
29}
30
31impl From<TimeoutSource> for SetupError {
32 fn from(value: TimeoutSource) -> Self {
33 SetupError::Timeout(value)
34 }
35}
36
37#[derive(Debug)]
38pub struct TimeoutSource {
39 pub file_name: &'static str,
40 pub line_no: u32,
41}
42
43impl TimeoutSource {
44 pub fn from_location(location: &'static Location<'static>) -> Self {
45 TimeoutSource {
46 file_name: location.file(),
47 line_no: location.line(),
48 }
49 }
50}
51
52pub trait TimeoutHelper {
53 type Data;
54
55 fn timeout(self, max: Duration) -> impl Future<Output = Result<Self::Data, SetupError>>;
56}
57
58pub trait TryTimeoutHelper {
59 type Success;
60 type Error;
61
62 fn try_timeout(self, max: Duration)
63 -> impl Future<Output = Result<Self::Success, Self::Error>>;
64}
65
66impl<F: Future> TimeoutHelper for F {
67 type Data = F::Output;
68
69 #[track_caller]
70 fn timeout(self, max: Duration) -> impl Future<Output = Result<Self::Data, SetupError>> {
71 tokio::time::timeout(max, self)
72 .map_err(|_| SetupError::Timeout(TimeoutSource::from_location(Location::caller())))
73 }
74}
75
76impl<R, E: From<TimeoutSource>, F: Future<Output = Result<R, E>>> TryTimeoutHelper for F {
77 type Success = R;
78 type Error = E;
79
80 #[track_caller]
81 fn try_timeout(
82 self,
83 max: Duration,
84 ) -> impl Future<Output = Result<Self::Success, Self::Error>> {
85 let fut = tokio::time::timeout(max, self)
86 .map_err(|_| E::from(TimeoutSource::from_location(Location::caller())));
87
88 async {
89 match fut.await {
90 Ok(Ok(res)) => Ok(res),
91 Err(err) | Ok(Err(err)) => Err(err),
92 }
93 }
94 }
95}
96
97impl<F: serde::Serialize> From<ApiError<F, HttpClientError>> for SetupError {
98 fn from(value: ApiError<F, HttpClientError>) -> Self {
99 match value {
100 ApiError::ApiError(api) => SetupError::ApiError(api),
101 ApiError::ClientError(error) => SetupError::RequestError(error),
102 ApiError::Fail(fail) => SetupError::ApiFail(serde_json::to_string(&fail).unwrap()),
103 }
104 }
105}
106
107impl From<ApiErrorNoFail<HttpClientError>> for SetupError {
108 fn from(value: ApiErrorNoFail<HttpClientError>) -> Self {
109 match value {
110 ApiErrorNoFail::ApiError(api) => SetupError::ApiError(api),
111 ApiErrorNoFail::ClientError(error) => SetupError::RequestError(error),
112 }
113 }
114}
115
116impl Display for SetupError {
117 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
118 write!(f, "{:?}", self)
119 }
120}
121
122impl Error for SetupError {}
123
124impl From<std::io::Error> for SetupError {
125 fn from(e: std::io::Error) -> Self {
126 SetupError::IoError(e)
127 }
128}
129
130#[derive(Debug)]
131pub enum ControlError {
132 IoError(std::io::Error),
133 InvalidRemote {
134 expected: SocketAddr,
135 got: SocketAddr,
136 },
137 FailedToReadControlFeed(std::io::Error),
138 Timeout(TimeoutSource),
139}
140
141impl From<std::io::Error> for ControlError {
142 fn from(e: std::io::Error) -> Self {
143 ControlError::IoError(e)
144 }
145}
146
147impl From<TimeoutSource> for ControlError {
148 fn from(value: TimeoutSource) -> Self {
149 ControlError::Timeout(value)
150 }
151}