Skip to content

Commit

Permalink
Add a FromStr impl to the xed_enum! macro
Browse files Browse the repository at this point in the history
  • Loading branch information
Phantomical committed Feb 21, 2024
1 parent 8b9b522 commit 3845a69
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 7 deletions.
14 changes: 7 additions & 7 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,17 +83,17 @@ impl std::error::Error for Error {}

/// Error for when converting an integer to an enum fails.
#[derive(Copy, Clone, Debug)]
pub struct InvalidEnumValue {
value: u32,
pub struct InvalidEnumValue<T = u32> {
value: T,
name: &'static str,
}

impl InvalidEnumValue {
pub(crate) fn new(value: u32, name: &'static str) -> Self {
impl<T> InvalidEnumValue<T> {
pub(crate) fn new(value: T, name: &'static str) -> Self {
Self { value, name }
}

pub fn value(self) -> u32 {
pub fn value(self) -> T {
self.value
}

Expand All @@ -102,13 +102,13 @@ impl InvalidEnumValue {
}
}

impl fmt::Display for InvalidEnumValue {
impl<T: fmt::Debug> fmt::Display for InvalidEnumValue<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?} is not a valid value for {}", self.value, self.name)
}
}

impl std::error::Error for InvalidEnumValue {}
impl<T: fmt::Debug> std::error::Error for InvalidEnumValue<T> {}

// #[derive(Copy, Clone, Debug)]
// pub struct DisassembleError(());
Expand Down
33 changes: 33 additions & 0 deletions src/macros/xed_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,39 @@ macro_rules! xed_enum {
}
}

impl std::str::FromStr for $name {
type Err = crate::InvalidEnumValue<String>;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut owned = String::with_capacity(s.len() + 1);
owned.push_str(s);
owned.push('\0');

let cstr = match std::ffi::CStr::from_bytes_with_nul(owned.as_bytes()) {
Ok(cstr) => cstr,
Err(_) => {
owned.pop();
return Err(crate::InvalidEnumValue::new(owned, stringify!($name)));
}
};

let variant = unsafe {
paste::paste!($crate::macros::first!(
$( [ xed_sys::[< str2 $enum_name >](cstr.as_ptr()) ] )?
[ xed_sys::[< str2 $base:lower _enum_t >](cstr.as_ptr()) ]
))
};

match Self::from_raw(variant) {
Some(value) => Ok(value),
None => {
owned.pop();
Err(crate::InvalidEnumValue::new(owned, stringify!($name)))
}
}
}
}

paste::paste! {
#[test]
fn [< $name:snake:lower _up_to_date >]() {
Expand Down

0 comments on commit 3845a69

Please sign in to comment.