1use std::convert::Infallible;
2
3use bytes::Bytes;
4use iri_string::types::UriStr;
5use tokio::sync::mpsc;
6
7use crate::{
8 capabilities::Requirements,
9 message::{
10 self,
11 rpc::{self, operation::Datastore},
12 },
13};
14
15#[derive(Debug, thiserror::Error)]
17pub enum Error {
18 #[cfg(feature = "ssh")]
20 #[error(transparent)]
22 SshTransport(#[from] russh::Error),
23
24 #[cfg(feature = "tls")]
25 #[error(transparent)]
27 TlsTransport(#[from] tokio_rustls::rustls::Error),
28
29 #[error("a transport error occurred: {0}")]
31 Transport(#[from] std::io::Error),
32
33 #[error("failed to enqueue a message")]
35 EnqueueMessage(#[from] mpsc::error::SendError<Bytes>),
36
37 #[error("failed to dequeue a message: send side is closed")]
39 DequeueMessage,
40
41 #[cfg(feature = "tls")]
42 #[error(transparent)]
44 InvalidDnsName(#[from] rustls_pki_types::InvalidDnsNameError),
45
46 #[error("authentication failed for user {username}")]
50 Authentication {
51 username: String,
53 },
54
55 #[error("failed to negotiate a common base protocol version")]
57 VersionNegotiation,
58
59 #[error("encountered a 'message-id' collision. please file a bug report!")]
63 MessageIdCollision {
64 message_id: rpc::MessageId,
66 },
67
68 #[error("request with message-id '{message_id:?}' not found")]
70 RequestNotFound {
71 message_id: rpc::MessageId,
73 },
74
75 #[error("attempted to poll for an already completed request")]
77 RequestComplete,
78
79 #[error(transparent)]
83 WriteMessage(#[from] message::WriteError),
84
85 #[error(transparent)]
89 ReadMessage(#[from] message::ReadError),
90
91 #[error("deleting the <running/> datastore is not permitted")]
95 DeleteRunningConfig,
96
97 #[error("invalid session-id: {session_id}")]
99 InvalidSessionId {
100 session_id: u32,
102 },
103
104 #[error("kill-session operation targeting the current session is not permitted")]
106 KillCurrentSession,
107
108 #[error("unsupported rpc operation '{operation_name}' (requires {required_capabilities})")]
110 UnsupportedOperation {
111 operation_name: &'static str,
113 required_capabilities: Requirements,
115 },
116
117 #[error("unsupported parameter '{param_name}' for rpc operation '{operation_name}' (requires {required_capabilities})")]
119 UnsupportedOperationParameter {
120 operation_name: &'static str,
122 param_name: &'static str,
124 required_capabilities: Requirements,
126 },
127
128 #[error("unsupported value '{param_value}' of parameter '{param_name}' for rpc operation '{operation_name}' (requires {required_capabilities})")]
130 UnsupportedOperParameterValue {
131 operation_name: &'static str,
133 param_name: &'static str,
135 param_value: &'static str,
137 required_capabilities: Requirements,
139 },
140
141 #[error("unsupported source datastore '{datastore:?}' (requires {required_capabilities})")]
143 UnsupportedSource {
144 datastore: Datastore,
146 required_capabilities: Requirements,
148 },
149
150 #[error("unsupported target datastore '{datastore:?}' (requires {required_capabilities})")]
152 UnsupportedTarget {
153 datastore: Datastore,
155 required_capabilities: Requirements,
157 },
158
159 #[error(
161 "unsupported lock target datastore '{datastore:?}' (requires {required_capabilities})"
162 )]
163 UnsupportedLockTarget {
164 datastore: Datastore,
166 required_capabilities: Requirements,
168 },
169
170 #[error("unsupported scheme in url '{url}' (requires ':url:1.0' capability with corresponding 'scheme' parameter)")]
172 UnsupportedUrlScheme {
173 url: Box<UriStr>,
175 },
176
177 #[error("unsupported filter type '{filter}' (requires {required_capabilities})")]
179 UnsupportedFilterType {
180 filter: &'static str,
182 required_capabilities: Requirements,
184 },
185
186 #[error("missing required parameter {param_name} for rpc operation {operation_name}")]
188 MissingOperationParameter {
189 operation_name: &'static str,
191 param_name: &'static str,
193 },
194
195 #[error("incompatible parameter combination for operation '{0}': {}", .parameters.join(", "))]
197 IncompatibleOperationParameters {
198 operation_name: &'static str,
200 parameters: Vec<&'static str>,
202 },
203
204 #[error("failed to parse URI")]
206 UrlParse(#[from] iri_string::validate::Error),
207
208 #[error("received rpc-error reply: {0}")]
212 RpcError(#[from] rpc::Errors),
213
214 #[error("unexpectedly empty rpc-reply")]
216 EmptyRpcReply,
217}
218
219impl Error {
220 pub(crate) const fn missing_operation_parameter(
221 operation_name: &'static str,
222 param_name: &'static str,
223 ) -> Self {
224 Self::MissingOperationParameter {
225 operation_name,
226 param_name,
227 }
228 }
229}
230
231impl From<Infallible> for Error {
232 fn from(_: Infallible) -> Self {
233 unreachable!()
234 }
235}