1use std::error::Error;
4use std::fmt;
5
6use nextcloud_sdk_core::UrlError;
7
8#[derive(Debug)]
10pub enum GoaError {
11 DBus(zbus::Error),
13 Url(UrlError),
15 NoAccountsFound,
17 MissingProperty(&'static str),
19}
20
21impl fmt::Display for GoaError {
22 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23 match self {
24 Self::DBus(err) => write!(f, "D-Bus operation failed: {err}"),
25 Self::Url(err) => write!(f, "failed to parse server URL: {err}"),
26 Self::NoAccountsFound => {
27 f.write_str("no Nextcloud or ownCloud accounts found in GNOME Online Accounts")
28 }
29 Self::MissingProperty(prop) => {
30 write!(f, "missing required D-Bus property `{prop}`")
31 }
32 }
33 }
34}
35
36impl Error for GoaError {
37 fn source(&self) -> Option<&(dyn Error + 'static)> {
38 match self {
39 Self::DBus(err) => Some(err),
40 Self::Url(err) => Some(err),
41 Self::NoAccountsFound | Self::MissingProperty(_) => None,
42 }
43 }
44}
45
46impl From<zbus::Error> for GoaError {
47 fn from(err: zbus::Error) -> Self {
48 Self::DBus(err)
49 }
50}
51
52impl From<UrlError> for GoaError {
53 fn from(err: UrlError) -> Self {
54 Self::Url(err)
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 use std::error::Error;
61
62 use nextcloud_sdk_core::UrlError;
63
64 use super::GoaError;
65
66 #[test]
67 fn display_formats_all_variants() {
68 assert!(
69 GoaError::NoAccountsFound
70 .to_string()
71 .contains("no Nextcloud")
72 );
73 assert!(
74 GoaError::MissingProperty("Id")
75 .to_string()
76 .contains("missing required D-Bus property `Id`")
77 );
78 assert!(
79 GoaError::Url(UrlError::MissingScheme)
80 .to_string()
81 .contains("server URL has no scheme")
82 );
83 }
84
85 #[test]
86 fn source_returns_underlying_error() {
87 let url_err = GoaError::Url(UrlError::MissingScheme);
88 assert!(url_err.source().is_some());
89
90 let missing = GoaError::MissingProperty("Id");
91 assert!(missing.source().is_none());
92
93 let no_acc = GoaError::NoAccountsFound;
94 assert!(no_acc.source().is_none());
95 }
96}