1use std::{error::Error as StdError, fmt::Display, path::PathBuf};
2
3use thiserror::Error;
4
5pub type Result<T> = std::result::Result<T, SyncwebError>;
6pub type BoxError = Box<dyn StdError + Send + Sync + 'static>;
7
8#[derive(Debug, Error)]
10#[non_exhaustive]
11pub enum SyncwebError {
12 #[error("folder not found: {0}")]
13 FolderNotFound(String),
14
15 #[error("no synchronized folders are available")]
16 NoFolders,
17
18 #[error("folder selector {0:?} is not a namespace ID and more than one synchronized folder is available")]
19 AmbiguousFolderSelector(String),
20
21 #[error("folder already managed")]
22 FolderAlreadyManaged,
23
24 #[error("folder mode {mode} does not permit local writes")]
25 WriteDenied { mode: String },
26
27 #[error("invalid doc ticket: {0}")]
28 InvalidTicket(String),
29
30 #[error("invalid configuration: {0}")]
31 InvalidConfig(String),
32
33 #[error("invalid identity: {0}")]
34 InvalidIdentity(String),
35
36 #[error("invalid device ID: {0}")]
37 InvalidDeviceId(String),
38
39 #[error("invalid sync mode: {0}")]
40 InvalidSyncMode(String),
41
42 #[error("syncthing relay fallback is disabled")]
43 RelayDisabled,
44
45 #[error("no syncthing relay is reachable: {reasons}")]
46 RelayUnreachable { reasons: String },
47
48 #[error("relay frame exceeds {max} byte limit")]
49 RelayFrameTooLarge { max: usize },
50
51 #[error("relay message decode error: {0}")]
52 RelayDecode(String),
53
54 #[error("relay URL must use tcp:// scheme")]
55 RelayBadScheme,
56
57 #[error("relay URL must contain a host and port: {0}")]
58 RelayBadAddress(String),
59
60 #[error("HKDF key derivation failed: {0}")]
61 KeyDerivation(String),
62
63 #[error("identity file error at {path}: {source}")]
64 Identity {
65 path: PathBuf,
66 #[source]
67 source: BoxError,
68 },
69
70 #[error("{context}: {detail}")]
71 Operation { context: String, detail: String },
72
73 #[error("blob size exceeds u64::MAX")]
74 BlobTooLarge,
75
76 #[error("namespace could not be opened")]
77 NamespaceNotAvailable,
78
79 #[error("missing cryptographic signature: {0}")]
80 MissingSignature(String),
81
82 #[error("invalid cryptographic signature: {0}")]
83 InvalidSignature(String),
84
85 #[error("access denied: {0}")]
86 AccessDenied(String),
87
88 #[error(transparent)]
89 Io(#[from] std::io::Error),
90}
91
92impl SyncwebError {
93 pub fn identity(path: impl Into<PathBuf>, source: impl StdError + Send + Sync + 'static) -> Self {
94 Self::Identity {
95 path: path.into(),
96 source: Box::new(source),
97 }
98 }
99
100 pub fn operation(context: impl Into<String>, source: impl Display) -> Self {
101 Self::Operation {
102 context: context.into(),
103 detail: source.to_string(),
104 }
105 }
106
107 pub fn access_denied(reason: impl Into<String>) -> Self {
108 Self::AccessDenied(reason.into())
109 }
110}