Skip to content

Commit ebcc1b3

Browse files
committed
New trait impls
Improved HashMap trait impl
1 parent a14ac7c commit ebcc1b3

3 files changed

Lines changed: 45 additions & 4 deletions

File tree

core/src/from_meta_item.rs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ use {Error, Result};
2727
/// * As a raw string literal, e.g. `foo = r#"hello "world""#`.
2828
///
2929
/// ## ()
30-
/// * Word with no value specified, e.g. `foo`. This is best used with `Option`.
30+
/// * Word with no value specified, e.g. `foo`. This is best used with `Option`.
31+
/// See `darling::util::Flag` for a more strongly-typed alternative.
3132
///
3233
/// ## Option
3334
/// * Any format produces `Some`.
@@ -189,6 +190,14 @@ impl<T: FromMetaItem> FromMetaItem for Result<T> {
189190
}
190191
}
191192

193+
/// Parses the meta-item, and in case of error preserves a copy of the input for
194+
/// later analysis.
195+
impl<T: FromMetaItem> FromMetaItem for ::std::result::Result<T, MetaItem> {
196+
fn from_meta_item(item: &MetaItem) -> Result<Self> {
197+
T::from_meta_item(item).map(Ok).or_else(|_| Ok(Err(item.clone())))
198+
}
199+
}
200+
192201
impl<T: FromMetaItem> FromMetaItem for Rc<T> {
193202
fn from_meta_item(item: &MetaItem) -> Result<Self> {
194203
Ok(Rc::new(FromMetaItem::from_meta_item(item)?))
@@ -214,7 +223,11 @@ impl<V: FromMetaItem> FromMetaItem for HashMap<String, V> {
214223
if let syn::NestedMetaItem::MetaItem(ref inner) = *item {
215224
match map.entry(inner.name().to_string()) {
216225
Entry::Occupied(_) => return Err(Error::duplicate_field(inner.name())),
217-
Entry::Vacant(entry) => { entry.insert(FromMetaItem::from_meta_item(inner)?); }
226+
Entry::Vacant(entry) => {
227+
entry.insert(
228+
FromMetaItem::from_meta_item(inner).map_err(|e| e.at(inner.name()))?
229+
);
230+
}
218231
}
219232
}
220233
}
@@ -229,7 +242,7 @@ impl<V: FromMetaItem> FromMetaItem for HashMap<String, V> {
229242
mod tests {
230243
use syn;
231244

232-
use {FromMetaItem};
245+
use {FromMetaItem, Result};
233246

234247
/// parse a string as a syn::MetaItem instance.
235248
fn pmi(s: &str) -> ::std::result::Result<syn::MetaItem, String> {
@@ -290,4 +303,12 @@ mod tests {
290303

291304
assert_eq!(fmi::<HashMap<String, bool>>(r#"ignore(hello, world = false, there = "true")"#), comparison);
292305
}
306+
307+
/// Tests that fallible parsing will always produce an outer `Ok` (from `fmi`),
308+
/// and will accurately preserve the inner contents.
309+
#[test]
310+
fn darling_result_succeeds() {
311+
fmi::<Result<()>>("ignore").unwrap();
312+
fmi::<Result<()>>("ignore(world)").unwrap_err();
313+
}
293314
}

core/src/from_variant.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use syn::Variant;
1+
use syn::{self, Variant};
22

33
use Result;
44

@@ -18,4 +18,16 @@ impl FromVariant for Variant {
1818
fn from_variant(variant: &Variant) -> Result<Self> {
1919
Ok(variant.clone())
2020
}
21+
}
22+
23+
impl FromVariant for syn::Ident {
24+
fn from_variant(variant: &Variant) -> Result<Self> {
25+
Ok(variant.ident.clone())
26+
}
27+
}
28+
29+
impl FromVariant for Vec<syn::Attribute> {
30+
fn from_variant(variant: &Variant) -> Result<Self> {
31+
Ok(variant.attrs.clone())
32+
}
2133
}

core/src/util/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//! Utility types for attribute parsing.
2+
23
use std::ops::{Deref, Not, BitAnd, BitOr};
34

45
use syn;
@@ -17,6 +18,7 @@ pub use self::over_ride::Override;
1718
pub struct Flag(Option<()>);
1819

1920
impl Flag {
21+
/// Creates a new `Flag` which corresponds to the presence of a value.
2022
pub fn present() -> Self {
2123
Flag(Some(()))
2224
}
@@ -47,6 +49,12 @@ impl From<bool> for Flag {
4749
}
4850
}
4951

52+
impl From<Option<()>> for Flag {
53+
fn from(v: Option<()>) -> Self {
54+
Flag::from(v.is_some())
55+
}
56+
}
57+
5058
impl PartialEq<Option<()>> for Flag {
5159
fn eq(&self, rhs: &Option<()>) -> bool {
5260
self.0 == *rhs

0 commit comments

Comments
 (0)