use std::fmt;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct DispatcherPriority {
value: i32,
}
impl DispatcherPriority {
const fn new(value: i32) -> Self {
Self { value }
}
#[inline]
pub const fn value(self) -> i32 {
self.value
}
pub const DEFAULT: Self = Self::new(0);
pub(crate) const MINIMUM_FOREGROUND_PRIORITY: Self = Self::DEFAULT;
pub const INPUT: Self = Self::new(Self::DEFAULT.value - 1);
pub const BACKGROUND: Self = Self::new(Self::INPUT.value - 1);
pub const CONTEXT_IDLE: Self = Self::new(Self::BACKGROUND.value - 1);
pub const APPLICATION_IDLE: Self = Self::new(Self::CONTEXT_IDLE.value - 1);
pub const SYSTEM_IDLE: Self = Self::new(Self::APPLICATION_IDLE.value - 1);
pub(crate) const MINIMUM_ACTIVE_VALUE: Self = Self::new(Self::SYSTEM_IDLE.value);
pub const INACTIVE: Self = Self::new(Self::MINIMUM_ACTIVE_VALUE.value - 1);
pub(crate) const MIN_VALUE: Self = Self::new(Self::INACTIVE.value);
pub const INVALID: Self = Self::new(Self::MINIMUM_ACTIVE_VALUE.value - 2);
pub const LOADED: Self = Self::new(Self::DEFAULT.value + 1);
pub const UI_THREAD_RENDER: Self = Self::new(Self::LOADED.value + 1);
pub const AFTER_RENDER: Self = Self::new(Self::UI_THREAD_RENDER.value + 1);
pub const RENDER: Self = Self::new(Self::AFTER_RENDER.value + 1);
pub const BEFORE_RENDER: Self = Self::new(Self::RENDER.value + 1);
pub const ASYNC_RENDER_TARGET_RESIZE: Self = Self::new(Self::BEFORE_RENDER.value + 1);
#[deprecated(note = "WPF compatibility")]
pub const DATA_BIND: Self = Self::new(Self::ASYNC_RENDER_TARGET_RESIZE.value + 1);
pub const NORMAL: Self = Self::new(Self::ASYNC_RENDER_TARGET_RESIZE.value + 2);
pub const SEND: Self = Self::new(Self::NORMAL.value + 1);
pub const MAX_VALUE: Self = Self::SEND;
pub fn from_value(value: i32) -> Self {
match Self::try_from(value) {
Ok(priority) => priority,
Err(_) => panic!("value: specified argument was out of the range of valid values"),
}
}
pub fn validate(priority: DispatcherPriority, parameter_name: &str) {
if priority < Self::INACTIVE || priority > Self::MAX_VALUE {
panic!("Invalid DispatcherPriority value (parameter '{parameter_name}')");
}
}
}
impl Default for DispatcherPriority {
fn default() -> Self {
Self::DEFAULT
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct DispatcherPriorityOutOfRangeError(pub i32);
impl fmt::Display for DispatcherPriorityOutOfRangeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} is not a valid dispatcher priority", self.0)
}
}
impl std::error::Error for DispatcherPriorityOutOfRangeError {}
impl TryFrom<i32> for DispatcherPriority {
type Error = DispatcherPriorityOutOfRangeError;
fn try_from(value: i32) -> Result<Self, Self::Error> {
if !(Self::MIN_VALUE.value..=Self::MAX_VALUE.value).contains(&value) {
Err(DispatcherPriorityOutOfRangeError(value))
} else {
Ok(Self::new(value))
}
}
}
impl From<DispatcherPriority> for i32 {
fn from(priority: DispatcherPriority) -> i32 {
priority.value
}
}
#[allow(deprecated)]
impl fmt::Display for DispatcherPriority {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let name = match *self {
Self::INVALID => "Invalid",
Self::INACTIVE => "Inactive",
Self::SYSTEM_IDLE => "SystemIdle",
Self::CONTEXT_IDLE => "ContextIdle",
Self::APPLICATION_IDLE => "ApplicationIdle",
Self::BACKGROUND => "Background",
Self::INPUT => "Input",
Self::DEFAULT => "Default",
Self::LOADED => "Loaded",
Self::UI_THREAD_RENDER => "UiThreadRender",
Self::AFTER_RENDER => "AfterRender",
Self::RENDER => "Render",
Self::BEFORE_RENDER => "BeforeRender",
Self::ASYNC_RENDER_TARGET_RESIZE => "AsyncRenderTargetResize",
Self::DATA_BIND => "DataBind",
Self::NORMAL => "Normal",
Self::SEND => "Send",
_ => return write!(f, "{}", self.value),
};
f.write_str(name)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[allow(deprecated)]
fn values_match_the_documented_ordering() {
assert_eq!(DispatcherPriority::INVALID.value(), -7);
assert_eq!(DispatcherPriority::INACTIVE.value(), -6);
assert_eq!(DispatcherPriority::SYSTEM_IDLE.value(), -5);
assert_eq!(DispatcherPriority::APPLICATION_IDLE.value(), -4);
assert_eq!(DispatcherPriority::CONTEXT_IDLE.value(), -3);
assert_eq!(DispatcherPriority::BACKGROUND.value(), -2);
assert_eq!(DispatcherPriority::INPUT.value(), -1);
assert_eq!(DispatcherPriority::DEFAULT.value(), 0);
assert_eq!(DispatcherPriority::LOADED.value(), 1);
assert_eq!(DispatcherPriority::UI_THREAD_RENDER.value(), 2);
assert_eq!(DispatcherPriority::AFTER_RENDER.value(), 3);
assert_eq!(DispatcherPriority::RENDER.value(), 4);
assert_eq!(DispatcherPriority::BEFORE_RENDER.value(), 5);
assert_eq!(DispatcherPriority::ASYNC_RENDER_TARGET_RESIZE.value(), 6);
assert_eq!(DispatcherPriority::DATA_BIND.value(), 7);
assert_eq!(DispatcherPriority::NORMAL.value(), 8);
assert_eq!(DispatcherPriority::SEND.value(), 9);
assert_eq!(DispatcherPriority::default(), DispatcherPriority::DEFAULT);
assert!(DispatcherPriority::RENDER > DispatcherPriority::INPUT);
}
#[test]
fn from_value_validates_the_range() {
assert_eq!(DispatcherPriority::try_from(4), Ok(DispatcherPriority::RENDER));
assert!(DispatcherPriority::try_from(-7).is_err());
assert!(DispatcherPriority::try_from(10).is_err());
assert_eq!(i32::from(DispatcherPriority::SEND), 9);
}
#[test]
fn display_uses_the_priority_name() {
assert_eq!(DispatcherPriority::RENDER.to_string(), "Render");
assert_eq!(DispatcherPriority::INVALID.to_string(), "Invalid");
assert_eq!(DispatcherPriority::UI_THREAD_RENDER.to_string(), "UiThreadRender");
}
#[test]
#[should_panic(expected = "Invalid DispatcherPriority value")]
fn validate_rejects_invalid() {
DispatcherPriority::validate(DispatcherPriority::INVALID, "priority");
}
}