mod parse;
use std::{
fmt::{self, Display, Formatter},
str::FromStr,
};
const DEFAULT_URGENCY: u8 = 3;
const MAX_URGENCY: u8 = 7;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Priority {
urgency: u8,
incremental: bool,
}
impl Default for Priority {
fn default() -> Self {
Self {
urgency: DEFAULT_URGENCY,
incremental: false,
}
}
}
impl Priority {
#[must_use]
#[cfg(test)] pub fn new(urgency: u8) -> Self {
Self {
urgency: urgency.min(MAX_URGENCY),
incremental: false,
}
}
#[must_use]
pub const fn urgency(self) -> u8 {
self.urgency
}
#[must_use]
pub const fn is_incremental(self) -> bool {
self.incremental
}
#[must_use]
#[cfg(test)] pub fn with_urgency(mut self, urgency: u8) -> Self {
self.urgency = urgency.min(MAX_URGENCY);
self
}
#[must_use]
#[cfg(test)] pub const fn with_incremental(mut self, incremental: bool) -> Self {
self.incremental = incremental;
self
}
#[must_use]
pub fn parse(s: &str) -> Self {
parse::parse(s)
}
}
impl FromStr for Priority {
type Err = std::convert::Infallible;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self::parse(s))
}
}
impl Display for Priority {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "u={}", self.urgency)?;
if self.incremental {
f.write_str(", i")?;
}
Ok(())
}
}
#[cfg(test)]
mod test {
use super::Priority;
#[test]
fn defaults() {
let p = Priority::default();
assert_eq!(p.urgency(), 3);
assert!(!p.is_incremental());
}
#[test]
fn constructors_clamp() {
assert_eq!(Priority::new(5).urgency(), 5);
assert_eq!(Priority::new(200).urgency(), 7);
assert_eq!(Priority::default().with_urgency(99).urgency(), 7);
assert!(Priority::new(0).with_incremental(true).is_incremental());
}
#[test]
fn display_roundtrip() {
assert_eq!(Priority::new(3).to_string(), "u=3");
assert_eq!(
Priority::new(0).with_incremental(true).to_string(),
"u=0, i"
);
for urgency in 0..=7 {
for incremental in [false, true] {
let p = Priority::new(urgency).with_incremental(incremental);
assert_eq!(p.to_string().parse::<Priority>().unwrap(), p);
}
}
}
}