Skip to main content

alpm_db/
error.rs

1//! Error handling.
2
3use std::path::PathBuf;
4
5use alpm_parsers::error::{Input, ParseStack};
6use fluent_i18n::t;
7use winnow::error::ParseError;
8
9use crate::desc::SectionKeyword;
10
11/// The error that can occur when working with the ALPM database desc files.
12#[derive(Debug, thiserror::Error)]
13#[non_exhaustive]
14pub enum Error {
15    /// An [`alpm_types::Error`].
16    #[error("{msg}", msg = t!("error-alpm-types", { "source" => .0.to_string() }))]
17    AlpmTypes(#[from] alpm_types::Error),
18
19    /// IO error.
20    #[error("{msg}", msg = t!("error-io", { "context" => context, "source" => source.to_string() }))]
21    Io {
22        /// The context in which the error occurred.
23        ///
24        /// This is meant to complete the sentence "I/O error while ".
25        context: String,
26        /// The source error.
27        source: std::io::Error,
28    },
29
30    /// An I/O error occurred at a path.
31    #[error("{msg}", msg = t!("error-io-path", {
32        "path" => path.display().to_string(),
33        "context" => context,
34        "source" => source.to_string(),
35    }))]
36    IoPath {
37        /// The path at which the error occurred.
38        path: PathBuf,
39        /// The context in which the error occurred.
40        ///
41        /// This is meant to complete the sentence "I/O error at path while ".
42        context: String,
43        /// The source error.
44        source: std::io::Error,
45    },
46
47    /// I/O error while reading a buffer.
48    #[error("{msg}", msg = t!("error-io-read", { "context" => context, "source" => source.to_string() }))]
49    IoRead {
50        /// The context in which the error occurred.
51        ///
52        /// This is meant to complete the sentence "Read error while ".
53        context: String,
54        /// The error source.
55        source: std::io::Error,
56    },
57
58    /// A winnow parser for a type didn't work and produced an error.
59    #[error("{msg}", msg = t!("error-parse", { "error" => .0 }))]
60    Parse(String),
61
62    /// A section is missing in the parsed data.
63    #[error("{msg}", msg = t!("error-missing-section", { "section" => .0.to_string() }))]
64    MissingSection(SectionKeyword),
65
66    /// A section is duplicated in the parsed data.
67    #[error("{msg}", msg = t!("error-duplicate-section", { "section" => .0.to_string() }))]
68    DuplicateSection(SectionKeyword),
69
70    /// No input file given.
71    #[error("{msg}", msg = t!("error-no-input-file"))]
72    NoInputFile,
73
74    #[cfg(feature = "cli")]
75    /// JSON error.
76    #[error("{msg}", msg = t!("error-json", { "context" => context, "source" => source.to_string() }))]
77    Json {
78        /// The context in which the error occurred.
79        ///
80        /// This is meant to complete the sentence "JSON error while ".
81        context: String,
82        /// The error source.
83        source: serde_json::Error,
84    },
85
86    /// Unsupported schema version.
87    #[error("{msg}", msg = t!("error-unsupported-schema-version", { "version" => .0 }))]
88    UnsupportedSchemaVersion(String),
89
90    /// Failed to parse v1 or v2.
91    #[error("{msg}", msg = t!("error-invalid-format"))]
92    InvalidFormat,
93}
94
95impl<'a> From<ParseError<Input<'a>, ParseStack<'a>>> for Error {
96    /// Converts a [`ParseError`] into an [`Error::Parse`].
97    fn from(value: ParseError<Input<'a>, ParseStack<'a>>) -> Self {
98        // Only take the **inner** parser error of our own ParseStack error type.
99        // We don't want to hit the `Display` impl of `ParseError`.
100        Self::Parse(value.into_inner().to_string())
101    }
102}