Skip to content

Commit

Permalink
add ConstDefault
Browse files Browse the repository at this point in the history
  • Loading branch information
cosmicexplorer committed May 3, 2024
1 parent 5ac2ed7 commit 88ce96f
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 2 deletions.
4 changes: 2 additions & 2 deletions num_enum/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
#![cfg_attr(not(feature = "std"), no_std)]

pub use ::num_enum_derive::{
ConstFromPrimitive, ConstIntoPrimitive, ConstTryFromPrimitive, Default, FromPrimitive,
IntoPrimitive, TryFromPrimitive, UnsafeFromPrimitive,
ConstDefault, ConstFromPrimitive, ConstIntoPrimitive, ConstTryFromPrimitive, Default,
FromPrimitive, IntoPrimitive, TryFromPrimitive, UnsafeFromPrimitive,
};

use ::core::fmt;
Expand Down
37 changes: 37 additions & 0 deletions num_enum/tests/const_default.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#![allow(non_upper_case_globals)]

// Guard against https://github.com/illicitonion/num_enum/issues/27
mod alloc {}
mod core {}
mod num_enum {}
mod std {}

#[test]
fn default() {
#[derive(Debug, Eq, PartialEq, ::num_enum::ConstDefault)]
#[repr(u8)]
enum Enum {
#[allow(unused)]
Zero = 0,
#[num_enum(default)]
NonZero = 1,
}

const nz: Enum = Enum::const_default();
assert_eq!(Enum::NonZero, nz);
}

#[test]
fn default_standard_default_attribute() {
#[derive(Debug, Eq, PartialEq, ::num_enum::ConstDefault)]
#[repr(u8)]
enum Enum {
#[allow(unused)]
Zero = 0,
#[default]
NonZero = 1,
}

const nz: Enum = Enum::const_default();
assert_eq!(Enum::NonZero, nz);
}
44 changes: 44 additions & 0 deletions num_enum_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -588,3 +588,47 @@ pub fn derive_default(stream: TokenStream) -> TokenStream {
}
})
}

/// Generates a `const_default() -> Self` method to obtain the default enum value in const contexts.
///
/// Whichever variant has the `#[default]` or `#[num_enum(default)]` attribute will be returned.
/// ----------------------------------------------
///
/// ```rust
/// #[derive(Debug, Eq, PartialEq, num_enum::ConstDefault)]
/// #[repr(u8)]
/// enum Number {
/// Zero,
/// #[default]
/// One,
/// }
///
/// const one: Number = Number::const_default();
/// assert_eq!(one, Number::One);
/// assert_eq!(Number::One, Number::const_default());
/// ```
#[proc_macro_derive(ConstDefault, attributes(num_enum, default))]
pub fn derive_const_default(stream: TokenStream) -> TokenStream {
let enum_info = parse_macro_input!(stream as EnumInfo);

let default_ident = match enum_info.default() {
Some(ident) => ident,
None => {
let span = Span::call_site();
let message =
"#[derive(num_enum::ConstDefault)] requires enum to be exhaustive, or a variant marked with `#[default]` or `#[num_enum(default)]`";
return syn::Error::new(span, message).to_compile_error().into();
}
};

let EnumInfo { ref name, .. } = enum_info;

TokenStream::from(quote! {
impl #name {
#[inline]
pub const fn const_default() -> Self {
Self::#default_ident
}
}
})
}

0 comments on commit 88ce96f

Please sign in to comment.