97 lines
2.7 KiB
Rust
97 lines
2.7 KiB
Rust
use std::io;
|
|
|
|
use log::Level;
|
|
use serde::Serialize;
|
|
use thiserror::Error;
|
|
|
|
#[derive(Error, Debug, Serialize)]
|
|
#[serde(tag = "kind", content = "details")]
|
|
pub enum SearchError {
|
|
#[error("another thread found a solution")]
|
|
SolutionFound,
|
|
#[error("time limit exceeded")]
|
|
Timeout,
|
|
#[error("schedule is already manually filled")]
|
|
ScheduleFull,
|
|
#[error("user configuration is invalid")]
|
|
Config(String),
|
|
#[error("no solution found")]
|
|
NoSolutionFound,
|
|
}
|
|
|
|
impl SearchError {
|
|
pub fn log_level(&self) -> Level {
|
|
match self {
|
|
SearchError::SolutionFound | SearchError::ScheduleFull => Level::Info,
|
|
SearchError::NoSolutionFound => Level::Warn,
|
|
SearchError::Timeout | SearchError::Config(_) => Level::Error,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<anyhow::Error> for SearchError {
|
|
fn from(err: anyhow::Error) -> Self {
|
|
SearchError::Config(err.to_string())
|
|
}
|
|
}
|
|
|
|
#[derive(Error, Debug)]
|
|
pub enum ExportError {
|
|
#[error("no schedule has been generated yet")]
|
|
NotGenerated,
|
|
#[error("path not found: {0}")]
|
|
InvalidPath(#[from] io::Error),
|
|
#[error("docx packaging error: {0}")]
|
|
Packaging(String),
|
|
#[error("failed to open doc: {0}")]
|
|
OpenFailed(String),
|
|
}
|
|
|
|
#[derive(Error, Debug, Serialize)]
|
|
#[serde(tag = "kind", content = "details")]
|
|
pub enum SwapError {
|
|
#[error("no schedule has been generated yet")]
|
|
NotGenerated,
|
|
#[error("invalid shift position: {0}")]
|
|
InvalidPosition(String),
|
|
#[error("slot has no assigned resident")]
|
|
SlotEmpty,
|
|
#[error("both slots belong to the same resident")]
|
|
SameResident,
|
|
#[error("resident not found in config")]
|
|
ResidentNotFound,
|
|
#[error("resident cannot take the target slot: negative shift or disallowed type")]
|
|
ResidentCannotTakeSlot,
|
|
#[error("swap violates same-day or toxic pair constraint")]
|
|
SameDayOrToxicPair,
|
|
#[error("swap creates a consecutive-day constraint violation")]
|
|
ConsecutiveDays,
|
|
#[error("cannot swap the same slot or slots on the same day")]
|
|
SameSlotOrDay,
|
|
}
|
|
|
|
impl Serialize for ExportError {
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: serde::Serializer,
|
|
{
|
|
use serde::ser::SerializeStruct;
|
|
|
|
let mut s = serializer.serialize_struct("ExportError", 2)?;
|
|
|
|
s.serialize_field(
|
|
"kind",
|
|
match self {
|
|
ExportError::NotGenerated => "NotGenerated",
|
|
ExportError::InvalidPath(_) => "InvalidPath",
|
|
ExportError::Packaging(_) => "Packaging",
|
|
ExportError::OpenFailed(_) => "OpenFailed",
|
|
},
|
|
)?;
|
|
|
|
s.serialize_field("details", &self.to_string())?;
|
|
|
|
s.end()
|
|
}
|
|
}
|