Skip to content

Commit c708606

Browse files
committed
Set version 0.0.1
1 parent 537f7d9 commit c708606

File tree

8 files changed

+86
-22
lines changed

8 files changed

+86
-22
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

kinded/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "kinded"
3-
version = "0.1.0"
3+
version = "0.0.1"
44
edition = "2021"
55
authors = ["Serhii Potapov <blake131313@gmail.com>"]
66

kinded_macros/src/gen.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,10 @@ fn gen_enum_kind(meta: &Meta) -> TokenStream {
4343
let vis = &meta.vis;
4444
let kind_name = meta.kind_name();
4545
let variant_name_idents = meta.variants.iter().map(|v| &v.ident);
46+
let traits = meta.derive_traits();
47+
4648
quote!(
47-
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
49+
#[derive(#(#traits),*)]
4850
#vis enum #kind_name {
4951
#(#variant_name_idents),*
5052
}

kinded_macros/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,17 @@ use syn::DeriveInput;
77

88
// DONE:
99
// * Allow renaming of kind type
10+
// * Allow to derive custom traits
1011

1112
// TODO:
12-
// * Allow to derive custom traits
1313
// * Consider supporting FromStr / Display?
1414
// * Allow to iterate, access ALL variants of Kind
15+
// * Features:
16+
// * enum-map
1517
// * Write documentation
1618
// * lib.rs
1719
// * README
18-
// * How it differs from enum-kind ?
20+
// * How it differs from enum-kinds ?
1921
//
2022

2123
#[proc_macro_derive(Kinded, attributes(kinded))]

kinded_macros/src/models.rs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use proc_macro2::Ident;
22
use quote::format_ident;
3-
use syn::Visibility;
3+
use syn::{Visibility, Path};
44

55
#[derive(Debug)]
66
pub struct Meta {
@@ -17,13 +17,36 @@ pub struct Meta {
1717
}
1818

1919
impl Meta {
20+
/// Get the name for the kind type.
2021
pub fn kind_name(&self) -> Ident {
2122
if let Some(ref kind_name) = self.kinded_attrs.kind {
2223
kind_name.clone()
2324
} else {
2425
format_ident!("{}Kind", self.ident)
2526
}
2627
}
28+
29+
/// Get the traits that need to be derived.
30+
pub fn derive_traits(&self) -> Vec<Path> {
31+
const DEFAULT_DERIVE_TRAITS: &[&'static str] = &[
32+
"Debug", "Clone", "Copy", "PartialEq", "Eq",
33+
];
34+
35+
let mut traits: Vec<Path> = DEFAULT_DERIVE_TRAITS.iter().map(|trait_name| {
36+
Path::from(format_ident!("{trait_name}"))
37+
}).collect();
38+
39+
// Add the extra specified traits, if they're different from the default ones
40+
if let Some(ref extra_traits) = self.kinded_attrs.derive {
41+
for extra_trait in extra_traits {
42+
if !traits.contains(extra_trait) {
43+
traits.push(extra_trait.clone());
44+
}
45+
}
46+
}
47+
48+
traits
49+
}
2750
}
2851

2952
#[derive(Debug)]
@@ -48,6 +71,9 @@ pub enum FieldsType {
4871
/// Attributes specified with #[kinded(..)]
4972
#[derive(Debug, Default)]
5073
pub struct KindedAttributes {
51-
/// Name for the kind type
74+
/// Name for the kind type, specified with `kind = ...`
5275
pub kind: Option<Ident>,
76+
77+
/// Traits to derive, specified with `derive(...)`
78+
pub derive: Option<Vec<Path>>,
5379
}

kinded_macros/src/parse.rs

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,10 @@ use syn::{
55
bracketed, parenthesized,
66
parse::{Parse, ParseStream},
77
spanned::Spanned,
8-
Attribute, Data, DeriveInput, Token,
8+
Attribute, Data, DeriveInput, Token, Path,
99
};
1010

1111
pub fn parse_derive_input(input: DeriveInput) -> Result<Meta, syn::Error> {
12-
eprintln!("{input:#?}");
13-
1412
let kinded_attrs: KindedAttributes = {
1513
match find_kinded_attr(&input)? {
1614
Some(kinded_attr) => syn::parse2(kinded_attr.to_token_stream())?,
@@ -89,19 +87,38 @@ impl Parse for KindedAttributes {
8987
parenthesized_content
9088
};
9189

92-
let attr_name: Ident = input.parse()?;
93-
if attr_name == "kind" {
94-
let _: Token!(=) = input.parse()?;
95-
let kind: Ident = input.parse()?;
96-
if kinded_attrs.kind.is_none() {
97-
kinded_attrs.kind = Some(kind);
90+
91+
while !input.is_empty() {
92+
let attr_name: Ident = input.parse()?;
93+
if attr_name == "kind" {
94+
let _: Token!(=) = input.parse()?;
95+
let kind: Ident = input.parse()?;
96+
if kinded_attrs.kind.is_none() {
97+
kinded_attrs.kind = Some(kind);
98+
} else {
99+
let msg = format!("Duplicated attribute: {attr_name}");
100+
return Err(syn::Error::new(attr_name.span(), msg));
101+
}
102+
} else if attr_name == "derive" {
103+
let derive_input;
104+
parenthesized!(derive_input in input);
105+
let parsed_traits = derive_input.parse_terminated(Path::parse, Token![,])?;
106+
let traits: Vec<Path> = parsed_traits.into_iter().collect();
107+
if kinded_attrs.derive.is_none() {
108+
kinded_attrs.derive = Some(traits);
109+
} else {
110+
let msg = format!("Duplicated attribute: {attr_name}");
111+
return Err(syn::Error::new(attr_name.span(), msg));
112+
}
98113
} else {
99-
let msg = format!("Duplicated attribute: {attr_name}");
114+
let msg = format!("Unknown attribute: {attr_name}");
100115
return Err(syn::Error::new(attr_name.span(), msg));
101116
}
102-
} else {
103-
let msg = format!("Unknown attribute: {attr_name}");
104-
return Err(syn::Error::new(attr_name.span(), msg));
117+
118+
// Parse `,` unless it's the end of the stream
119+
if !input.is_empty() {
120+
let _comma: Token![,] = input.parse()?;
121+
}
105122
}
106123

107124
Ok(kinded_attrs)

sandbox/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "sandbox"
3-
version = "0.1.0"
3+
version = "0.0.1"
44
edition = "2021"
55

66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

sandbox/src/main.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,20 @@ fn should_allow_to_give_custom_name_kind_type() {
110110
let green_tea = Drink::Tea("Green");
111111
assert_eq!(green_tea.kind(), SimpleDrink::Tea);
112112
}
113+
114+
#[test]
115+
fn should_allow_to_derive_custom_traits() {
116+
use std::collections::HashMap;
117+
118+
#[derive(Kinded)]
119+
#[kinded(derive(Hash, Eq))]
120+
enum Drink {
121+
Tea(&'static str),
122+
Coffee(&'static str),
123+
}
124+
125+
let mut drinks = HashMap::new();
126+
drinks.insert(DrinkKind::Tea, 5);
127+
128+
assert!(false);
129+
}

0 commit comments

Comments
 (0)