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, }, }