ffbm/
error.rs

1//! Error types for ffbm.
2
3use std::fmt;
4use std::path::PathBuf;
5
6/// Errors that can occur during bookmark management.
7#[derive(Debug)]
8pub enum Error {
9    /// Firefox is currently running; close it first.
10    FirefoxRunning,
11    /// Firefox application directory not found.
12    FirefoxDirNotFound,
13    /// No Profile Groups databases found.
14    NoProfileGroups,
15    /// Profile name not found.
16    ProfileNotFound { name: String },
17    /// Multiple profiles match the given name.
18    AmbiguousProfile { name: String, matches: Vec<String> },
19    /// Profile path specified does not exist.
20    ProfilePathInvalid { path: PathBuf },
21    /// Database file not found in profile.
22    DatabaseNotFound { name: String, path: PathBuf },
23    /// Database error.
24    Sqlite(rusqlite::Error),
25    /// I/O error.
26    Io(std::io::Error),
27    /// TOML serialization error.
28    TomlSerialize(toml::ser::Error),
29    /// TOML deserialization error.
30    TomlDeserialize(toml::de::Error),
31    /// Invalid bookmark data.
32    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
116/// A specialized Result type for ffbm operations.
117pub type Result<T> = std::result::Result<T, Error>;