Skip to main content

rtb_docs/
error.rs

1//! `DocsError` — every failure mode the browser / server / search
2//! path can surface.
3
4use std::sync::Arc;
5
6/// Every failure mode surfaced by `rtb-docs`.
7#[derive(Debug, thiserror::Error, miette::Diagnostic, Clone)]
8#[non_exhaustive]
9pub enum DocsError {
10    /// The configured `root` doesn't exist in the asset tree.
11    #[error("docs root not found in assets: {0}")]
12    #[diagnostic(code(rtb::docs::root_missing))]
13    RootMissing(String),
14
15    /// `_index.yaml` was present but couldn't be parsed.
16    #[error("index file not found or malformed: {0}")]
17    #[diagnostic(code(rtb::docs::index_malformed))]
18    IndexMalformed(String),
19
20    /// Markdown parse failed on a specific page.
21    #[error("markdown parse failed for {path}: {reason}")]
22    #[diagnostic(code(rtb::docs::markdown_error))]
23    MarkdownError {
24        /// The doc-tree-relative path that failed to parse.
25        path: String,
26        /// The inner parser error message.
27        reason: String,
28    },
29
30    /// Terminal initialisation (raw mode / alternate screen) failed.
31    #[error("terminal initialisation failed: {0}")]
32    #[diagnostic(code(rtb::docs::terminal))]
33    Terminal(String),
34
35    /// `docs ask` invoked without the `ai` feature compiled in.
36    #[error("AI feature not enabled")]
37    #[diagnostic(
38        code(rtb::docs::ai_disabled),
39        help("rebuild with `--features ai` to enable `docs ask`")
40    )]
41    AiDisabled,
42
43    /// Wrapped `rtb-assets::AssetError`. Carried as a message since
44    /// `AssetError` is not `Clone` and we want `DocsError: Clone`.
45    #[error("asset error: {0}")]
46    #[diagnostic(code(rtb::docs::assets))]
47    Assets(String),
48
49    /// Wrapped `tantivy::TantivyError`. Carried as a message since
50    /// `tantivy`'s error type is not `Clone`.
51    #[error("full-text search index error: {0}")]
52    #[diagnostic(code(rtb::docs::search))]
53    Search(String),
54
55    /// Wrapped `hyper` / `axum` server error.
56    #[error("docs server error: {0}")]
57    #[diagnostic(code(rtb::docs::server))]
58    Server(String),
59
60    /// I/O error surfaced through the cache-dir or server path.
61    #[error("I/O error: {0}")]
62    #[diagnostic(code(rtb::docs::io))]
63    Io(#[from] Arc<std::io::Error>),
64}
65
66impl From<std::io::Error> for DocsError {
67    fn from(err: std::io::Error) -> Self {
68        Self::Io(Arc::new(err))
69    }
70}
71
72impl From<tantivy::TantivyError> for DocsError {
73    fn from(err: tantivy::TantivyError) -> Self {
74        Self::Search(err.to_string())
75    }
76}
77
78impl From<rtb_assets::AssetError> for DocsError {
79    fn from(err: rtb_assets::AssetError) -> Self {
80        Self::Assets(err.to_string())
81    }
82}
83
84/// `Result<T, DocsError>`.
85pub type Result<T> = std::result::Result<T, DocsError>;