ankiconnect_rs/
error.rs

1//! Error types for the ankiconnect-rs crate
2
3use thiserror::Error;
4
5pub type Result<T> = std::result::Result<T, AnkiError>;
6
7/// Main error type for the ankiconnect-rs crate
8#[derive(Error, Debug)]
9pub enum AnkiError {
10    /// Error from the AnkiConnect API
11    #[error(transparent)]
12    AnkiConnectError(#[from] AnkiConnectError),
13
14    /// HTTP request error
15    #[error("HTTP request failed: {0}")]
16    HttpError(#[from] ureq::Error),
17
18    /// JSON parsing error
19    #[error("JSON parsing failed: {0}")]
20    JsonError(String),
21
22    /// Invalid field for the given model
23    #[error("Invalid field '{field_name}' for model '{model_name}'")]
24    InvalidField {
25        field_name: String,
26        model_name: String,
27    },
28
29    /// Validation error
30    #[error("Validation error: {0}")]
31    ValidationError(String),
32
33    #[error("Unknown error: {0}")]
34    UnknownError(String),
35}
36
37/// Errors specific to the AnkiConnect API
38#[derive(Error, Debug)]
39pub enum AnkiConnectError {
40    /// The action is not supported by AnkiConnect
41    #[error("Unsupported action")]
42    UnsupportedAction,
43
44    /// Field values would make an empty question
45    #[error("The field values would make an empty question")]
46    EmptyQuestion,
47
48    /// The specified model was not found
49    #[error("Model not found: {0}")]
50    ModelNotFound(String),
51
52    /// The specified deck was not found
53    #[error("Deck not found: {0}")]
54    DeckNotFound(String),
55
56    /// The note is a duplicate
57    #[error("Duplicate note")]
58    DuplicateNote,
59
60    /// The note is empty
61    #[error("Empty note")]
62    EmptyNote,
63
64    /// Missing media field (data, path, or URL)
65    #[error("Missing media field (provide data, path, or URL)")]
66    MissingMediaField,
67
68    /// A model with this name already exists
69    #[error("Model name already exists")]
70    ModelNameExists,
71
72    /// Invalid column ID
73    #[error("Invalid column ID: {0}")]
74    InvalidColumnId(String),
75
76    /// Invalid card order
77    #[error("Invalid card order: {0}")]
78    InvalidCardOrder(String),
79
80    /// Other unspecified AnkiConnect error
81    #[error("Other error: {0}")]
82    Other(String),
83}
84
85/// Errors that can occur when creating or manipulating notes
86#[derive(Error, Debug)]
87pub enum NoteError {
88    /// A required field was missing from the note
89    #[error("Missing required field: {0}")]
90    MissingField(String),
91
92    /// An unknown field was provided
93    #[error("Unknown field: {0}")]
94    UnknownField(String),
95
96    /// A field was provided with empty content
97    #[error("Empty content for field: {0}")]
98    EmptyField(String),
99
100    /// Field content would make an empty question
101    #[error("The provided field content would result in an empty question")]
102    EmptyQuestion,
103
104    /// Media file is missing or invalid
105    #[error("Invalid media: {0}")]
106    InvalidMedia(String),
107
108    /// The note would be a duplicate
109    #[error("Note would be a duplicate of an existing note")]
110    DuplicateNote,
111
112    /// Other validation error
113    #[error("Note validation error: {0}")]
114    ValidationError(String),
115
116    /// Field content validation error
117    #[error("Field content validation error for '{field}': {message}")]
118    FieldValidationError { field: String, message: String },
119
120    /// Conversion from AnkiError
121    #[error("Anki error: {0}")]
122    AnkiError(#[from] AnkiError),
123}
124
125// Implement conversion from AnkiConnectError to NoteError for convenience
126impl From<AnkiConnectError> for NoteError {
127    fn from(err: AnkiConnectError) -> Self {
128        use crate::error::AnkiConnectError;
129        match err {
130            AnkiConnectError::EmptyQuestion => NoteError::EmptyQuestion,
131            AnkiConnectError::DuplicateNote => NoteError::DuplicateNote,
132            AnkiConnectError::EmptyNote => NoteError::ValidationError("Note is empty".to_string()),
133            e => NoteError::AnkiError(e.into()),
134        }
135    }
136}