mirror of
https://github.com/danog/strum.git
synced 2024-12-03 09:57:55 +01:00
Add TryFrom to FromRepr
This commit is contained in:
parent
054df849e1
commit
9318da3d3e
@ -3,7 +3,7 @@ use proc_macro2::{Span, TokenStream};
|
|||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
use syn::{Data, DeriveInput, Fields, PathArguments, Type, TypeParen};
|
use syn::{Data, DeriveInput, Fields, PathArguments, Type, TypeParen};
|
||||||
|
|
||||||
use crate::helpers::{non_enum_error, HasStrumVariantProperties};
|
use crate::helpers::{non_enum_error, HasStrumVariantProperties, HasTypeProperties};
|
||||||
|
|
||||||
pub fn from_repr_inner(ast: &DeriveInput) -> syn::Result<TokenStream> {
|
pub fn from_repr_inner(ast: &DeriveInput) -> syn::Result<TokenStream> {
|
||||||
let name = &ast.ident;
|
let name = &ast.ident;
|
||||||
@ -12,6 +12,9 @@ pub fn from_repr_inner(ast: &DeriveInput) -> syn::Result<TokenStream> {
|
|||||||
let vis = &ast.vis;
|
let vis = &ast.vis;
|
||||||
let attrs = &ast.attrs;
|
let attrs = &ast.attrs;
|
||||||
|
|
||||||
|
let type_properties = ast.get_type_properties()?;
|
||||||
|
let strum_module_path = type_properties.crate_module_path();
|
||||||
|
|
||||||
let mut discriminant_type: Type = syn::parse("usize".parse().unwrap()).unwrap();
|
let mut discriminant_type: Type = syn::parse("usize".parse().unwrap()).unwrap();
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
let path = &attr.path;
|
let path = &attr.path;
|
||||||
@ -124,7 +127,7 @@ pub fn from_repr_inner(ast: &DeriveInput) -> syn::Result<TokenStream> {
|
|||||||
filter_by_rust_version(quote! { const })
|
filter_by_rust_version(quote! { const })
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(quote! {
|
let from_repr = quote! {
|
||||||
#[allow(clippy::use_self)]
|
#[allow(clippy::use_self)]
|
||||||
impl #impl_generics #name #ty_generics #where_clause {
|
impl #impl_generics #name #ty_generics #where_clause {
|
||||||
#[doc = "Try to create [Self] from the raw representation"]
|
#[doc = "Try to create [Self] from the raw representation"]
|
||||||
@ -135,5 +138,51 @@ pub fn from_repr_inner(ast: &DeriveInput) -> syn::Result<TokenStream> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let try_from_repr = try_from_repr(
|
||||||
|
name,
|
||||||
|
&discriminant_type,
|
||||||
|
&impl_generics,
|
||||||
|
&ty_generics,
|
||||||
|
where_clause,
|
||||||
|
&strum_module_path,
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(quote! {
|
||||||
|
#from_repr
|
||||||
|
#try_from_repr
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rustversion::before(1.34)]
|
||||||
|
fn try_from_repr(
|
||||||
|
_name: &proc_macro2::Ident,
|
||||||
|
_discriminant_type: &Type,
|
||||||
|
_impl_generics: &syn::ImplGenerics,
|
||||||
|
_ty_generics: &syn::TypeGenerics,
|
||||||
|
_where_clause: Option<&syn::WhereClause>,
|
||||||
|
_strum_module_path: &syn::Path,
|
||||||
|
) -> TokenStream {
|
||||||
|
Default::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustversion::since(1.34)]
|
||||||
|
fn try_from_repr(
|
||||||
|
name: &proc_macro2::Ident,
|
||||||
|
discriminant_type: &Type,
|
||||||
|
impl_generics: &syn::ImplGenerics,
|
||||||
|
ty_generics: &syn::TypeGenerics,
|
||||||
|
where_clause: Option<&syn::WhereClause>,
|
||||||
|
strum_module_path: &syn::Path,
|
||||||
|
) -> TokenStream {
|
||||||
|
quote! {
|
||||||
|
#[allow(clippy::use_self)]
|
||||||
|
impl #impl_generics ::core::convert::TryFrom<#discriminant_type> for #name #ty_generics #where_clause {
|
||||||
|
type Error = #strum_module_path::ParseError;
|
||||||
|
fn try_from(s: #discriminant_type) -> ::core::result::Result< #name #ty_generics , <Self as ::core::convert::TryFrom<#discriminant_type>>::Error> {
|
||||||
|
Self::from_repr(s).ok_or(#strum_module_path::ParseError::VariantNotFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
use core::convert::TryFrom;
|
||||||
|
use core::convert::TryInto;
|
||||||
|
|
||||||
use strum::FromRepr;
|
use strum::FromRepr;
|
||||||
|
|
||||||
#[derive(Debug, FromRepr, PartialEq)]
|
#[derive(Debug, FromRepr, PartialEq)]
|
||||||
@ -12,14 +15,27 @@ enum Week {
|
|||||||
Saturday = 8,
|
Saturday = 8,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! assert_eq_repr {
|
||||||
|
( $type:ident::from_repr($number:literal), Some($enum:expr) ) => {
|
||||||
|
assert_eq!($type::from_repr($number), Some($enum));
|
||||||
|
assert_eq!(TryInto::<$type>::try_into($number), Ok($enum));
|
||||||
|
assert_eq!(<$type as TryFrom<_>>::try_from($number), Ok($enum));
|
||||||
|
};
|
||||||
|
( $type:ident::from_repr($number:literal), None ) => {
|
||||||
|
assert_eq!($type::from_repr($number), None);
|
||||||
|
assert_eq!(TryInto::<$type>::try_into($number), Err(::strum::ParseError::VariantNotFound));
|
||||||
|
assert_eq!(<$type as TryFrom<_>>::try_from($number), Err(::strum::ParseError::VariantNotFound));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn simple_test() {
|
fn simple_test() {
|
||||||
assert_eq!(Week::from_repr(0), Some(Week::Sunday));
|
assert_eq_repr!(Week::from_repr(0), Some(Week::Sunday));
|
||||||
assert_eq!(Week::from_repr(1), Some(Week::Monday));
|
assert_eq_repr!(Week::from_repr(1), Some(Week::Monday));
|
||||||
assert_eq!(Week::from_repr(6), None);
|
assert_eq_repr!(Week::from_repr(6), None);
|
||||||
assert_eq!(Week::from_repr(7), Some(Week::Friday));
|
assert_eq_repr!(Week::from_repr(7), Some(Week::Friday));
|
||||||
assert_eq!(Week::from_repr(8), Some(Week::Saturday));
|
assert_eq_repr!(Week::from_repr(8), Some(Week::Saturday));
|
||||||
assert_eq!(Week::from_repr(9), None);
|
assert_eq_repr!(Week::from_repr(9), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustversion::since(1.46)]
|
#[rustversion::since(1.46)]
|
||||||
@ -57,7 +73,7 @@ fn crate_module_path_test() {
|
|||||||
Saturday,
|
Saturday,
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(Week::from_repr(0), Some(Week::Sunday));
|
assert_eq_repr!(Week::from_repr(0), Some(Week::Sunday));
|
||||||
assert_eq!(Week::from_repr(6), Some(Week::Saturday));
|
assert_eq_repr!(Week::from_repr(6), Some(Week::Saturday));
|
||||||
assert_eq!(Week::from_repr(7), None);
|
assert_eq_repr!(Week::from_repr(7), None);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user