use thiserror::Error;
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum SyncError {
#[error("No transport enabled. Call enable_http_transport() first")]
NoTransportEnabled,
#[error("Server already running on {address}")]
ServerAlreadyRunning { address: String },
#[error("Server not running")]
ServerNotRunning,
#[error("Unexpected response type: expected {expected}, got {actual}")]
UnexpectedResponse {
expected: &'static str,
actual: String,
},
#[error("Network error: {0}")]
Network(String),
#[error("Failed to send command to background sync: {0}")]
CommandSendError(String),
#[error("Failed to initialize transport: {0}")]
TransportInit(String),
#[error("Failed to create async runtime: {0}")]
RuntimeCreation(String),
#[error("Failed to bind server to {address}: {reason}")]
ServerBind { address: String, reason: String },
#[error("Failed to connect to {address}: {reason}")]
ConnectionFailed { address: String, reason: String },
#[error("Device key '{key_name}' not found in backend storage")]
DeviceKeyNotFound { key_name: String },
#[error("Transport type '{transport_type}' not supported")]
UnsupportedTransport { transport_type: String },
#[error("Peer not found: {0}")]
PeerNotFound(String),
#[error("Peer already exists: {0}")]
PeerAlreadyExists(String),
#[error("Serialization error: {0}")]
SerializationError(String),
#[error("Protocol version mismatch: expected {expected}, received {received}")]
ProtocolMismatch { expected: u32, received: u32 },
#[error("Handshake failed: {0}")]
HandshakeFailed(String),
#[error("Entry not found: {0}")]
EntryNotFound(crate::entry::ID),
#[error("Invalid entry: {0}")]
InvalidEntry(String),
#[error("Sync protocol error: {0}")]
SyncProtocolError(String),
#[error("Backend error: {0}")]
BackendError(String),
#[error("Bootstrap request not found: {0}")]
RequestNotFound(String),
#[error("Bootstrap request already exists: {0}")]
RequestAlreadyExists(String),
#[error(
"Invalid request state for '{request_id}': expected {expected_status}, found {current_status}"
)]
InvalidRequestState {
request_id: String,
current_status: String,
expected_status: String,
},
#[error("Invalid data: {0}")]
InvalidData(String),
#[error(
"Insufficient permission for request '{request_id}': required {required_permission}, but key has {actual_permission:?}"
)]
InsufficientPermission {
request_id: String,
required_permission: String,
actual_permission: crate::auth::Permission,
},
#[error("Invalid public key: {reason}")]
InvalidPublicKey { reason: String },
#[error("Invalid key name: {reason}")]
InvalidKeyName { reason: String },
#[error("Instance has been dropped")]
InstanceDropped,
#[error("Bootstrap request pending approval (request_id: {request_id}): {message}")]
BootstrapPending { request_id: String, message: String },
}
impl SyncError {
pub fn is_configuration_error(&self) -> bool {
matches!(self, SyncError::NoTransportEnabled)
}
pub fn is_server_error(&self) -> bool {
matches!(
self,
SyncError::ServerAlreadyRunning { .. }
| SyncError::ServerNotRunning
| SyncError::ServerBind { .. }
)
}
pub fn is_network_error(&self) -> bool {
matches!(
self,
SyncError::Network(_) | SyncError::ConnectionFailed { .. }
)
}
pub fn is_protocol_error(&self) -> bool {
matches!(self, SyncError::UnexpectedResponse { .. })
}
pub fn is_not_found(&self) -> bool {
matches!(
self,
SyncError::PeerNotFound(_) | SyncError::EntryNotFound(_)
)
}
pub fn is_validation_error(&self) -> bool {
matches!(
self,
SyncError::InvalidEntry(_)
| SyncError::InvalidPublicKey { .. }
| SyncError::InvalidKeyName { .. }
)
}
pub fn is_backend_error(&self) -> bool {
matches!(self, SyncError::BackendError(_))
}
}