105 lines
2.8 KiB
Rust
105 lines
2.8 KiB
Rust
use std::path::PathBuf;
|
|
use thiserror::Error;
|
|
|
|
/// Top-level error returned from all public Brittle API methods.
|
|
#[derive(Debug, Error)]
|
|
pub enum BrittleError {
|
|
#[error("{0}")]
|
|
Store(#[from] StoreError),
|
|
|
|
#[error("{0}")]
|
|
Validation(#[from] ValidationError),
|
|
|
|
#[error("{0}")]
|
|
BibTeX(#[from] BibtexError),
|
|
}
|
|
|
|
/// Errors from the storage layer.
|
|
#[derive(Debug, Error)]
|
|
pub enum StoreError {
|
|
#[error("{entity_type} not found: {id}")]
|
|
NotFound { entity_type: EntityType, id: String },
|
|
|
|
#[error("I/O error: {0}")]
|
|
Io(#[from] std::io::Error),
|
|
|
|
#[error("serialization error: {message}")]
|
|
Serialization { message: String },
|
|
|
|
#[error("deserialization error for {path}: {message}")]
|
|
Deserialization { path: PathBuf, message: String },
|
|
|
|
#[error("git error: {0}")]
|
|
Git(#[from] git2::Error),
|
|
|
|
#[error("repository not found at {path}")]
|
|
RepoNotFound { path: PathBuf },
|
|
|
|
#[error("repository already exists at {path}")]
|
|
RepoAlreadyExists { path: PathBuf },
|
|
}
|
|
|
|
/// The kind of entity involved in a not-found error.
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub enum EntityType {
|
|
Reference,
|
|
Library,
|
|
Annotation,
|
|
Snapshot,
|
|
}
|
|
|
|
impl std::fmt::Display for EntityType {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
EntityType::Reference => write!(f, "Reference"),
|
|
EntityType::Library => write!(f, "Library"),
|
|
EntityType::Annotation => write!(f, "Annotation"),
|
|
EntityType::Snapshot => write!(f, "Snapshot"),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Business logic validation errors.
|
|
#[derive(Debug, Error)]
|
|
pub enum ValidationError {
|
|
#[error(
|
|
"library cycle detected: moving library {library_id} under {parent_id} would create a cycle"
|
|
)]
|
|
LibraryCycle {
|
|
library_id: String,
|
|
parent_id: String,
|
|
},
|
|
|
|
#[error("library {id} has children and cannot be deleted; delete or move children first")]
|
|
LibraryHasChildren { id: String },
|
|
|
|
#[error("cite key already exists: {cite_key}")]
|
|
DuplicateCiteKey { cite_key: String },
|
|
|
|
#[error("cite key cannot be empty")]
|
|
EmptyCiteKey,
|
|
|
|
#[error("library name cannot be empty")]
|
|
EmptyLibraryName,
|
|
|
|
#[error("reference {reference_id} has no PDF attached")]
|
|
NoPdfAttached { reference_id: String },
|
|
|
|
#[error("PDF file not found: {path}")]
|
|
PdfNotFound { path: PathBuf },
|
|
|
|
#[error("there are uncommitted changes; create a snapshot or call discard_changes() first")]
|
|
UncommittedChanges,
|
|
}
|
|
|
|
/// Errors specific to BibTeX export.
|
|
#[derive(Debug, Error)]
|
|
pub enum BibtexError {
|
|
#[error("reference '{cite_key}' ({entry_type}): missing required field '{field}'")]
|
|
MissingRequiredField {
|
|
cite_key: String,
|
|
entry_type: String,
|
|
field: String,
|
|
},
|
|
}
|