-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Difference between num_enum and num_derive ? #61
Comments
That's a great question - thanks for asking! These two crates do indeed do similar things, but there's a key difference between them:
#[repr(u16)]
enum Number {
Zero,
One,
} Without any third-party crates, we can trivially convert this enum to a assert_eq!(Number::Zero as u16, 0_u16) But there's nothing special about assert_eq!(Number::Zero as u8, 0_u8) It's less trivial to convert a let number = match 0_u16 {
0_u16 => Number::Zero,
1_u16 => Number::One,
_ => // Up to you what to do here
} That's our base-line :) So, let's talk about what these two crates do to try to make this better!
|
Thank you for sharing such insights. Got to learn a lot. For my use case, where I am writing a proc macro pub enum ServerGreetingMode {
Unavailable = 0,
Unauthenticated = 1,
Authenticated = 2,
Encrypted = 4,
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::marker::Copy for ServerGreetingMode {}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::core::clone::Clone for ServerGreetingMode {
#[inline]
fn clone(&self) -> ServerGreetingMode {
{
*self
}
}
}
#[allow(non_upper_case_globals, unused_qualifications)]
const _IMPL_NUM_FromPrimitive_FOR_ServerGreetingMode: () = {
#[allow(clippy::useless_attribute)]
#[allow(rust_2018_idioms)]
extern crate num_traits as _num_traits;
impl _num_traits::FromPrimitive for ServerGreetingMode {
#[allow(trivial_numeric_casts)]
#[inline]
fn from_i64(n: i64) -> Option<Self> {
if n == ServerGreetingMode::Unavailable as i64 {
Some(ServerGreetingMode::Unavailable)
} else if n == ServerGreetingMode::Unauthenticated as i64 {
Some(ServerGreetingMode::Unauthenticated)
} else if n == ServerGreetingMode::Authenticated as i64 {
Some(ServerGreetingMode::Authenticated)
} else if n == ServerGreetingMode::Encrypted as i64 {
Some(ServerGreetingMode::Encrypted)
} else {
None
}
}
#[inline]
fn from_u64(n: u64) -> Option<Self> {
Self::from_i64(n as i64)
}
}
};
pub struct ServerGreetingFrame {
pub unused: [u8; 12],
#[byte_it(u32)]
pub mode: ServerGreetingMode,
pub challenge: [u8; 16],
pub salt: [u8; 16],
pub count: u128,
pub mbz: [u8; 12],
}
impl ServerGreetingFrame {
const SIZE: usize = 76usize;
/// Convert the struct to a byte array.
pub fn to_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
bytes.extend_from_slice(&(self.unused));
bytes.extend_from_slice(&(self.mode as u32).to_be_bytes().to_vec());
bytes.extend_from_slice(&(self.challenge));
bytes.extend_from_slice(&(self.salt));
bytes.extend_from_slice(&(self.count as u128).to_be_bytes().to_vec());
bytes.extend_from_slice(&(self.mbz));
bytes
}
/// Convert the byte array to a struct.
pub fn from_bytes(bytes: Vec<u8>) -> Self {
let unused: [u8; 12usize] = bytes[0usize..12usize].try_into().unwrap();
let mode: [u8; 4usize] = bytes[12usize..16usize].try_into().unwrap();
let mode = u32::from_be_bytes(mode);
let mode = ServerGreetingMode::from_u32(mode).unwrap();
let challenge: [u8; 16usize] = bytes[16usize..32usize].try_into().unwrap();
let salt: [u8; 16usize] = bytes[32usize..48usize].try_into().unwrap();
let count: [u8; 16usize] = bytes[48usize..64usize].try_into().unwrap();
let count = u128::from_be_bytes(count);
let mbz: [u8; 12usize] = bytes[64usize..76usize].try_into().unwrap();
Self {
unused,
mode,
challenge,
salt,
count,
mbz,
}
}
} Inspecting the output again, especially on the trait implementation on the enum, I can see the merits of using So far in my code, I haven't felt the need to use Thankyou again. |
Sounds good - glad it was useful! I'm going to close this issue, as I think it's resolved, but feel free to reply to it again if you have any thoughts/ideas/questions! :) |
First of all, thankyou for your efforts.
It appears that both the
num-derive
andnum-enum
crate provides the same functionality. What is the motivation behind this crate?The text was updated successfully, but these errors were encountered: