mirror of
https://github.com/danog/strum.git
synced 2024-11-30 04:28:59 +01:00
Did additional refactoring and added helpful trait methods to improve readability
This commit is contained in:
parent
8502a1cabc
commit
ca17ae7581
@ -1,4 +1,6 @@
|
|||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
use heck::{CamelCase, KebabCase, MixedCase, ShoutySnakeCase, SnakeCase, TitleCase};
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
pub enum CaseStyle {
|
pub enum CaseStyle {
|
||||||
CamelCase,
|
CamelCase,
|
||||||
KebabCase,
|
KebabCase,
|
||||||
@ -43,3 +45,45 @@ impl<'s> From<&'s str> for CaseStyle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait CaseStyleHelpers {
|
||||||
|
fn convert_case(&self, case_style: Option<CaseStyle>) -> String;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CaseStyleHelpers for syn::Ident {
|
||||||
|
fn convert_case(&self, case_style: Option<CaseStyle>) -> String {
|
||||||
|
let ident_string = self.to_string();
|
||||||
|
if let Some(case_style) = case_style {
|
||||||
|
match case_style {
|
||||||
|
CaseStyle::PascalCase => ident_string.to_camel_case(),
|
||||||
|
CaseStyle::KebabCase => ident_string.to_kebab_case(),
|
||||||
|
CaseStyle::MixedCase => ident_string.to_mixed_case(),
|
||||||
|
CaseStyle::ShoutySnakeCase => ident_string.to_shouty_snake_case(),
|
||||||
|
CaseStyle::SnakeCase => ident_string.to_snake_case(),
|
||||||
|
CaseStyle::TitleCase => ident_string.to_title_case(),
|
||||||
|
CaseStyle::UpperCase => ident_string.to_uppercase(),
|
||||||
|
CaseStyle::LowerCase => ident_string.to_lowercase(),
|
||||||
|
CaseStyle::ScreamingKebabCase => ident_string.to_kebab_case().to_uppercase(),
|
||||||
|
CaseStyle::CamelCase => {
|
||||||
|
let camel_case = ident_string.to_camel_case();
|
||||||
|
let mut pascal = String::with_capacity(camel_case.len());
|
||||||
|
let mut it = camel_case.chars();
|
||||||
|
if let Some(ch) = it.next() {
|
||||||
|
pascal.extend(ch.to_lowercase());
|
||||||
|
}
|
||||||
|
pascal.extend(it);
|
||||||
|
pascal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ident_string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_convert_case() {
|
||||||
|
let id = syn::Ident::new("test_me", proc_macro2::Span::call_site());
|
||||||
|
assert_eq!("testMe", id.convert_case(Some(CaseStyle::CamelCase)));
|
||||||
|
assert_eq!("TestMe", id.convert_case(Some(CaseStyle::PascalCase)));
|
||||||
|
}
|
@ -1,18 +1,15 @@
|
|||||||
use syn::{Meta, MetaList};
|
use syn::Meta;
|
||||||
|
|
||||||
use super::MetaHelpers;
|
use super::MetaHelpers;
|
||||||
use super::MetaListHelpers;
|
use super::MetaListHelpers;
|
||||||
|
|
||||||
pub trait MetaIteratorHelpers {
|
pub trait MetaIteratorHelpers {
|
||||||
type Item;
|
|
||||||
|
|
||||||
fn unique_meta_list(self, attr: &str) -> Option<Self::Item>;
|
fn find_attribute(&self, attr: &str) -> std::vec::IntoIter<&Meta>;
|
||||||
fn extract_attrs(self, attr: &str, prop: &str) -> Vec<String>;
|
fn find_properties(&self, attr: &str, prop: &str) -> Vec<String>;
|
||||||
|
|
||||||
fn unique_attr(self, attr: &str, prop: &str) -> Option<String>
|
fn find_unique_property(&self, attr: &str, prop: &str) -> Option<String>
|
||||||
where Self: Sized
|
|
||||||
{
|
{
|
||||||
let mut curr = self.extract_attrs(attr, prop);
|
let mut curr = self.find_properties(attr, prop);
|
||||||
if curr.len() > 1 {
|
if curr.len() > 1 {
|
||||||
panic!("More than one property: {} found on variant", prop);
|
panic!("More than one property: {} found on variant", prop);
|
||||||
}
|
}
|
||||||
@ -20,10 +17,9 @@ pub trait MetaIteratorHelpers {
|
|||||||
curr.pop()
|
curr.pop()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_disabled(self) -> bool
|
fn is_disabled(&self) -> bool
|
||||||
where Self: Sized
|
|
||||||
{
|
{
|
||||||
let v = self.extract_attrs("strum", "disabled");
|
let v = self.find_properties("strum", "disabled");
|
||||||
match v.len() {
|
match v.len() {
|
||||||
0 => false,
|
0 => false,
|
||||||
1 => v[0] == "true",
|
1 => v[0] == "true",
|
||||||
@ -32,44 +28,29 @@ pub trait MetaIteratorHelpers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'a, I> MetaIteratorHelpers for I
|
//impl MetaIteratorHelpers for [Meta]
|
||||||
|
impl <T> MetaIteratorHelpers for [T]
|
||||||
where
|
where
|
||||||
I: std::iter::IntoIterator<Item=&'a Meta>
|
T: std::borrow::Borrow<Meta>
|
||||||
{
|
{
|
||||||
type Item=&'a MetaList;
|
fn find_attribute(&self, attr: &str) -> std::vec::IntoIter<&Meta> {
|
||||||
|
self.iter()
|
||||||
/// Returns the `MetaList` that matches the given name from the list of `Meta`s, or `None`.
|
.filter_map(|meta| meta.borrow().try_metalist())
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// Panics if more than one `Meta` exists with the name.
|
|
||||||
fn unique_meta_list(self, attr: &str) -> Option<&'a MetaList>
|
|
||||||
where
|
|
||||||
Self: Sized
|
|
||||||
{
|
|
||||||
// let mut curr = get_meta_list(metas.into_iter(), attr).collect::<Vec<_>>();
|
|
||||||
let mut curr = self.into_iter()
|
|
||||||
.filter_map(|meta| meta.try_metalist())
|
|
||||||
.filter(|list| list.path.is_ident(attr))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
if curr.len() > 1 {
|
|
||||||
panic!("More than one `{}` attribute found on type", attr);
|
|
||||||
}
|
|
||||||
|
|
||||||
curr.pop()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn extract_attrs(self, attr: &str, prop: &str) -> Vec<String>
|
|
||||||
where
|
|
||||||
Self: Sized
|
|
||||||
{
|
|
||||||
use syn::{Lit, MetaNameValue};
|
|
||||||
self.into_iter()
|
|
||||||
.filter_map(|meta| meta.try_metalist())
|
|
||||||
.filter(|list| list.path.is_ident(attr))
|
.filter(|list| list.path.is_ident(attr))
|
||||||
.flat_map(|list| list.expand_inner())
|
.flat_map(|list| list.expand_inner())
|
||||||
// Get all the inner elements as long as they start with ser.
|
.collect::<Vec<_>>()
|
||||||
|
.into_iter()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_properties(&self, attr: &str, prop: &str) -> Vec<String>
|
||||||
|
{
|
||||||
|
use syn::{Lit, MetaNameValue};
|
||||||
|
self.iter()
|
||||||
|
// Only look at MetaList style attributes `[strum(...)]`
|
||||||
|
.filter_map(|meta| meta.borrow().try_metalist())
|
||||||
|
.filter(|list| list.path.is_ident(attr))
|
||||||
|
.flat_map(|list| list.expand_inner())
|
||||||
|
// Match all the properties with a given ident `[strum(serialize = "value")]`
|
||||||
.filter_map(|meta| match *meta {
|
.filter_map(|meta| match *meta {
|
||||||
Meta::NameValue(MetaNameValue {
|
Meta::NameValue(MetaNameValue {
|
||||||
ref path,
|
ref path,
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use heck::{CamelCase, KebabCase, MixedCase, ShoutySnakeCase, SnakeCase, TitleCase};
|
|
||||||
use syn::{Attribute, Ident, Meta, MetaList};
|
use syn::{Attribute, Meta};
|
||||||
use crate::helpers::case_style::CaseStyle;
|
|
||||||
|
|
||||||
pub mod case_style;
|
pub mod case_style;
|
||||||
mod metalist_helpers;
|
mod metalist_helpers;
|
||||||
@ -10,6 +9,7 @@ mod meta_iterator_helpers;
|
|||||||
pub use self::metalist_helpers::MetaListHelpers;
|
pub use self::metalist_helpers::MetaListHelpers;
|
||||||
pub use self::meta_helpers::MetaHelpers;
|
pub use self::meta_helpers::MetaHelpers;
|
||||||
pub use self::meta_iterator_helpers::MetaIteratorHelpers;
|
pub use self::meta_iterator_helpers::MetaIteratorHelpers;
|
||||||
|
pub use self::case_style::CaseStyleHelpers;
|
||||||
|
|
||||||
pub fn extract_meta(attrs: &[Attribute]) -> Vec<Meta> {
|
pub fn extract_meta(attrs: &[Attribute]) -> Vec<Meta> {
|
||||||
attrs
|
attrs
|
||||||
@ -17,61 +17,3 @@ pub fn extract_meta(attrs: &[Attribute]) -> Vec<Meta> {
|
|||||||
.filter_map(|attribute| attribute.parse_meta().ok())
|
.filter_map(|attribute| attribute.parse_meta().ok())
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `MetaList` that matches the given name from the list of `Meta`s, or `None`.
|
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// Panics if more than one `Meta` exists with the name.
|
|
||||||
pub fn unique_meta_list<'meta, MetaIt>(metas: MetaIt, attr: &'meta str) -> Option<&'meta MetaList>
|
|
||||||
where
|
|
||||||
MetaIt: Iterator<Item = &'meta Meta>,
|
|
||||||
{
|
|
||||||
// let mut curr = get_meta_list(metas.into_iter(), attr).collect::<Vec<_>>();
|
|
||||||
let mut curr = metas
|
|
||||||
.filter_map(|meta| meta.try_metalist())
|
|
||||||
.filter(|list| list.path.is_ident(attr))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
if curr.len() > 1 {
|
|
||||||
panic!("More than one `{}` attribute found on type", attr);
|
|
||||||
}
|
|
||||||
|
|
||||||
curr.pop()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn convert_case(ident: &Ident, case_style: Option<CaseStyle>) -> String {
|
|
||||||
let ident_string = ident.to_string();
|
|
||||||
if let Some(case_style) = case_style {
|
|
||||||
match case_style {
|
|
||||||
CaseStyle::PascalCase => ident_string.to_camel_case(),
|
|
||||||
CaseStyle::KebabCase => ident_string.to_kebab_case(),
|
|
||||||
CaseStyle::MixedCase => ident_string.to_mixed_case(),
|
|
||||||
CaseStyle::ShoutySnakeCase => ident_string.to_shouty_snake_case(),
|
|
||||||
CaseStyle::SnakeCase => ident_string.to_snake_case(),
|
|
||||||
CaseStyle::TitleCase => ident_string.to_title_case(),
|
|
||||||
CaseStyle::UpperCase => ident_string.to_uppercase(),
|
|
||||||
CaseStyle::LowerCase => ident_string.to_lowercase(),
|
|
||||||
CaseStyle::ScreamingKebabCase => ident_string.to_kebab_case().to_uppercase(),
|
|
||||||
CaseStyle::CamelCase => {
|
|
||||||
let camel_case = ident_string.to_camel_case();
|
|
||||||
let mut pascal = String::with_capacity(camel_case.len());
|
|
||||||
let mut it = camel_case.chars();
|
|
||||||
if let Some(ch) = it.next() {
|
|
||||||
pascal.extend(ch.to_lowercase());
|
|
||||||
}
|
|
||||||
pascal.extend(it);
|
|
||||||
pascal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ident_string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_convert_case() {
|
|
||||||
let id = Ident::new("test_me", proc_macro2::Span::call_site());
|
|
||||||
assert_eq!("testMe", convert_case(&id, Some(CaseStyle::CamelCase)));
|
|
||||||
assert_eq!("TestMe", convert_case(&id, Some(CaseStyle::PascalCase)));
|
|
||||||
}
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use crate::helpers::{MetaHelpers, MetaListHelpers};
|
use crate::helpers::{MetaHelpers, MetaListHelpers, MetaIteratorHelpers};
|
||||||
use proc_macro2::{Span, TokenStream};
|
use proc_macro2::{Span, TokenStream};
|
||||||
use syn;
|
use syn;
|
||||||
|
|
||||||
use helpers::{extract_meta, unique_meta_list};
|
use helpers::{extract_meta};
|
||||||
|
|
||||||
pub fn enum_discriminants_inner(ast: &syn::DeriveInput) -> TokenStream {
|
pub fn enum_discriminants_inner(ast: &syn::DeriveInput) -> TokenStream {
|
||||||
let name = &ast.ident;
|
let name = &ast.ident;
|
||||||
@ -15,19 +15,12 @@ pub fn enum_discriminants_inner(ast: &syn::DeriveInput) -> TokenStream {
|
|||||||
|
|
||||||
// Derives for the generated enum
|
// Derives for the generated enum
|
||||||
let type_meta = extract_meta(&ast.attrs);
|
let type_meta = extract_meta(&ast.attrs);
|
||||||
let discriminant_attrs = type_meta.iter()
|
let discriminant_attrs = type_meta
|
||||||
// We are only looking at 'metalist' style attributes [list(item1,item2,...)]
|
.find_attribute("strum_discriminants")
|
||||||
.filter_map(|meta| meta.try_metalist())
|
|
||||||
// Find the list named `strum_discriminants`
|
|
||||||
.filter(|list| list.path.is_ident("strum_discriminants"))
|
|
||||||
// If there are multiple attributes, we combine them all together.
|
|
||||||
.flat_map(|list| list.expand_inner())
|
|
||||||
.collect::<Vec<&syn::Meta>>();
|
.collect::<Vec<&syn::Meta>>();
|
||||||
|
|
||||||
let derives = discriminant_attrs.iter()
|
let derives = discriminant_attrs
|
||||||
.filter_map(|meta| meta.try_metalist())
|
.find_attribute("derive")
|
||||||
.filter(|list| list.path.is_ident("derive"))
|
|
||||||
.flat_map(|list| list.expand_inner())
|
|
||||||
.map(|meta| meta.path())
|
.map(|meta| meta.path())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
@ -41,7 +34,16 @@ pub fn enum_discriminants_inner(ast: &syn::DeriveInput) -> TokenStream {
|
|||||||
Span::call_site()
|
Span::call_site()
|
||||||
));
|
));
|
||||||
|
|
||||||
let discriminants_name = unique_meta_list(discriminant_attrs.iter().map(|&m| m), "name")
|
let discriminants_name = discriminant_attrs.iter()
|
||||||
|
.filter_map(|meta| meta.try_metalist())
|
||||||
|
.filter(|list| list.path.is_ident("name"))
|
||||||
|
// We want exactly zero or one items. Start with the assumption we have zero, i.e. None
|
||||||
|
// Then set our output to the first value we see. If fold is called again and we already
|
||||||
|
// have a value, panic.
|
||||||
|
.fold(None, |acc, val| match acc {
|
||||||
|
Some(_) => panic!("Expecting a single attribute 'name' in EnumDiscriminants."),
|
||||||
|
None => Some(val),
|
||||||
|
})
|
||||||
.map(|meta| meta.expand_inner())
|
.map(|meta| meta.expand_inner())
|
||||||
.and_then(|metas| metas.into_iter().map(|meta| meta.path()).next())
|
.and_then(|metas| metas.into_iter().map(|meta| meta.path()).next())
|
||||||
.unwrap_or(&default_name);
|
.unwrap_or(&default_name);
|
||||||
|
@ -17,8 +17,8 @@ pub fn enum_message_inner(ast: &syn::DeriveInput) -> TokenStream {
|
|||||||
|
|
||||||
for variant in variants {
|
for variant in variants {
|
||||||
let meta = extract_meta(&variant.attrs);
|
let meta = extract_meta(&variant.attrs);
|
||||||
let messages = meta.unique_attr("strum", "message");
|
let messages = meta.find_unique_property("strum", "message");
|
||||||
let detailed_messages = meta.unique_attr("strum", "detailed_message");
|
let detailed_messages = meta.find_unique_property("strum", "detailed_message");
|
||||||
let ident = &variant.ident;
|
let ident = &variant.ident;
|
||||||
|
|
||||||
use syn::Fields::*;
|
use syn::Fields::*;
|
||||||
@ -30,7 +30,7 @@ pub fn enum_message_inner(ast: &syn::DeriveInput) -> TokenStream {
|
|||||||
|
|
||||||
// You can't disable getting the serializations.
|
// You can't disable getting the serializations.
|
||||||
{
|
{
|
||||||
let mut serialization_variants = meta.extract_attrs("strum", "serialize");
|
let mut serialization_variants = meta.find_properties("strum", "serialize");
|
||||||
if serialization_variants.len() == 0 {
|
if serialization_variants.len() == 0 {
|
||||||
serialization_variants.push(ident.to_string());
|
serialization_variants.push(ident.to_string());
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ use proc_macro2::TokenStream;
|
|||||||
use syn;
|
use syn;
|
||||||
|
|
||||||
use crate::helpers::case_style::CaseStyle;
|
use crate::helpers::case_style::CaseStyle;
|
||||||
use crate::helpers::{convert_case, extract_meta, MetaIteratorHelpers};
|
use crate::helpers::{CaseStyleHelpers, extract_meta, MetaIteratorHelpers};
|
||||||
|
|
||||||
pub fn enum_variant_names_inner(ast: &syn::DeriveInput) -> TokenStream {
|
pub fn enum_variant_names_inner(ast: &syn::DeriveInput) -> TokenStream {
|
||||||
let name = &ast.ident;
|
let name = &ast.ident;
|
||||||
@ -14,12 +14,12 @@ pub fn enum_variant_names_inner(ast: &syn::DeriveInput) -> TokenStream {
|
|||||||
|
|
||||||
// Derives for the generated enum
|
// Derives for the generated enum
|
||||||
let type_meta = extract_meta(&ast.attrs);
|
let type_meta = extract_meta(&ast.attrs);
|
||||||
let case_style = type_meta.unique_attr("strum", "serialize_all")
|
let case_style = type_meta.find_unique_property("strum", "serialize_all")
|
||||||
.map(|style| CaseStyle::from(style.as_ref()));
|
.map(|style| CaseStyle::from(style.as_ref()));
|
||||||
|
|
||||||
let names = variants
|
let names = variants
|
||||||
.iter()
|
.iter()
|
||||||
.map(|v| convert_case(&v.ident, case_style))
|
.map(|v| v.ident.convert_case(case_style))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
pub mod as_ref_str;
|
|
||||||
pub mod display;
|
|
||||||
pub mod enum_count;
|
pub mod enum_count;
|
||||||
pub mod enum_discriminants;
|
pub mod enum_discriminants;
|
||||||
pub mod enum_iter;
|
pub mod enum_iter;
|
||||||
pub mod enum_messages;
|
pub mod enum_messages;
|
||||||
pub mod enum_properties;
|
pub mod enum_properties;
|
||||||
pub mod enum_variant_names;
|
pub mod enum_variant_names;
|
||||||
pub mod from_string;
|
|
||||||
pub mod to_string;
|
mod strings;
|
||||||
|
|
||||||
|
pub use self::strings::as_ref_str;
|
||||||
|
pub use self::strings::display;
|
||||||
|
pub use self::strings::from_string;
|
||||||
|
pub use self::strings::to_string;
|
||||||
|
@ -2,7 +2,7 @@ use proc_macro2::TokenStream;
|
|||||||
use syn;
|
use syn;
|
||||||
|
|
||||||
use crate::helpers::case_style::CaseStyle;
|
use crate::helpers::case_style::CaseStyle;
|
||||||
use helpers::{convert_case, extract_meta, MetaIteratorHelpers};
|
use helpers::{CaseStyleHelpers, extract_meta, MetaIteratorHelpers};
|
||||||
|
|
||||||
fn get_arms(ast: &syn::DeriveInput) -> Vec<TokenStream> {
|
fn get_arms(ast: &syn::DeriveInput) -> Vec<TokenStream> {
|
||||||
let name = &ast.ident;
|
let name = &ast.ident;
|
||||||
@ -13,7 +13,7 @@ fn get_arms(ast: &syn::DeriveInput) -> Vec<TokenStream> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let type_meta = extract_meta(&ast.attrs);
|
let type_meta = extract_meta(&ast.attrs);
|
||||||
let case_style = type_meta.unique_attr("strum", "serialize_all")
|
let case_style = type_meta.find_unique_property("strum", "serialize_all")
|
||||||
.map(|style| CaseStyle::from(style.as_ref()));
|
.map(|style| CaseStyle::from(style.as_ref()));
|
||||||
|
|
||||||
for variant in variants {
|
for variant in variants {
|
||||||
@ -28,16 +28,16 @@ fn get_arms(ast: &syn::DeriveInput) -> Vec<TokenStream> {
|
|||||||
// Look at all the serialize attributes.
|
// Look at all the serialize attributes.
|
||||||
// Use `to_string` attribute (not `as_ref_str` or something) to keep things consistent
|
// Use `to_string` attribute (not `as_ref_str` or something) to keep things consistent
|
||||||
// (i.e. always `enum.as_ref().to_string() == enum.to_string()`).
|
// (i.e. always `enum.as_ref().to_string() == enum.to_string()`).
|
||||||
let output = if let Some(n) = meta.unique_attr("strum", "to_string") {
|
let output = if let Some(n) = meta.find_unique_property("strum", "to_string") {
|
||||||
n
|
n
|
||||||
} else {
|
} else {
|
||||||
let mut attrs = meta.extract_attrs("strum", "serialize");
|
let mut attrs = meta.find_properties("strum", "serialize");
|
||||||
// We always take the longest one. This is arbitary, but is *mostly* deterministic
|
// We always take the longest one. This is arbitary, but is *mostly* deterministic
|
||||||
attrs.sort_by_key(|s| s.len());
|
attrs.sort_by_key(|s| s.len());
|
||||||
if let Some(n) = attrs.pop() {
|
if let Some(n) = attrs.pop() {
|
||||||
n
|
n
|
||||||
} else {
|
} else {
|
||||||
convert_case(ident, case_style)
|
ident.convert_case(case_style)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -2,7 +2,7 @@ use proc_macro2::TokenStream;
|
|||||||
use syn;
|
use syn;
|
||||||
|
|
||||||
use crate::helpers::case_style::CaseStyle;
|
use crate::helpers::case_style::CaseStyle;
|
||||||
use helpers::{convert_case, extract_meta, MetaIteratorHelpers};
|
use helpers::{CaseStyleHelpers, extract_meta, MetaIteratorHelpers};
|
||||||
|
|
||||||
pub fn display_inner(ast: &syn::DeriveInput) -> TokenStream {
|
pub fn display_inner(ast: &syn::DeriveInput) -> TokenStream {
|
||||||
let name = &ast.ident;
|
let name = &ast.ident;
|
||||||
@ -13,7 +13,7 @@ pub fn display_inner(ast: &syn::DeriveInput) -> TokenStream {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let type_meta = extract_meta(&ast.attrs);
|
let type_meta = extract_meta(&ast.attrs);
|
||||||
let case_style = type_meta.unique_attr("strum", "serialize_all")
|
let case_style = type_meta.find_unique_property("strum", "serialize_all")
|
||||||
.map(|style| CaseStyle::from(style.as_ref()));
|
.map(|style| CaseStyle::from(style.as_ref()));
|
||||||
|
|
||||||
let mut arms = Vec::new();
|
let mut arms = Vec::new();
|
||||||
@ -27,16 +27,16 @@ pub fn display_inner(ast: &syn::DeriveInput) -> TokenStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Look at all the serialize attributes.
|
// Look at all the serialize attributes.
|
||||||
let output = if let Some(n) = meta.unique_attr("strum", "to_string") {
|
let output = if let Some(n) = meta.find_unique_property("strum", "to_string") {
|
||||||
n
|
n
|
||||||
} else {
|
} else {
|
||||||
let mut attrs = meta.extract_attrs("strum", "serialize");
|
let mut attrs = meta.find_properties("strum", "serialize");
|
||||||
// We always take the longest one. This is arbitary, but is *mostly* deterministic
|
// We always take the longest one. This is arbitary, but is *mostly* deterministic
|
||||||
attrs.sort_by_key(|s| s.len());
|
attrs.sort_by_key(|s| s.len());
|
||||||
if let Some(n) = attrs.pop() {
|
if let Some(n) = attrs.pop() {
|
||||||
n
|
n
|
||||||
} else {
|
} else {
|
||||||
convert_case(ident, case_style)
|
ident.convert_case(case_style)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -2,8 +2,7 @@ use proc_macro2::TokenStream;
|
|||||||
use syn;
|
use syn;
|
||||||
|
|
||||||
use crate::helpers::case_style::CaseStyle;
|
use crate::helpers::case_style::CaseStyle;
|
||||||
// use helpers::{convert_case, extract_attrs, extract_meta, is_disabled, unique_attr, MetaIteratorHelpers};
|
use crate::helpers::{CaseStyleHelpers, extract_meta, MetaIteratorHelpers};
|
||||||
use crate::helpers::{convert_case, extract_meta, MetaIteratorHelpers};
|
|
||||||
|
|
||||||
pub fn from_string_inner(ast: &syn::DeriveInput) -> TokenStream {
|
pub fn from_string_inner(ast: &syn::DeriveInput) -> TokenStream {
|
||||||
let name = &ast.ident;
|
let name = &ast.ident;
|
||||||
@ -14,7 +13,7 @@ pub fn from_string_inner(ast: &syn::DeriveInput) -> TokenStream {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let type_meta = extract_meta(&ast.attrs);
|
let type_meta = extract_meta(&ast.attrs);
|
||||||
let case_style = type_meta.unique_attr("strum", "serialize_all")
|
let case_style = type_meta.find_unique_property("strum", "serialize_all")
|
||||||
.map(|style| CaseStyle::from(style.as_ref()));
|
.map(|style| CaseStyle::from(style.as_ref()));
|
||||||
|
|
||||||
let mut has_default = false;
|
let mut has_default = false;
|
||||||
@ -27,18 +26,18 @@ pub fn from_string_inner(ast: &syn::DeriveInput) -> TokenStream {
|
|||||||
let meta = extract_meta(&variant.attrs);
|
let meta = extract_meta(&variant.attrs);
|
||||||
|
|
||||||
// Look at all the serialize attributes.
|
// Look at all the serialize attributes.
|
||||||
// let mut attrs = extract_attrs(&meta, "strum", "serialize");
|
// let mut attrs = find_properties(&meta, "strum", "serialize");
|
||||||
// attrs.extend(extract_attrs(&meta, "strum", "to_string"));
|
// attrs.extend(find_properties(&meta, "strum", "to_string"));
|
||||||
|
|
||||||
let mut attrs = meta.extract_attrs("strum", "serialize");
|
let mut attrs = meta.find_properties("strum", "serialize");
|
||||||
attrs.extend(meta.extract_attrs("strum", "to_string"));
|
attrs.extend(meta.find_properties("strum", "to_string"));
|
||||||
|
|
||||||
// if is_disabled(&meta) {
|
// if is_disabled(&meta) {
|
||||||
if meta.is_disabled() {
|
if meta.is_disabled() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if meta.unique_attr("strum", "default").map_or(false, |s| s == "true") {
|
if meta.find_unique_property("strum", "default").map_or(false, |s| s == "true") {
|
||||||
if has_default {
|
if has_default {
|
||||||
panic!("Can't have multiple default variants");
|
panic!("Can't have multiple default variants");
|
||||||
}
|
}
|
||||||
@ -61,7 +60,7 @@ pub fn from_string_inner(ast: &syn::DeriveInput) -> TokenStream {
|
|||||||
|
|
||||||
// If we don't have any custom variants, add the default serialized name.
|
// If we don't have any custom variants, add the default serialized name.
|
||||||
if attrs.len() == 0 {
|
if attrs.len() == 0 {
|
||||||
attrs.push(convert_case(ident, case_style));
|
attrs.push(ident.convert_case(case_style));
|
||||||
}
|
}
|
||||||
|
|
||||||
let params = match variant.fields {
|
let params = match variant.fields {
|
4
strum_macros/src/macros/strings/mod.rs
Normal file
4
strum_macros/src/macros/strings/mod.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
pub mod as_ref_str;
|
||||||
|
pub mod display;
|
||||||
|
pub mod from_string;
|
||||||
|
pub mod to_string;
|
@ -2,7 +2,7 @@ use proc_macro2::TokenStream;
|
|||||||
use syn;
|
use syn;
|
||||||
|
|
||||||
use crate::helpers::case_style::CaseStyle;
|
use crate::helpers::case_style::CaseStyle;
|
||||||
use crate::helpers::{convert_case, extract_meta, MetaIteratorHelpers};
|
use crate::helpers::{CaseStyleHelpers, extract_meta, MetaIteratorHelpers};
|
||||||
|
|
||||||
pub fn to_string_inner(ast: &syn::DeriveInput) -> TokenStream {
|
pub fn to_string_inner(ast: &syn::DeriveInput) -> TokenStream {
|
||||||
let name = &ast.ident;
|
let name = &ast.ident;
|
||||||
@ -13,7 +13,7 @@ pub fn to_string_inner(ast: &syn::DeriveInput) -> TokenStream {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let type_meta = extract_meta(&ast.attrs);
|
let type_meta = extract_meta(&ast.attrs);
|
||||||
let case_style = type_meta.unique_attr( "strum", "serialize_all")
|
let case_style = type_meta.find_unique_property( "strum", "serialize_all")
|
||||||
.map(|style| CaseStyle::from(style.as_ref()));
|
.map(|style| CaseStyle::from(style.as_ref()));
|
||||||
|
|
||||||
let mut arms = Vec::new();
|
let mut arms = Vec::new();
|
||||||
@ -27,16 +27,16 @@ pub fn to_string_inner(ast: &syn::DeriveInput) -> TokenStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Look at all the serialize attributes.
|
// Look at all the serialize attributes.
|
||||||
let output = if let Some(n) = meta.unique_attr("strum", "to_string") {
|
let output = if let Some(n) = meta.find_unique_property("strum", "to_string") {
|
||||||
n
|
n
|
||||||
} else {
|
} else {
|
||||||
let mut attrs = meta.extract_attrs("strum", "serialize");
|
let mut attrs = meta.find_properties("strum", "serialize");
|
||||||
// We always take the longest one. This is arbitary, but is *mostly* deterministic
|
// We always take the longest one. This is arbitary, but is *mostly* deterministic
|
||||||
attrs.sort_by_key(|s| s.len());
|
attrs.sort_by_key(|s| s.len());
|
||||||
if let Some(n) = attrs.pop() {
|
if let Some(n) = attrs.pop() {
|
||||||
n
|
n
|
||||||
} else {
|
} else {
|
||||||
convert_case(ident, case_style)
|
ident.convert_case(case_style)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user