macros: Derive macro to generate integer to enum conversion
This CL adds a procedural macro to generate functions for converting a
primitive integer into the corresponding variant of an enum.
Loosely based on https://docs.rs/enum-primitive-derive but implemented
against a newer version of Syn and without the dependency on num-traits.
The generated function is named `n` and has the following signature:
impl YourEnum {
pub fn n(value: Repr) -> Option<Self>;
}
where `Repr` is an integer type of the right size as described in more
detail below.
EXAMPLE
extern crate enumn;
#[derive(PartialEq, Debug, enumn::N)]
enum Status {
LegendaryTriumph,
QualifiedSuccess,
FortuitousRevival,
IndeterminateStalemate,
RecoverableSetback,
DireMisadventure,
AbjectFailure,
}
fn main() {
let s = Status::n(1);
assert_eq!(s, Some(Status::QualifiedSuccess));
let s = Status::n(9);
assert_eq!(s, None);
}
SIGNATURE
The generated signature depends on whether the enum has a `#[repr(..)]`
attribute. If a `repr` is specified, the input to `n` will be required
to be of that type.
#[derive(enumn::N)]
#[repr(u8)]
enum E {
/* ... */
}
// expands to:
impl E {
pub fn n(value: u8) -> Option<Self> {
/* ... */
}
}
On the other hand if no `repr` is specified then we get a signature that
is generic over a variety of possible types.
impl E {
pub fn n<REPR: Into<i64>>(value: REPR) -> Option<Self> {
/* ... */
}
}
DISCRIMINANTS
The conversion respects explictly specified enum discriminants. Consider
this enum:
#[derive(enumn::N)]
enum Letter {
A = 65,
B = 66,
}
Here `Letter::n(65)` would return `Some(Letter::A)`.
TEST=`cargo test` against the new crate
Change-Id: I4286a816828c83507b35185fe497455ee30ae9e8
Reviewed-on: https://chromium-review.googlesource.com/1365114
Commit-Ready: David Tolnay <dtolnay@chromium.org>
Tested-by: David Tolnay <dtolnay@chromium.org>
Reviewed-by: Chirantan Ekbote <chirantan@chromium.org>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
2018-12-06 09:58:21 +00:00
|
|
|
// Copyright 2018 The Chromium OS Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
|
|
|
//! Convert number to enum.
|
|
|
|
//!
|
|
|
|
//! This crate provides a derive macro to generate a function for converting a
|
|
|
|
//! primitive integer into the corresponding variant of an enum.
|
|
|
|
//!
|
|
|
|
//! The generated function is named `n` and has the following signature:
|
|
|
|
//!
|
|
|
|
//! ```rust
|
|
|
|
//! # const IGNORE: &str = stringify! {
|
|
|
|
//! impl YourEnum {
|
|
|
|
//! pub fn n(value: Repr) -> Option<Self>;
|
|
|
|
//! }
|
|
|
|
//! # };
|
|
|
|
//! ```
|
|
|
|
//!
|
|
|
|
//! where `Repr` is an integer type of the right size as described in more
|
|
|
|
//! detail below.
|
|
|
|
//!
|
|
|
|
//! # Example
|
|
|
|
//!
|
|
|
|
//! ```rust
|
2019-04-12 19:18:35 +00:00
|
|
|
//! use enumn::N;
|
macros: Derive macro to generate integer to enum conversion
This CL adds a procedural macro to generate functions for converting a
primitive integer into the corresponding variant of an enum.
Loosely based on https://docs.rs/enum-primitive-derive but implemented
against a newer version of Syn and without the dependency on num-traits.
The generated function is named `n` and has the following signature:
impl YourEnum {
pub fn n(value: Repr) -> Option<Self>;
}
where `Repr` is an integer type of the right size as described in more
detail below.
EXAMPLE
extern crate enumn;
#[derive(PartialEq, Debug, enumn::N)]
enum Status {
LegendaryTriumph,
QualifiedSuccess,
FortuitousRevival,
IndeterminateStalemate,
RecoverableSetback,
DireMisadventure,
AbjectFailure,
}
fn main() {
let s = Status::n(1);
assert_eq!(s, Some(Status::QualifiedSuccess));
let s = Status::n(9);
assert_eq!(s, None);
}
SIGNATURE
The generated signature depends on whether the enum has a `#[repr(..)]`
attribute. If a `repr` is specified, the input to `n` will be required
to be of that type.
#[derive(enumn::N)]
#[repr(u8)]
enum E {
/* ... */
}
// expands to:
impl E {
pub fn n(value: u8) -> Option<Self> {
/* ... */
}
}
On the other hand if no `repr` is specified then we get a signature that
is generic over a variety of possible types.
impl E {
pub fn n<REPR: Into<i64>>(value: REPR) -> Option<Self> {
/* ... */
}
}
DISCRIMINANTS
The conversion respects explictly specified enum discriminants. Consider
this enum:
#[derive(enumn::N)]
enum Letter {
A = 65,
B = 66,
}
Here `Letter::n(65)` would return `Some(Letter::A)`.
TEST=`cargo test` against the new crate
Change-Id: I4286a816828c83507b35185fe497455ee30ae9e8
Reviewed-on: https://chromium-review.googlesource.com/1365114
Commit-Ready: David Tolnay <dtolnay@chromium.org>
Tested-by: David Tolnay <dtolnay@chromium.org>
Reviewed-by: Chirantan Ekbote <chirantan@chromium.org>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
2018-12-06 09:58:21 +00:00
|
|
|
//!
|
2019-04-12 19:18:35 +00:00
|
|
|
//! #[derive(PartialEq, Debug, N)]
|
macros: Derive macro to generate integer to enum conversion
This CL adds a procedural macro to generate functions for converting a
primitive integer into the corresponding variant of an enum.
Loosely based on https://docs.rs/enum-primitive-derive but implemented
against a newer version of Syn and without the dependency on num-traits.
The generated function is named `n` and has the following signature:
impl YourEnum {
pub fn n(value: Repr) -> Option<Self>;
}
where `Repr` is an integer type of the right size as described in more
detail below.
EXAMPLE
extern crate enumn;
#[derive(PartialEq, Debug, enumn::N)]
enum Status {
LegendaryTriumph,
QualifiedSuccess,
FortuitousRevival,
IndeterminateStalemate,
RecoverableSetback,
DireMisadventure,
AbjectFailure,
}
fn main() {
let s = Status::n(1);
assert_eq!(s, Some(Status::QualifiedSuccess));
let s = Status::n(9);
assert_eq!(s, None);
}
SIGNATURE
The generated signature depends on whether the enum has a `#[repr(..)]`
attribute. If a `repr` is specified, the input to `n` will be required
to be of that type.
#[derive(enumn::N)]
#[repr(u8)]
enum E {
/* ... */
}
// expands to:
impl E {
pub fn n(value: u8) -> Option<Self> {
/* ... */
}
}
On the other hand if no `repr` is specified then we get a signature that
is generic over a variety of possible types.
impl E {
pub fn n<REPR: Into<i64>>(value: REPR) -> Option<Self> {
/* ... */
}
}
DISCRIMINANTS
The conversion respects explictly specified enum discriminants. Consider
this enum:
#[derive(enumn::N)]
enum Letter {
A = 65,
B = 66,
}
Here `Letter::n(65)` would return `Some(Letter::A)`.
TEST=`cargo test` against the new crate
Change-Id: I4286a816828c83507b35185fe497455ee30ae9e8
Reviewed-on: https://chromium-review.googlesource.com/1365114
Commit-Ready: David Tolnay <dtolnay@chromium.org>
Tested-by: David Tolnay <dtolnay@chromium.org>
Reviewed-by: Chirantan Ekbote <chirantan@chromium.org>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
2018-12-06 09:58:21 +00:00
|
|
|
//! enum Status {
|
|
|
|
//! LegendaryTriumph,
|
|
|
|
//! QualifiedSuccess,
|
|
|
|
//! FortuitousRevival,
|
|
|
|
//! IndeterminateStalemate,
|
|
|
|
//! RecoverableSetback,
|
|
|
|
//! DireMisadventure,
|
|
|
|
//! AbjectFailure,
|
|
|
|
//! }
|
|
|
|
//!
|
|
|
|
//! fn main() {
|
|
|
|
//! let s = Status::n(1);
|
|
|
|
//! assert_eq!(s, Some(Status::QualifiedSuccess));
|
|
|
|
//!
|
|
|
|
//! let s = Status::n(9);
|
|
|
|
//! assert_eq!(s, None);
|
|
|
|
//! }
|
|
|
|
//! ```
|
|
|
|
//!
|
|
|
|
//! # Signature
|
|
|
|
//!
|
|
|
|
//! The generated signature depends on whether the enum has a `#[repr(..)]`
|
|
|
|
//! attribute. If a `repr` is specified, the input to `n` will be required to be
|
|
|
|
//! of that type.
|
|
|
|
//!
|
2019-05-28 17:25:25 +00:00
|
|
|
//! ```ignore
|
2019-04-12 19:18:35 +00:00
|
|
|
//! use enumn::N;
|
|
|
|
//!
|
|
|
|
//! #[derive(N)]
|
macros: Derive macro to generate integer to enum conversion
This CL adds a procedural macro to generate functions for converting a
primitive integer into the corresponding variant of an enum.
Loosely based on https://docs.rs/enum-primitive-derive but implemented
against a newer version of Syn and without the dependency on num-traits.
The generated function is named `n` and has the following signature:
impl YourEnum {
pub fn n(value: Repr) -> Option<Self>;
}
where `Repr` is an integer type of the right size as described in more
detail below.
EXAMPLE
extern crate enumn;
#[derive(PartialEq, Debug, enumn::N)]
enum Status {
LegendaryTriumph,
QualifiedSuccess,
FortuitousRevival,
IndeterminateStalemate,
RecoverableSetback,
DireMisadventure,
AbjectFailure,
}
fn main() {
let s = Status::n(1);
assert_eq!(s, Some(Status::QualifiedSuccess));
let s = Status::n(9);
assert_eq!(s, None);
}
SIGNATURE
The generated signature depends on whether the enum has a `#[repr(..)]`
attribute. If a `repr` is specified, the input to `n` will be required
to be of that type.
#[derive(enumn::N)]
#[repr(u8)]
enum E {
/* ... */
}
// expands to:
impl E {
pub fn n(value: u8) -> Option<Self> {
/* ... */
}
}
On the other hand if no `repr` is specified then we get a signature that
is generic over a variety of possible types.
impl E {
pub fn n<REPR: Into<i64>>(value: REPR) -> Option<Self> {
/* ... */
}
}
DISCRIMINANTS
The conversion respects explictly specified enum discriminants. Consider
this enum:
#[derive(enumn::N)]
enum Letter {
A = 65,
B = 66,
}
Here `Letter::n(65)` would return `Some(Letter::A)`.
TEST=`cargo test` against the new crate
Change-Id: I4286a816828c83507b35185fe497455ee30ae9e8
Reviewed-on: https://chromium-review.googlesource.com/1365114
Commit-Ready: David Tolnay <dtolnay@chromium.org>
Tested-by: David Tolnay <dtolnay@chromium.org>
Reviewed-by: Chirantan Ekbote <chirantan@chromium.org>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
2018-12-06 09:58:21 +00:00
|
|
|
//! #[repr(u8)]
|
|
|
|
//! enum E {
|
|
|
|
//! /* ... */
|
|
|
|
//! # IGNORE
|
|
|
|
//! }
|
|
|
|
//!
|
|
|
|
//! // expands to:
|
|
|
|
//! impl E {
|
|
|
|
//! pub fn n(value: u8) -> Option<Self> {
|
|
|
|
//! /* ... */
|
|
|
|
//! # unimplemented!()
|
|
|
|
//! }
|
|
|
|
//! }
|
|
|
|
//! ```
|
|
|
|
//!
|
|
|
|
//! On the other hand if no `repr` is specified then we get a signature that is
|
|
|
|
//! generic over a variety of possible types.
|
|
|
|
//!
|
2019-05-28 17:25:25 +00:00
|
|
|
//! ```ignore
|
macros: Derive macro to generate integer to enum conversion
This CL adds a procedural macro to generate functions for converting a
primitive integer into the corresponding variant of an enum.
Loosely based on https://docs.rs/enum-primitive-derive but implemented
against a newer version of Syn and without the dependency on num-traits.
The generated function is named `n` and has the following signature:
impl YourEnum {
pub fn n(value: Repr) -> Option<Self>;
}
where `Repr` is an integer type of the right size as described in more
detail below.
EXAMPLE
extern crate enumn;
#[derive(PartialEq, Debug, enumn::N)]
enum Status {
LegendaryTriumph,
QualifiedSuccess,
FortuitousRevival,
IndeterminateStalemate,
RecoverableSetback,
DireMisadventure,
AbjectFailure,
}
fn main() {
let s = Status::n(1);
assert_eq!(s, Some(Status::QualifiedSuccess));
let s = Status::n(9);
assert_eq!(s, None);
}
SIGNATURE
The generated signature depends on whether the enum has a `#[repr(..)]`
attribute. If a `repr` is specified, the input to `n` will be required
to be of that type.
#[derive(enumn::N)]
#[repr(u8)]
enum E {
/* ... */
}
// expands to:
impl E {
pub fn n(value: u8) -> Option<Self> {
/* ... */
}
}
On the other hand if no `repr` is specified then we get a signature that
is generic over a variety of possible types.
impl E {
pub fn n<REPR: Into<i64>>(value: REPR) -> Option<Self> {
/* ... */
}
}
DISCRIMINANTS
The conversion respects explictly specified enum discriminants. Consider
this enum:
#[derive(enumn::N)]
enum Letter {
A = 65,
B = 66,
}
Here `Letter::n(65)` would return `Some(Letter::A)`.
TEST=`cargo test` against the new crate
Change-Id: I4286a816828c83507b35185fe497455ee30ae9e8
Reviewed-on: https://chromium-review.googlesource.com/1365114
Commit-Ready: David Tolnay <dtolnay@chromium.org>
Tested-by: David Tolnay <dtolnay@chromium.org>
Reviewed-by: Chirantan Ekbote <chirantan@chromium.org>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
2018-12-06 09:58:21 +00:00
|
|
|
//! # enum E {}
|
|
|
|
//! #
|
|
|
|
//! impl E {
|
|
|
|
//! pub fn n<REPR: Into<i64>>(value: REPR) -> Option<Self> {
|
|
|
|
//! /* ... */
|
|
|
|
//! # unimplemented!()
|
|
|
|
//! }
|
|
|
|
//! }
|
|
|
|
//! ```
|
|
|
|
//!
|
|
|
|
//! # Discriminants
|
|
|
|
//!
|
|
|
|
//! The conversion respects explictly specified enum discriminants. Consider
|
|
|
|
//! this enum:
|
|
|
|
//!
|
|
|
|
//! ```rust
|
2019-04-12 19:18:35 +00:00
|
|
|
//! use enumn::N;
|
|
|
|
//!
|
|
|
|
//! #[derive(N)]
|
macros: Derive macro to generate integer to enum conversion
This CL adds a procedural macro to generate functions for converting a
primitive integer into the corresponding variant of an enum.
Loosely based on https://docs.rs/enum-primitive-derive but implemented
against a newer version of Syn and without the dependency on num-traits.
The generated function is named `n` and has the following signature:
impl YourEnum {
pub fn n(value: Repr) -> Option<Self>;
}
where `Repr` is an integer type of the right size as described in more
detail below.
EXAMPLE
extern crate enumn;
#[derive(PartialEq, Debug, enumn::N)]
enum Status {
LegendaryTriumph,
QualifiedSuccess,
FortuitousRevival,
IndeterminateStalemate,
RecoverableSetback,
DireMisadventure,
AbjectFailure,
}
fn main() {
let s = Status::n(1);
assert_eq!(s, Some(Status::QualifiedSuccess));
let s = Status::n(9);
assert_eq!(s, None);
}
SIGNATURE
The generated signature depends on whether the enum has a `#[repr(..)]`
attribute. If a `repr` is specified, the input to `n` will be required
to be of that type.
#[derive(enumn::N)]
#[repr(u8)]
enum E {
/* ... */
}
// expands to:
impl E {
pub fn n(value: u8) -> Option<Self> {
/* ... */
}
}
On the other hand if no `repr` is specified then we get a signature that
is generic over a variety of possible types.
impl E {
pub fn n<REPR: Into<i64>>(value: REPR) -> Option<Self> {
/* ... */
}
}
DISCRIMINANTS
The conversion respects explictly specified enum discriminants. Consider
this enum:
#[derive(enumn::N)]
enum Letter {
A = 65,
B = 66,
}
Here `Letter::n(65)` would return `Some(Letter::A)`.
TEST=`cargo test` against the new crate
Change-Id: I4286a816828c83507b35185fe497455ee30ae9e8
Reviewed-on: https://chromium-review.googlesource.com/1365114
Commit-Ready: David Tolnay <dtolnay@chromium.org>
Tested-by: David Tolnay <dtolnay@chromium.org>
Reviewed-by: Chirantan Ekbote <chirantan@chromium.org>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
2018-12-06 09:58:21 +00:00
|
|
|
//! enum Letter {
|
|
|
|
//! A = 65,
|
|
|
|
//! B = 66,
|
|
|
|
//! }
|
|
|
|
//! ```
|
|
|
|
//!
|
|
|
|
//! Here `Letter::n(65)` would return `Some(Letter::A)`.
|
|
|
|
|
|
|
|
#![recursion_limit = "128"]
|
|
|
|
|
|
|
|
extern crate proc_macro;
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests;
|
|
|
|
|
|
|
|
use proc_macro::TokenStream;
|
|
|
|
use quote::quote;
|
|
|
|
use syn::parse::Error;
|
|
|
|
use syn::{parse_macro_input, parse_quote, Data, DeriveInput, Fields, Meta, NestedMeta};
|
|
|
|
|
|
|
|
fn testable_derive(input: DeriveInput) -> proc_macro2::TokenStream {
|
|
|
|
let variants = match input.data {
|
|
|
|
Data::Enum(data) => data.variants,
|
|
|
|
Data::Struct(_) | Data::Union(_) => panic!("input must be an enum"),
|
|
|
|
};
|
|
|
|
|
|
|
|
for variant in &variants {
|
|
|
|
match variant.fields {
|
|
|
|
Fields::Unit => {}
|
|
|
|
Fields::Named(_) | Fields::Unnamed(_) => {
|
|
|
|
let span = variant.ident.span();
|
|
|
|
let err = Error::new(span, "enumn: variant with data is not supported");
|
|
|
|
return err.to_compile_error();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse repr attribute like #[repr(u16)].
|
|
|
|
let mut repr = None;
|
|
|
|
for attr in input.attrs {
|
|
|
|
if let Ok(Meta::List(list)) = attr.parse_meta() {
|
|
|
|
if list.ident == "repr" {
|
|
|
|
if let Some(NestedMeta::Meta(Meta::Word(word))) = list.nested.into_iter().next() {
|
|
|
|
match word.to_string().as_str() {
|
|
|
|
"u8" | "u16" | "u32" | "u64" | "u128" | "usize" | "i8" | "i16" | "i32"
|
|
|
|
| "i64" | "i128" | "isize" => {
|
|
|
|
repr = Some(word);
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let signature;
|
|
|
|
let value;
|
2019-04-15 22:56:35 +00:00
|
|
|
match &repr {
|
|
|
|
Some(repr) => {
|
macros: Derive macro to generate integer to enum conversion
This CL adds a procedural macro to generate functions for converting a
primitive integer into the corresponding variant of an enum.
Loosely based on https://docs.rs/enum-primitive-derive but implemented
against a newer version of Syn and without the dependency on num-traits.
The generated function is named `n` and has the following signature:
impl YourEnum {
pub fn n(value: Repr) -> Option<Self>;
}
where `Repr` is an integer type of the right size as described in more
detail below.
EXAMPLE
extern crate enumn;
#[derive(PartialEq, Debug, enumn::N)]
enum Status {
LegendaryTriumph,
QualifiedSuccess,
FortuitousRevival,
IndeterminateStalemate,
RecoverableSetback,
DireMisadventure,
AbjectFailure,
}
fn main() {
let s = Status::n(1);
assert_eq!(s, Some(Status::QualifiedSuccess));
let s = Status::n(9);
assert_eq!(s, None);
}
SIGNATURE
The generated signature depends on whether the enum has a `#[repr(..)]`
attribute. If a `repr` is specified, the input to `n` will be required
to be of that type.
#[derive(enumn::N)]
#[repr(u8)]
enum E {
/* ... */
}
// expands to:
impl E {
pub fn n(value: u8) -> Option<Self> {
/* ... */
}
}
On the other hand if no `repr` is specified then we get a signature that
is generic over a variety of possible types.
impl E {
pub fn n<REPR: Into<i64>>(value: REPR) -> Option<Self> {
/* ... */
}
}
DISCRIMINANTS
The conversion respects explictly specified enum discriminants. Consider
this enum:
#[derive(enumn::N)]
enum Letter {
A = 65,
B = 66,
}
Here `Letter::n(65)` would return `Some(Letter::A)`.
TEST=`cargo test` against the new crate
Change-Id: I4286a816828c83507b35185fe497455ee30ae9e8
Reviewed-on: https://chromium-review.googlesource.com/1365114
Commit-Ready: David Tolnay <dtolnay@chromium.org>
Tested-by: David Tolnay <dtolnay@chromium.org>
Reviewed-by: Chirantan Ekbote <chirantan@chromium.org>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
2018-12-06 09:58:21 +00:00
|
|
|
signature = quote! {
|
|
|
|
fn n(value: #repr)
|
|
|
|
};
|
|
|
|
value = quote!(value);
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
repr = Some(parse_quote!(i64));
|
|
|
|
signature = quote! {
|
|
|
|
fn n<REPR: Into<i64>>(value: REPR)
|
|
|
|
};
|
|
|
|
value = quote! {
|
|
|
|
<REPR as Into<i64>>::into(value)
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let ident = input.ident;
|
|
|
|
let declare_discriminants = variants.iter().map(|variant| {
|
|
|
|
let variant = &variant.ident;
|
|
|
|
quote! {
|
|
|
|
const #variant: #repr = #ident::#variant as #repr;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
let match_discriminants = variants.iter().map(|variant| {
|
|
|
|
let variant = &variant.ident;
|
|
|
|
quote! {
|
|
|
|
discriminant::#variant => Some(#ident::#variant),
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
quote! {
|
2019-03-22 21:50:47 +00:00
|
|
|
#[allow(non_upper_case_globals)]
|
macros: Derive macro to generate integer to enum conversion
This CL adds a procedural macro to generate functions for converting a
primitive integer into the corresponding variant of an enum.
Loosely based on https://docs.rs/enum-primitive-derive but implemented
against a newer version of Syn and without the dependency on num-traits.
The generated function is named `n` and has the following signature:
impl YourEnum {
pub fn n(value: Repr) -> Option<Self>;
}
where `Repr` is an integer type of the right size as described in more
detail below.
EXAMPLE
extern crate enumn;
#[derive(PartialEq, Debug, enumn::N)]
enum Status {
LegendaryTriumph,
QualifiedSuccess,
FortuitousRevival,
IndeterminateStalemate,
RecoverableSetback,
DireMisadventure,
AbjectFailure,
}
fn main() {
let s = Status::n(1);
assert_eq!(s, Some(Status::QualifiedSuccess));
let s = Status::n(9);
assert_eq!(s, None);
}
SIGNATURE
The generated signature depends on whether the enum has a `#[repr(..)]`
attribute. If a `repr` is specified, the input to `n` will be required
to be of that type.
#[derive(enumn::N)]
#[repr(u8)]
enum E {
/* ... */
}
// expands to:
impl E {
pub fn n(value: u8) -> Option<Self> {
/* ... */
}
}
On the other hand if no `repr` is specified then we get a signature that
is generic over a variety of possible types.
impl E {
pub fn n<REPR: Into<i64>>(value: REPR) -> Option<Self> {
/* ... */
}
}
DISCRIMINANTS
The conversion respects explictly specified enum discriminants. Consider
this enum:
#[derive(enumn::N)]
enum Letter {
A = 65,
B = 66,
}
Here `Letter::n(65)` would return `Some(Letter::A)`.
TEST=`cargo test` against the new crate
Change-Id: I4286a816828c83507b35185fe497455ee30ae9e8
Reviewed-on: https://chromium-review.googlesource.com/1365114
Commit-Ready: David Tolnay <dtolnay@chromium.org>
Tested-by: David Tolnay <dtolnay@chromium.org>
Reviewed-by: Chirantan Ekbote <chirantan@chromium.org>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
2018-12-06 09:58:21 +00:00
|
|
|
impl #ident {
|
|
|
|
pub #signature -> Option<Self> {
|
|
|
|
struct discriminant;
|
|
|
|
impl discriminant {
|
|
|
|
#(#declare_discriminants)*
|
|
|
|
}
|
|
|
|
match #value {
|
|
|
|
#(#match_discriminants)*
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[proc_macro_derive(N)]
|
|
|
|
pub fn derive(input: TokenStream) -> TokenStream {
|
|
|
|
let input = parse_macro_input!(input as DeriveInput);
|
|
|
|
let expanded = testable_derive(input);
|
|
|
|
TokenStream::from(expanded)
|
|
|
|
}
|