Skip to main content

jobberdb/
error.rs

1//! Errors & Warnings
2
3use super::prelude::*;
4use thiserror::Error;
5
6/// Errors that occur in *jobber*.
7#[derive(Error, Debug)]
8pub enum Error {
9    /// No database found
10    #[error("No database found")]
11    NoDatabase,
12    /// Database is empty
13    #[error("Database is empty")]
14    DatabaseEmpty,
15    /// Global configuration error
16    #[error("Global configuration error")]
17    Confy(confy::ConfyError),
18    /// I/O error
19    #[error("I/O error: {0}")]
20    Io(std::io::Error),
21    /// Formatting error
22    #[error("Formatting error: {0}")]
23    Fmt(std::fmt::Error),
24    /// JSON error
25    #[error("JSON error: {0}")]
26    Json(serde_json::Error),
27    /// There still is an open job.
28    #[error("There still is an open job:\n\n    Pos: {0}\n{1}")]
29    OpenJob(usize, Job),
30    /// There is no open job.
31    #[error("There is no open job")]
32    NoOpenJob,
33    /// End of the job is before it's start
34    #[error("End {0} of the job is before it's start {1}")]
35    EndBeforeStart(DateTime, DateTime),
36    /// Found warming(s).
37    #[error("Found warming(s).")]
38    Warnings(Vec<Warning>),
39    /// You canceled.
40    #[error("You canceled.")]
41    Cancel,
42    /// Can not use tags within same job because they have different configurations.
43    #[error("Can not use tags {0} within same job because they have different configurations.")]
44    TagCollision(TagSet),
45    /// User needs to enter message
46    #[error("User needs to enter message")]
47    EnterMessage,
48    /// Unknown column name
49    #[error("Unknown column name '{0}'")]
50    UnknownColumn(String),
51    /// Output file already exists.
52    #[error("Output file '{0}' already exists.")]
53    OutputFileExists(String),
54    /// Date/Time parse error: {0}
55    #[error("Date/Time parse error: {0}")]
56    DateTimeParse(chrono::ParseError),
57    /// No job found at position {0}
58    #[error("No job found at position {0}")]
59    JobNotFound(usize),
60    /// A value is required for '--tags <TAGS>' but none was supplied
61    #[error("a value is required for '--tags <TAGS>' but none was supplied")]
62    MissingTags,
63    /// Too few jobs in database to process operation
64    #[error("Too few jobs in database to process operation in range {0}-{0}")]
65    ToFewJobs(usize, usize),
66    /// Parsing of a range failed
67    #[error("Parsing of range '{0}' failed")]
68    RangeFormat(String),
69    /// Parsing of a duration failed
70    #[error("Parsing of duration '{0}' failed")]
71    DurationFormat(String),
72    /// Parsing of a partial date and time failed
73    #[error("Parsing of partial date and time '{0}' failed")]
74    PartialDateTimeFormat(String),
75}
76
77impl From<std::io::Error> for Error {
78    fn from(err: std::io::Error) -> Self {
79        Error::Io(err)
80    }
81}
82
83impl From<std::fmt::Error> for Error {
84    fn from(err: std::fmt::Error) -> Self {
85        Error::Fmt(err)
86    }
87}
88
89/// Warnings that occur in *jobber* which the user might want to ignore.
90#[derive(Error, Debug)]
91pub enum Warning {
92    /// The job you want to add overlaps existing one(s)
93    #[error("The job you want to add overlaps existing one(s):\n\nJob you want to add:\n\n{new}\nExisting overlapping jobs:\n\n{existing}")]
94    Overlaps { new: Job, existing: JobListOwned },
95    #[error(
96        "You have used some tags ({0}) which are unknown so far. Continue if you want to create them."
97    )]
98    UnknownTags(TagSet),
99    /// You are about to delete job(s) at the following position(s).
100    #[error("You are about to delete job(s) at the following position(s): {0}")]
101    ConfirmDeletion(Positions),
102}
103
104/// List of jobs with index extracted from database list.
105///
106/// This is needed to let `Error` contain job lists even if the database is gone already.
107#[derive(Debug)]
108pub struct JobListOwned {
109    /// List of jobs (including original index within database).
110    jobs: Vec<(usize, Job)>,
111    /// Copy of the configuration of the original [Jobs] database.
112    pub configuration: Configuration,
113}
114
115impl JobListOwned {
116    /// Get read-only iterator over included jobs.
117    pub fn iter(&self) -> core::slice::Iter<'_, (usize, Job)> {
118        self.jobs.iter()
119    }
120}
121
122impl From<JobList<'_>> for JobListOwned {
123    fn from(list: JobList) -> Self {
124        Self {
125            configuration: list.configuration.clone(),
126            jobs: list.into_iter().map(|(n, j)| (n, j.clone())).collect(),
127        }
128    }
129}
130
131impl std::fmt::Display for JobListOwned {
132    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
133        JobList::from(self).fmt(f)
134    }
135}