#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[repr(transparent)]
pub struct CpuIndex(u32);
impl CpuIndex {
pub const INVALID_RAW: u32 = u32::MAX;
pub const fn from_u32(index: u32) -> Option<Self> {
if index == Self::INVALID_RAW {
None
} else {
Some(Self(index))
}
}
pub const fn as_u32(self) -> u32 {
self.0
}
pub const fn as_usize(self) -> usize {
self.0 as usize
}
}
impl TryFrom<usize> for CpuIndex {
type Error = CpuIndexError;
fn try_from(index: usize) -> Result<Self, Self::Error> {
let raw = u32::try_from(index).map_err(|_| CpuIndexError { index })?;
Self::from_u32(raw).ok_or(CpuIndexError { index })
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, thiserror::Error)]
#[error("CPU index {index} exceeds the CPU-local index range")]
pub struct CpuIndexError {
index: usize,
}
impl CpuIndexError {
pub const fn index(self) -> usize {
self.index
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn cpu_index_reserves_the_invalid_header_value() {
assert_eq!(CpuIndex::try_from(7).unwrap().as_u32(), 7);
assert!(CpuIndex::from_u32(CpuIndex::INVALID_RAW).is_none());
}
}