Skip to main content

alpm_repo_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-repo-desc`] files.
12///
13/// [`alpm-repo-desc`]: https://alpm.archlinux.page/specifications/alpm-repo-desc.5.html
14#[derive(Debug, thiserror::Error)]
15#[non_exhaustive]
16pub enum Error {
17    /// IO error.
18    #[error("{msg}", msg = t!("error-io", { "context" => context, "source" => source.to_string() }))]
19    Io {
20        /// The context in which the error occurred.
21        ///
22        /// This is meant to complete the sentence "I/O error while ".
23        context: String,
24        /// The source error.
25        source: std::io::Error,
26    },
27
28    /// An I/O error occurred at a path.
29    #[error("{msg}", msg = t!("error-io-path", {
30        "path" => path.display().to_string(),
31        "context" => context,
32        "source" => source.to_string(),
33    }))]
34    IoPath {
35        /// The path at which the error occurred.
36        path: PathBuf,
37        /// The context in which the error occurred.
38        ///
39        /// This is meant to complete the sentence "I/O error at path while ".
40        context: String,
41        /// The source error.
42        source: std::io::Error,
43    },
44
45    /// I/O error while reading a buffer.
46    #[error("{msg}", msg = t!("error-io-read", { "context" => context, "source" => source.to_string() }))]
47    IoRead {
48        /// The context in which the error occurred.
49        ///
50        /// This is meant to complete the sentence "Read error while ".
51        context: String,
52        /// The error source.
53        source: std::io::Error,
54    },
55
56    /// A winnow parser for a type didn't work and produced an error.
57    #[error("{msg}", msg = t!("error-parse", { "error" => .0 }))]
58    ParseError(String),
59
60    /// A section is missing in the parsed data.
61    #[error("{msg}", msg = t!("error-missing-section", { "section" => .0.to_string() }))]
62    MissingSection(SectionKeyword),
63
64    /// A section is duplicated in the parsed data.
65    #[error("{msg}", msg = t!("error-duplicate-section", { "section" => .0.to_string() }))]
66    DuplicateSection(SectionKeyword),
67
68    /// A section is invalid for the given schema version.
69    #[error("{msg}", msg = t!("error-invalid-section-for-version", { "section" => section.to_string(), "version" => version.to_string() }))]
70    InvalidSectionForVersion {
71        /// The section keyword.
72        section: SectionKeyword,
73        /// The schema version.
74        version: u8,
75    },
76
77    /// Found an empty section that should either contain value(s) or be omitted.
78    #[error("{msg}", msg = t!("error-empty-section", { "section" => .0.to_string() }))]
79    EmptySection(SectionKeyword),
80
81    /// No input file given.
82    #[error("{msg}", msg = t!("error-no-input-file"))]
83    NoInputFile,
84
85    #[cfg(feature = "cli")]
86    /// JSON error.
87    #[error("{msg}", msg = t!("error-json", { "context" => context, "source" => source.to_string() }))]
88    Json {
89        /// The context in which the error occurred.
90        ///
91        /// This is meant to complete the sentence "JSON error while ".
92        context: String,
93        /// The error source.
94        source: serde_json::Error,
95    },
96
97    /// Unsupported schema version.
98    #[error("{msg}", msg = t!("error-unsupported-schema-version", { "version" => .0 }))]
99    UnsupportedSchemaVersion(String),
100
101    /// Failed to parse v1 or v2.
102    #[error("{msg}", msg = t!("error-invalid-format"))]
103    InvalidFormat,
104}
105
106impl<'a> From<ParseError<Input<'a>, ParseStack<'a>>> for Error {
107    /// Converts a [`ParseError`] into an [`Error::ParseError`].
108    fn from(value: ParseError<Input<'a>, ParseStack<'a>>) -> Self {
109        // Only take the **inner** parser error of our own ParseStack error type.
110        // We don't want to hit the `Display` impl of `ParseError`.
111        Self::ParseError(value.into_inner().to_string())
112    }
113}