1use thiserror::Error;
4
5use super::peer_types::Address;
6use crate::{auth::Permission, entry::ID};
7
8#[derive(Debug, Error)]
10#[non_exhaustive]
11pub enum SyncError {
12 #[error("No transport enabled. Call enable_http_transport() first")]
14 NoTransportEnabled,
15
16 #[error("Sync is not enabled on this Instance. Call Instance::enable_sync() first")]
18 SyncNotEnabled,
19
20 #[error("Server already running on {address}")]
22 ServerAlreadyRunning { address: String },
23
24 #[error("Server not running")]
26 ServerNotRunning,
27
28 #[error("Unexpected response type: expected {expected}, got {actual}")]
30 UnexpectedResponse {
31 expected: &'static str,
32 actual: String,
33 },
34
35 #[error("Network error: {0}")]
37 Network(String),
38
39 #[error("Failed to send command to background sync: {0}")]
41 CommandSendError(String),
42
43 #[error("Failed to initialize transport: {0}")]
45 TransportInit(String),
46
47 #[error("Failed to create async runtime: {0}")]
49 RuntimeCreation(String),
50
51 #[error("Failed to bind server to {address}: {reason}")]
53 ServerBind { address: String, reason: String },
54
55 #[error("Failed to connect to {address}: {reason}")]
57 ConnectionFailed { address: String, reason: String },
58
59 #[error("Device key '{key_name}' not found in backend storage")]
61 DeviceKeyNotFound { key_name: String },
62
63 #[error("Transport type '{transport_type}' not supported")]
65 UnsupportedTransport { transport_type: String },
66
67 #[error("Invalid address: {0}")]
69 InvalidAddress(String),
70
71 #[error("Peer not found: {0}")]
73 PeerNotFound(String),
74
75 #[error("Peer already exists: {0}")]
77 PeerAlreadyExists(String),
78
79 #[error("Serialization error: {0}")]
81 SerializationError(String),
82
83 #[error("Protocol version mismatch: expected {expected}, received {received}")]
85 ProtocolMismatch { expected: u32, received: u32 },
86
87 #[error("Handshake failed: {0}")]
89 HandshakeFailed(String),
90
91 #[error("Entry not found: {0}")]
93 EntryNotFound(ID),
94
95 #[error("Invalid entry: {0}")]
97 InvalidEntry(String),
98
99 #[error("Sync protocol error: {0}")]
101 SyncProtocolError(String),
102
103 #[error("Backend error: {0}")]
105 BackendError(String),
106
107 #[error("Bootstrap request not found: {0}")]
109 RequestNotFound(String),
110
111 #[error("Bootstrap request already exists: {0}")]
113 RequestAlreadyExists(String),
114
115 #[error(
117 "Invalid request state for '{request_id}': expected {expected_status}, found {current_status}"
118 )]
119 InvalidRequestState {
120 request_id: String,
121 current_status: String,
122 expected_status: String,
123 },
124
125 #[error("Invalid data: {0}")]
127 InvalidData(String),
128
129 #[error(
131 "Insufficient permission for request '{request_id}': required {required_permission}, but key has {actual_permission:?}"
132 )]
133 InsufficientPermission {
134 request_id: String,
135 required_permission: String,
136 actual_permission: Permission,
137 },
138
139 #[error("Invalid public key: {reason}")]
141 InvalidPublicKey { reason: String },
142
143 #[error("Invalid key name: {reason}")]
145 InvalidKeyName { reason: String },
146
147 #[error("Instance has been dropped")]
149 InstanceDropped,
150
151 #[error("Bootstrap request pending approval (request_id: {request_id}): {message}")]
153 BootstrapPending { request_id: String, message: String },
154
155 #[error("Transport config type mismatch for '{name}': expected '{expected}', found '{found}'")]
157 TransportTypeMismatch {
158 name: String,
159 expected: String,
160 found: String,
161 },
162
163 #[error("Transport not found: {name}")]
165 TransportNotFound { name: String },
166
167 #[error("No transport can handle address: {address:?}")]
169 NoTransportForAddress { address: Address },
170
171 #[error("Multiple transport errors: {}", errors.join(", "))]
173 MultipleTransportErrors { errors: Vec<String> },
174}
175
176impl SyncError {
177 pub fn is_configuration_error(&self) -> bool {
180 matches!(
181 self,
182 SyncError::NoTransportEnabled | SyncError::SyncNotEnabled
183 )
184 }
185
186 pub fn is_server_error(&self) -> bool {
188 matches!(
189 self,
190 SyncError::ServerAlreadyRunning { .. }
191 | SyncError::ServerNotRunning
192 | SyncError::ServerBind { .. }
193 )
194 }
195
196 pub fn is_network_error(&self) -> bool {
198 matches!(
199 self,
200 SyncError::Network(_) | SyncError::ConnectionFailed { .. }
201 )
202 }
203
204 pub fn is_protocol_error(&self) -> bool {
206 matches!(self, SyncError::UnexpectedResponse { .. })
207 }
208
209 pub fn is_not_found(&self) -> bool {
211 matches!(
212 self,
213 SyncError::PeerNotFound(_) | SyncError::EntryNotFound(_)
214 )
215 }
216
217 pub fn is_validation_error(&self) -> bool {
219 matches!(
220 self,
221 SyncError::InvalidEntry(_)
222 | SyncError::InvalidPublicKey { .. }
223 | SyncError::InvalidKeyName { .. }
224 )
225 }
226
227 pub fn is_backend_error(&self) -> bool {
229 matches!(self, SyncError::BackendError(_))
230 }
231}