use core::{
convert::Infallible,
fmt,
num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroUsize},
};
use atomig::{Atom, impls::PrimitiveAtom};
pub trait Task {
type Priority: TaskPriority;
fn priority(&self) -> Self::Priority;
}
impl Task for Infallible {
type Priority = Infallible;
fn priority(&self) -> Self::Priority {
match *self {}
}
}
impl Task for () {
type Priority = ();
fn priority(&self) -> Self::Priority {}
}
pub unsafe trait TaskPriority: Copy + Ord + fmt::Debug {
type Repr: Atom + PrimitiveAtom;
const TRIVIAL: bool = false;
fn pack(priority: Option<Self>) -> Self::Repr;
fn unpack(repr: Self::Repr) -> Option<Self>;
}
unsafe impl TaskPriority for Infallible {
type Repr = u8;
fn pack(priority: Option<Self>) -> Self::Repr {
let None = priority;
0u8
}
fn unpack(repr: Self::Repr) -> Option<Self> {
assert_eq!(repr, 0u8);
None
}
}
unsafe impl TaskPriority for () {
type Repr = bool;
const TRIVIAL: bool = true;
fn pack(priority: Option<Self>) -> Self::Repr {
match priority {
Some(()) => true,
None => false,
}
}
fn unpack(repr: Self::Repr) -> Option<Self> {
match repr {
true => Some(()),
false => None,
}
}
}
unsafe impl TaskPriority for NonZeroU8 {
type Repr = u8;
fn pack(priority: Option<Self>) -> Self::Repr {
priority.map_or(0, NonZeroU8::get)
}
fn unpack(repr: Self::Repr) -> Option<Self> {
NonZeroU8::new(repr)
}
}
unsafe impl TaskPriority for NonZeroU16 {
type Repr = u16;
fn pack(priority: Option<Self>) -> Self::Repr {
priority.map_or(0, NonZeroU16::get)
}
fn unpack(repr: Self::Repr) -> Option<Self> {
NonZeroU16::new(repr)
}
}
unsafe impl TaskPriority for NonZeroU32 {
type Repr = u32;
fn pack(priority: Option<Self>) -> Self::Repr {
priority.map_or(0, NonZeroU32::get)
}
fn unpack(repr: Self::Repr) -> Option<Self> {
NonZeroU32::new(repr)
}
}
unsafe impl TaskPriority for NonZeroU64 {
type Repr = u64;
fn pack(priority: Option<Self>) -> Self::Repr {
priority.map_or(0, NonZeroU64::get)
}
fn unpack(repr: Self::Repr) -> Option<Self> {
NonZeroU64::new(repr)
}
}
unsafe impl TaskPriority for NonZeroUsize {
type Repr = usize;
fn pack(priority: Option<Self>) -> Self::Repr {
priority.map_or(0, NonZeroUsize::get)
}
fn unpack(repr: Self::Repr) -> Option<Self> {
NonZeroUsize::new(repr)
}
}