1use std::fmt;
4
5#[derive(Debug)]
7pub enum Error {
8 Sqlite(rusqlite::Error),
10 SchemaTooNew {
12 found: i64,
14 supported: i64,
16 },
17 InvalidTimestamp(String),
19 Json(serde_json::Error),
21 Search(omgbase_search::Error),
23 Mutation(omgbase_mutate::MutationError),
25 MintExhausted {
28 prefix: String,
30 rejected: usize,
32 },
33 InvalidEffect(String),
37 RevisionArchived {
41 rev: String,
43 archive: String,
45 path: Option<String>,
48 },
49 NotASegment {
52 path: String,
54 detail: String,
57 },
58 StaleSegment {
62 path: String,
64 rev: String,
66 },
67 RetentionPolicy(String),
69 Other(String),
71}
72
73impl fmt::Display for Error {
74 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75 match self {
76 Error::Sqlite(e) => write!(f, "sqlite: {e}"),
77 Error::SchemaTooNew { found, supported } => write!(
78 f,
79 "database schema (v{found}) is newer than this build (v{supported}); upgrade omgbase"
80 ),
81 Error::InvalidTimestamp(ts) => write!(f, "invalid RFC 3339 UTC timestamp {ts:?}"),
82 Error::Json(e) => write!(f, "json: {e}"),
83 Error::Search(e) => write!(f, "search: {e}"),
84 Error::Mutation(e) => write!(f, "mutation: {e}"),
85 Error::MintExhausted { prefix, rejected } => write!(
86 f,
87 "mint({prefix}): {rejected} consecutive candidates were already in use; the minter cannot produce a fresh id"
88 ),
89 Error::InvalidEffect(msg) => write!(f, "invalid effect: {msg}"),
90 Error::RevisionArchived {
93 rev,
94 archive,
95 path: None,
96 } => write!(
97 f,
98 "revision {} is archived in segment {archive}, which is not attached (omg history attach <file>)",
99 serde_json::Value::String(rev.clone())
100 ),
101 Error::RevisionArchived {
102 rev,
103 archive,
104 path: Some(path),
105 } => write!(
106 f,
107 "revision {} is archived in segment {archive} at {path}, which is not on disk",
108 serde_json::Value::String(rev.clone())
109 ),
110 Error::NotASegment { path, detail } => write!(f, "{path}: {detail}"),
111 Error::StaleSegment { path, rev } => write!(
112 f,
113 "{path}: an unrecorded segment naming revision {rev}, which is not a live revision of this store — move the file out of the way"
114 ),
115 Error::RetentionPolicy(msg) => f.write_str(msg),
116 Error::Other(msg) => f.write_str(msg),
117 }
118 }
119}
120
121impl std::error::Error for Error {
122 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
123 match self {
124 Error::Sqlite(e) => Some(e),
125 Error::Json(e) => Some(e),
126 Error::Search(e) => Some(e),
127 Error::Mutation(e) => Some(e),
128 _ => None,
129 }
130 }
131}
132
133impl From<rusqlite::Error> for Error {
134 fn from(e: rusqlite::Error) -> Self {
135 Error::Sqlite(e)
136 }
137}
138
139impl From<serde_json::Error> for Error {
140 fn from(e: serde_json::Error) -> Self {
141 Error::Json(e)
142 }
143}
144
145impl From<omgbase_search::Error> for Error {
146 fn from(e: omgbase_search::Error) -> Self {
147 Error::Search(e)
148 }
149}
150
151impl From<omgbase_mutate::MutationError> for Error {
152 fn from(e: omgbase_mutate::MutationError) -> Self {
153 Error::Mutation(e)
154 }
155}
156
157impl Error {
158 #[must_use]
160 pub fn as_mutation(&self) -> Option<&omgbase_mutate::MutationError> {
161 match self {
162 Error::Mutation(e) => Some(e),
163 _ => None,
164 }
165 }
166}
167
168pub type Result<T> = std::result::Result<T, Error>;