-
Notifications
You must be signed in to change notification settings - Fork 68
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Improve
FromMeta
implementation for enums (#260)
* Add #[darling(word)] to allow marking a variant as the one when a shorthand property is observed * Improve validation and parsing for enums with heterogeneous variant shapes
- Loading branch information
1 parent
0c79e55
commit 6118a83
Showing
15 changed files
with
311 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
//! This example demonstrates: | ||
//! | ||
//! - The behavior of a derived `FromMeta` implementation for heterogeneous enums | ||
//! (i.e. enums that include a mix of unit, newtype and struct variants). | ||
//! - Using `#[darling(word)]` to specify a unit variant to use when a receiver field | ||
//! is specified without a value (i.e. a unit variant to use for deriving the | ||
//! `FromMeta::from_word` method). | ||
//! - Using `#[darling(default)]` on a receiver field to fall back to `Default::default()` | ||
//! for the enum's value when the receiver field is not specified by the caller. | ||
use darling::{Error, FromDeriveInput, FromMeta}; | ||
use syn::parse_quote; | ||
|
||
/// A playback volume. | ||
#[derive(Debug, FromMeta, PartialEq, Eq)] | ||
enum Volume { | ||
Normal, | ||
#[darling(word)] | ||
Low, | ||
High, | ||
#[darling(rename = "dB")] | ||
Decibels(u8), | ||
} | ||
|
||
impl Default for Volume { | ||
fn default() -> Self { | ||
Volume::Normal | ||
} | ||
} | ||
|
||
#[derive(Debug, FromDeriveInput)] | ||
#[darling(attributes(play))] | ||
struct PlayReceiver { | ||
#[darling(default)] | ||
volume: Volume, | ||
} | ||
|
||
fn main() { | ||
// `Default::default()` is used when `volume` is not specified. | ||
let missing_volume = PlayReceiver::from_derive_input(&parse_quote! { | ||
#[play] | ||
struct Player; | ||
}) | ||
.unwrap(); | ||
assert_eq!(Volume::Normal, missing_volume.volume); | ||
|
||
// `#[darling(word)]` unit variant is used when `volume` is specified as a word with no value. | ||
let empty_volume = PlayReceiver::from_derive_input(&parse_quote! { | ||
#[play(volume)] | ||
struct Player; | ||
}) | ||
.unwrap(); | ||
assert_eq!(Volume::Low, empty_volume.volume); | ||
|
||
// Specified `volume` value is used when provided. | ||
let unit_variant_volume = PlayReceiver::from_derive_input(&parse_quote! { | ||
#[play(volume(high))] | ||
struct Player; | ||
}) | ||
.unwrap(); | ||
assert_eq!(Volume::High, unit_variant_volume.volume); | ||
let newtype_volume = PlayReceiver::from_derive_input(&parse_quote! { | ||
#[play(volume(dB = 100))] | ||
struct Player; | ||
}) | ||
.unwrap(); | ||
assert_eq!(Volume::Decibels(100), newtype_volume.volume); | ||
|
||
// Multiple `volume` values result in an error. | ||
let err = PlayReceiver::from_derive_input(&parse_quote! { | ||
#[play(volume(low, dB = 20))] | ||
struct Player; | ||
}) | ||
.unwrap_err(); | ||
assert_eq!( | ||
err.to_string(), | ||
Error::too_many_items(1).at("volume").to_string() | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
use darling::FromMeta; | ||
|
||
#[derive(FromMeta)] | ||
enum Choice { | ||
#[darling(word)] | ||
A, | ||
#[darling(word)] | ||
B, | ||
C, | ||
} | ||
|
||
fn main() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
error: `#[darling(word)]` can only be applied to one variant | ||
--> tests/compile-fail/duplicate_word_across_variants.rs:5:15 | ||
| | ||
5 | #[darling(word)] | ||
| ^^^^ | ||
|
||
error: `#[darling(word)]` can only be applied to one variant | ||
--> tests/compile-fail/duplicate_word_across_variants.rs:7:15 | ||
| | ||
7 | #[darling(word)] | ||
| ^^^^ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
use darling::FromMeta; | ||
|
||
#[derive(FromMeta)] | ||
enum Choice { | ||
#[darling(word, word)] | ||
A, | ||
B, | ||
} | ||
|
||
fn main() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
error: Duplicate field `word` | ||
--> tests/compile-fail/duplicate_word_on_variant.rs:5:21 | ||
| | ||
5 | #[darling(word, word)] | ||
| ^^^^ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
use darling::FromMeta; | ||
|
||
#[derive(FromMeta)] | ||
enum Meta { | ||
Unit, | ||
#[darling(word)] | ||
NotUnit(String) | ||
} | ||
|
||
fn main() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
error: Unexpected field: `word`. `#[darling(word)]` can only be applied to a unit variant | ||
--> tests/compile-fail/word_on_wrong_variant_type.rs:6:15 | ||
| | ||
6 | #[darling(word)] | ||
| ^^^^ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
use darling::{FromDeriveInput, FromMeta}; | ||
use syn::parse_quote; | ||
|
||
#[derive(Debug, FromMeta, PartialEq, Eq)] | ||
enum Dolor { | ||
Sit, | ||
#[darling(word)] | ||
Amet, | ||
} | ||
|
||
impl Default for Dolor { | ||
fn default() -> Self { | ||
Dolor::Sit | ||
} | ||
} | ||
|
||
#[derive(FromDeriveInput)] | ||
#[darling(attributes(hello))] | ||
struct Receiver { | ||
#[darling(default)] | ||
example: Dolor, | ||
} | ||
|
||
#[test] | ||
fn missing_meta() { | ||
let di = Receiver::from_derive_input(&parse_quote! { | ||
#[hello] | ||
struct Example; | ||
}) | ||
.unwrap(); | ||
|
||
assert_eq!(Dolor::Sit, di.example); | ||
} | ||
|
||
#[test] | ||
fn empty_meta() { | ||
let di = Receiver::from_derive_input(&parse_quote! { | ||
#[hello(example)] | ||
struct Example; | ||
}) | ||
.unwrap(); | ||
|
||
assert_eq!(Dolor::Amet, di.example); | ||
} |
Oops, something went wrong.