#![no_std]
pub mod result;
use result::Result;
pub unsafe trait ExceptionNumber: Copy {
const MAX_EXCEPTION_NUMBER: usize;
fn number(self) -> usize;
fn from_number(value: usize) -> Result<Self>;
}
pub unsafe trait InterruptNumber: Copy {
const MAX_INTERRUPT_NUMBER: usize;
fn number(self) -> usize;
fn from_number(value: usize) -> Result<Self>;
}
pub unsafe trait CoreInterruptNumber: InterruptNumber {}
pub unsafe trait ExternalInterruptNumber: InterruptNumber {}
pub unsafe trait PriorityNumber: Copy {
const MAX_PRIORITY_NUMBER: usize;
fn number(self) -> usize;
fn from_number(value: usize) -> Result<Self>;
}
pub unsafe trait HartIdNumber: Copy {
const MAX_HART_ID_NUMBER: usize;
fn number(self) -> usize;
fn from_number(value: usize) -> Result<Self>;
}
#[cfg(test)]
mod test {
use super::*;
use crate::result::Error;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum Exception {
E1 = 1,
E3 = 3,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum Interrupt {
I1 = 1,
I2 = 2,
I4 = 4,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum Priority {
P0 = 0,
P1 = 1,
P2 = 2,
P3 = 3,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum HartId {
H0 = 0,
H1 = 1,
H2 = 2,
}
unsafe impl ExceptionNumber for Exception {
const MAX_EXCEPTION_NUMBER: usize = Self::E3 as usize;
#[inline]
fn number(self) -> usize {
self as _
}
#[inline]
fn from_number(number: usize) -> Result<Self> {
match number {
1 => Ok(Exception::E1),
3 => Ok(Exception::E3),
_ => Err(Error::InvalidVariant(number)),
}
}
}
unsafe impl InterruptNumber for Interrupt {
const MAX_INTERRUPT_NUMBER: usize = Self::I4 as usize;
#[inline]
fn number(self) -> usize {
self as _
}
#[inline]
fn from_number(number: usize) -> Result<Self> {
match number {
1 => Ok(Interrupt::I1),
2 => Ok(Interrupt::I2),
4 => Ok(Interrupt::I4),
_ => Err(Error::InvalidVariant(number)),
}
}
}
unsafe impl PriorityNumber for Priority {
const MAX_PRIORITY_NUMBER: usize = Self::P3 as usize;
#[inline]
fn number(self) -> usize {
self as _
}
#[inline]
fn from_number(number: usize) -> Result<Self> {
match number {
0 => Ok(Priority::P0),
1 => Ok(Priority::P1),
2 => Ok(Priority::P2),
3 => Ok(Priority::P3),
_ => Err(Error::InvalidVariant(number)),
}
}
}
unsafe impl HartIdNumber for HartId {
const MAX_HART_ID_NUMBER: usize = Self::H2 as usize;
#[inline]
fn number(self) -> usize {
self as _
}
#[inline]
fn from_number(number: usize) -> Result<Self> {
match number {
0 => Ok(HartId::H0),
1 => Ok(HartId::H1),
2 => Ok(HartId::H2),
_ => Err(Error::InvalidVariant(number)),
}
}
}
#[test]
fn check_exception_enum() {
assert_eq!(Exception::E1.number(), 1);
assert_eq!(Exception::E3.number(), 3);
assert_eq!(Exception::from_number(0), Err(Error::InvalidVariant(0)));
assert_eq!(Exception::from_number(1), Ok(Exception::E1));
assert_eq!(Exception::from_number(2), Err(Error::InvalidVariant(2)));
assert_eq!(Exception::from_number(3), Ok(Exception::E3));
assert_eq!(Exception::from_number(4), Err(Error::InvalidVariant(4)));
}
#[test]
fn check_interrupt_enum() {
assert_eq!(Interrupt::I1.number(), 1);
assert_eq!(Interrupt::I2.number(), 2);
assert_eq!(Interrupt::I4.number(), 4);
assert_eq!(Interrupt::from_number(0), Err(Error::InvalidVariant(0)));
assert_eq!(Interrupt::from_number(1), Ok(Interrupt::I1));
assert_eq!(Interrupt::from_number(2), Ok(Interrupt::I2));
assert_eq!(Interrupt::from_number(3), Err(Error::InvalidVariant(3)));
assert_eq!(Interrupt::from_number(4), Ok(Interrupt::I4));
assert_eq!(Interrupt::from_number(5), Err(Error::InvalidVariant(5)));
}
#[test]
fn check_priority_enum() {
assert_eq!(Priority::P0.number(), 0);
assert_eq!(Priority::P1.number(), 1);
assert_eq!(Priority::P2.number(), 2);
assert_eq!(Priority::P3.number(), 3);
assert_eq!(Priority::from_number(0), Ok(Priority::P0));
assert_eq!(Priority::from_number(1), Ok(Priority::P1));
assert_eq!(Priority::from_number(2), Ok(Priority::P2));
assert_eq!(Priority::from_number(3), Ok(Priority::P3));
assert_eq!(Priority::from_number(4), Err(Error::InvalidVariant(4)));
}
#[test]
fn check_hart_id_enum() {
assert_eq!(HartId::H0.number(), 0);
assert_eq!(HartId::H1.number(), 1);
assert_eq!(HartId::H2.number(), 2);
assert_eq!(HartId::from_number(0), Ok(HartId::H0));
assert_eq!(HartId::from_number(1), Ok(HartId::H1));
assert_eq!(HartId::from_number(2), Ok(HartId::H2));
assert_eq!(HartId::from_number(3), Err(Error::InvalidVariant(3)));
}
}