1use std::fmt;
4use std::path::PathBuf;
5
6#[derive(Debug)]
8pub enum Error {
9 FirefoxRunning,
11 FirefoxDirNotFound,
13 NoProfileGroups,
15 ProfileNotFound { name: String },
17 AmbiguousProfile { name: String, matches: Vec<String> },
19 ProfilePathInvalid { path: PathBuf },
21 DatabaseNotFound { name: String, path: PathBuf },
23 Sqlite(rusqlite::Error),
25 Io(std::io::Error),
27 TomlSerialize(toml::ser::Error),
29 TomlDeserialize(toml::de::Error),
31 InvalidBookmark { reason: String },
33}
34
35impl fmt::Display for Error {
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 match self {
38 Self::FirefoxRunning => {
39 write!(f, "Firefox is running; close it before modifying bookmarks")
40 }
41 Self::FirefoxDirNotFound => write!(
42 f,
43 "Firefox directory not found (expected ~/Library/Application Support/Firefox)"
44 ),
45 Self::NoProfileGroups => {
46 write!(f, "no Profile Groups databases found in Firefox directory")
47 }
48 Self::ProfileNotFound { name } => {
49 write!(f, "profile not found: {name}")
50 }
51 Self::AmbiguousProfile { name, matches } => {
52 write!(
53 f,
54 "multiple profiles match \"{name}\": {}",
55 matches.join(", ")
56 )
57 }
58 Self::ProfilePathInvalid { path } => {
59 write!(f, "profile path does not exist: {}", path.display())
60 }
61 Self::DatabaseNotFound { name, path } => {
62 write!(f, "database {} not found in {}", name, path.display())
63 }
64 Self::Sqlite(e) => write!(f, "SQLite error: {e}"),
65 Self::Io(e) => write!(f, "I/O error: {e}"),
66 Self::TomlSerialize(e) => write!(f, "TOML serialization error: {e}"),
67 Self::TomlDeserialize(e) => write!(f, "TOML deserialization error: {e}"),
68 Self::InvalidBookmark { reason } => write!(f, "invalid bookmark: {reason}"),
69 }
70 }
71}
72
73impl std::error::Error for Error {
74 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
75 match self {
76 Self::Sqlite(e) => Some(e),
77 Self::Io(e) => Some(e),
78 Self::TomlSerialize(e) => Some(e),
79 Self::TomlDeserialize(e) => Some(e),
80 Self::FirefoxRunning
81 | Self::FirefoxDirNotFound
82 | Self::NoProfileGroups
83 | Self::ProfileNotFound { .. }
84 | Self::AmbiguousProfile { .. }
85 | Self::ProfilePathInvalid { .. }
86 | Self::DatabaseNotFound { .. }
87 | Self::InvalidBookmark { .. } => None,
88 }
89 }
90}
91
92impl From<rusqlite::Error> for Error {
93 fn from(e: rusqlite::Error) -> Self {
94 Self::Sqlite(e)
95 }
96}
97
98impl From<std::io::Error> for Error {
99 fn from(e: std::io::Error) -> Self {
100 Self::Io(e)
101 }
102}
103
104impl From<toml::ser::Error> for Error {
105 fn from(e: toml::ser::Error) -> Self {
106 Self::TomlSerialize(e)
107 }
108}
109
110impl From<toml::de::Error> for Error {
111 fn from(e: toml::de::Error) -> Self {
112 Self::TomlDeserialize(e)
113 }
114}
115
116pub type Result<T> = std::result::Result<T, Error>;