1 use std::borrow::Cow; 2 use std::cell::RefCell; 3 use std::collections::hash_map::HashMap; 4 use std::collections::HashSet; 5 use std::hash::BuildHasher; 6 use std::rc::Rc; 7 use std::sync::atomic::AtomicBool; 8 use std::sync::Arc; 9 10 use syn::{Expr, Lit, Meta}; 11 12 use crate::ast::NestedMeta; 13 use crate::util::path_to_string; 14 use crate::{Error, Result}; 15 16 /// Create an instance from an item in an attribute declaration. 17 /// 18 /// # Implementing `FromMeta` 19 /// * Do not take a dependency on the `ident` of the passed-in meta item. The ident will be set by the field name of the containing struct. 20 /// * Implement only the `from_*` methods that you intend to support. The default implementations will return useful errors. 21 /// 22 /// # Provided Implementations 23 /// ## bool 24 /// 25 /// * Word with no value specified - becomes `true`. 26 /// * As a boolean literal, e.g. `foo = true`. 27 /// * As a string literal, e.g. `foo = "true"`. 28 /// 29 /// ## char 30 /// * As a char literal, e.g. `foo = '#'`. 31 /// * As a string literal consisting of a single character, e.g. `foo = "#"`. 32 /// 33 /// ## String 34 /// * As a string literal, e.g. `foo = "hello"`. 35 /// * As a raw string literal, e.g. `foo = r#"hello "world""#`. 36 /// 37 /// ## Number 38 /// * As a string literal, e.g. `foo = "-25"`. 39 /// * As an unquoted positive value, e.g. `foo = 404`. Negative numbers must be in quotation marks. 40 /// 41 /// ## () 42 /// * Word with no value specified, e.g. `foo`. This is best used with `Option`. 43 /// See `darling::util::Flag` for a more strongly-typed alternative. 44 /// 45 /// ## Option 46 /// * Any format produces `Some`. 47 /// 48 /// ## `Result<T, darling::Error>` 49 /// * Allows for fallible parsing; will populate the target field with the result of the 50 /// parse attempt. 51 pub trait FromMeta: Sized { from_nested_meta(item: &NestedMeta) -> Result<Self>52 fn from_nested_meta(item: &NestedMeta) -> Result<Self> { 53 (match *item { 54 NestedMeta::Lit(ref lit) => Self::from_value(lit), 55 NestedMeta::Meta(ref mi) => Self::from_meta(mi), 56 }) 57 .map_err(|e| e.with_span(item)) 58 } 59 60 /// Create an instance from a `syn::Meta` by dispatching to the format-appropriate 61 /// trait function. This generally should not be overridden by implementers. 62 /// 63 /// # Error Spans 64 /// If this method is overridden and can introduce errors that weren't passed up from 65 /// other `from_meta` calls, the override must call `with_span` on the error using the 66 /// `item` to make sure that the emitted diagnostic points to the correct location in 67 /// source code. from_meta(item: &Meta) -> Result<Self>68 fn from_meta(item: &Meta) -> Result<Self> { 69 (match *item { 70 Meta::Path(_) => Self::from_word(), 71 Meta::List(ref value) => { 72 Self::from_list(&NestedMeta::parse_meta_list(value.tokens.clone())?[..]) 73 } 74 Meta::NameValue(ref value) => Self::from_expr(&value.value), 75 }) 76 .map_err(|e| e.with_span(item)) 77 } 78 79 /// When a field is omitted from a parent meta-item, `from_none` is used to attempt 80 /// recovery before a missing field error is generated. 81 /// 82 /// **Most types should not override this method.** `darling` already allows field-level 83 /// missing-field recovery using `#[darling(default)]` and `#[darling(default = "...")]`, 84 /// and users who add a `String` field to their `FromMeta`-deriving struct would be surprised 85 /// if they get back `""` instead of a missing field error when that field is omitted. 86 /// 87 /// The primary use-case for this is `Option<T>` fields gracefully handlling absence without 88 /// needing `#[darling(default)]`. from_none() -> Option<Self>89 fn from_none() -> Option<Self> { 90 None 91 } 92 93 /// Create an instance from the presence of the word in the attribute with no 94 /// additional options specified. from_word() -> Result<Self>95 fn from_word() -> Result<Self> { 96 Err(Error::unsupported_format("word")) 97 } 98 99 /// Create an instance from a list of nested meta items. 100 #[allow(unused_variables)] from_list(items: &[NestedMeta]) -> Result<Self>101 fn from_list(items: &[NestedMeta]) -> Result<Self> { 102 Err(Error::unsupported_format("list")) 103 } 104 105 /// Create an instance from a literal value of either `foo = "bar"` or `foo("bar")`. 106 /// This dispatches to the appropriate method based on the type of literal encountered, 107 /// and generally should not be overridden by implementers. 108 /// 109 /// # Error Spans 110 /// If this method is overridden, the override must make sure to add `value`'s span 111 /// information to the returned error by calling `with_span(value)` on the `Error` instance. from_value(value: &Lit) -> Result<Self>112 fn from_value(value: &Lit) -> Result<Self> { 113 (match *value { 114 Lit::Bool(ref b) => Self::from_bool(b.value), 115 Lit::Str(ref s) => Self::from_string(&s.value()), 116 Lit::Char(ref ch) => Self::from_char(ch.value()), 117 _ => Err(Error::unexpected_lit_type(value)), 118 }) 119 .map_err(|e| e.with_span(value)) 120 } 121 from_expr(expr: &Expr) -> Result<Self>122 fn from_expr(expr: &Expr) -> Result<Self> { 123 match *expr { 124 Expr::Lit(ref lit) => Self::from_value(&lit.lit), 125 Expr::Group(ref group) => { 126 // syn may generate this invisible group delimiter when the input to the darling 127 // proc macro (specifically, the attributes) are generated by a 128 // macro_rules! (e.g. propagating a macro_rules!'s expr) 129 // Since we want to basically ignore these invisible group delimiters, 130 // we just propagate the call to the inner expression. 131 Self::from_expr(&group.expr) 132 } 133 _ => Err(Error::unexpected_expr_type(expr)), 134 } 135 .map_err(|e| e.with_span(expr)) 136 } 137 138 /// Create an instance from a char literal in a value position. 139 #[allow(unused_variables)] from_char(value: char) -> Result<Self>140 fn from_char(value: char) -> Result<Self> { 141 Err(Error::unexpected_type("char")) 142 } 143 144 /// Create an instance from a string literal in a value position. 145 #[allow(unused_variables)] from_string(value: &str) -> Result<Self>146 fn from_string(value: &str) -> Result<Self> { 147 Err(Error::unexpected_type("string")) 148 } 149 150 /// Create an instance from a bool literal in a value position. 151 #[allow(unused_variables)] from_bool(value: bool) -> Result<Self>152 fn from_bool(value: bool) -> Result<Self> { 153 Err(Error::unexpected_type("bool")) 154 } 155 } 156 157 // FromMeta impls for std and syn types. 158 159 impl FromMeta for () { from_word() -> Result<Self>160 fn from_word() -> Result<Self> { 161 Ok(()) 162 } 163 } 164 165 impl FromMeta for bool { from_word() -> Result<Self>166 fn from_word() -> Result<Self> { 167 Ok(true) 168 } 169 170 #[allow(clippy::wrong_self_convention)] // false positive from_bool(value: bool) -> Result<Self>171 fn from_bool(value: bool) -> Result<Self> { 172 Ok(value) 173 } 174 from_string(value: &str) -> Result<Self>175 fn from_string(value: &str) -> Result<Self> { 176 value.parse().map_err(|_| Error::unknown_value(value)) 177 } 178 } 179 180 impl FromMeta for AtomicBool { from_meta(mi: &Meta) -> Result<Self>181 fn from_meta(mi: &Meta) -> Result<Self> { 182 FromMeta::from_meta(mi) 183 .map(AtomicBool::new) 184 .map_err(|e| e.with_span(mi)) 185 } 186 } 187 188 impl FromMeta for char { 189 #[allow(clippy::wrong_self_convention)] // false positive from_char(value: char) -> Result<Self>190 fn from_char(value: char) -> Result<Self> { 191 Ok(value) 192 } 193 from_string(s: &str) -> Result<Self>194 fn from_string(s: &str) -> Result<Self> { 195 let mut chars = s.chars(); 196 let char1 = chars.next(); 197 let char2 = chars.next(); 198 199 if let (Some(char), None) = (char1, char2) { 200 Ok(char) 201 } else { 202 Err(Error::unexpected_type("string")) 203 } 204 } 205 } 206 207 impl FromMeta for String { from_string(s: &str) -> Result<Self>208 fn from_string(s: &str) -> Result<Self> { 209 Ok(s.to_string()) 210 } 211 } 212 213 impl FromMeta for std::path::PathBuf { from_string(s: &str) -> Result<Self>214 fn from_string(s: &str) -> Result<Self> { 215 Ok(s.into()) 216 } 217 } 218 219 /// Generate an impl of `FromMeta` that will accept strings which parse to numbers or 220 /// integer literals. 221 macro_rules! from_meta_num { 222 ($ty:ident) => { 223 impl FromMeta for $ty { 224 fn from_string(s: &str) -> Result<Self> { 225 s.parse().map_err(|_| Error::unknown_value(s)) 226 } 227 228 fn from_value(value: &Lit) -> Result<Self> { 229 (match *value { 230 Lit::Str(ref s) => Self::from_string(&s.value()), 231 Lit::Int(ref s) => Ok(s.base10_parse::<$ty>().unwrap()), 232 _ => Err(Error::unexpected_lit_type(value)), 233 }) 234 .map_err(|e| e.with_span(value)) 235 } 236 } 237 }; 238 } 239 240 from_meta_num!(u8); 241 from_meta_num!(u16); 242 from_meta_num!(u32); 243 from_meta_num!(u64); 244 from_meta_num!(u128); 245 from_meta_num!(usize); 246 from_meta_num!(i8); 247 from_meta_num!(i16); 248 from_meta_num!(i32); 249 from_meta_num!(i64); 250 from_meta_num!(i128); 251 from_meta_num!(isize); 252 253 /// Generate an impl of `FromMeta` that will accept strings which parse to floats or 254 /// float literals. 255 macro_rules! from_meta_float { 256 ($ty:ident) => { 257 impl FromMeta for $ty { 258 fn from_string(s: &str) -> Result<Self> { 259 s.parse().map_err(|_| Error::unknown_value(s)) 260 } 261 262 fn from_value(value: &Lit) -> Result<Self> { 263 (match *value { 264 Lit::Str(ref s) => Self::from_string(&s.value()), 265 Lit::Float(ref s) => Ok(s.base10_parse::<$ty>().unwrap()), 266 _ => Err(Error::unexpected_lit_type(value)), 267 }) 268 .map_err(|e| e.with_span(value)) 269 } 270 } 271 }; 272 } 273 274 from_meta_float!(f32); 275 from_meta_float!(f64); 276 277 /// Parsing support for punctuated. This attempts to preserve span information 278 /// when available, but also supports parsing strings with the call site as the 279 /// emitted span. 280 impl<T: syn::parse::Parse, P: syn::parse::Parse> FromMeta for syn::punctuated::Punctuated<T, P> { from_value(value: &Lit) -> Result<Self>281 fn from_value(value: &Lit) -> Result<Self> { 282 if let Lit::Str(ref ident) = *value { 283 ident 284 .parse_with(syn::punctuated::Punctuated::parse_terminated) 285 .map_err(|_| Error::unknown_lit_str_value(ident)) 286 } else { 287 Err(Error::unexpected_lit_type(value)) 288 } 289 } 290 } 291 292 /// Support for arbitrary expressions as values in a meta item. 293 /// 294 /// For backwards-compatibility to versions of `darling` based on `syn` 1, 295 /// string literals will be "unwrapped" and their contents will be parsed 296 /// as an expression. 297 /// 298 /// See [`util::parse_expr`](crate::util::parse_expr) for functions to provide 299 /// alternate parsing modes for this type. 300 impl FromMeta for syn::Expr { from_expr(expr: &Expr) -> Result<Self>301 fn from_expr(expr: &Expr) -> Result<Self> { 302 match expr { 303 Expr::Lit(syn::ExprLit { 304 lit: lit @ syn::Lit::Str(_), 305 .. 306 }) => Self::from_value(lit), 307 Expr::Group(group) => Self::from_expr(&group.expr), // see FromMeta::from_expr 308 _ => Ok(expr.clone()), 309 } 310 } 311 from_string(value: &str) -> Result<Self>312 fn from_string(value: &str) -> Result<Self> { 313 syn::parse_str(value).map_err(|_| Error::unknown_value(value)) 314 } 315 from_value(value: &::syn::Lit) -> Result<Self>316 fn from_value(value: &::syn::Lit) -> Result<Self> { 317 if let ::syn::Lit::Str(ref v) = *value { 318 v.parse::<syn::Expr>() 319 .map_err(|_| Error::unknown_lit_str_value(v)) 320 } else { 321 Err(Error::unexpected_lit_type(value)) 322 } 323 } 324 } 325 326 /// Parser for paths that supports both quote-wrapped and bare values. 327 impl FromMeta for syn::Path { from_string(value: &str) -> Result<Self>328 fn from_string(value: &str) -> Result<Self> { 329 syn::parse_str(value).map_err(|_| Error::unknown_value(value)) 330 } 331 from_value(value: &::syn::Lit) -> Result<Self>332 fn from_value(value: &::syn::Lit) -> Result<Self> { 333 if let ::syn::Lit::Str(ref v) = *value { 334 v.parse().map_err(|_| Error::unknown_lit_str_value(v)) 335 } else { 336 Err(Error::unexpected_lit_type(value)) 337 } 338 } 339 from_expr(expr: &Expr) -> Result<Self>340 fn from_expr(expr: &Expr) -> Result<Self> { 341 match expr { 342 Expr::Lit(lit) => Self::from_value(&lit.lit), 343 Expr::Path(path) => Ok(path.path.clone()), 344 Expr::Group(group) => Self::from_expr(&group.expr), // see FromMeta::from_expr 345 _ => Err(Error::unexpected_expr_type(expr)), 346 } 347 } 348 } 349 350 impl FromMeta for syn::Ident { from_string(value: &str) -> Result<Self>351 fn from_string(value: &str) -> Result<Self> { 352 syn::parse_str(value).map_err(|_| Error::unknown_value(value)) 353 } 354 from_value(value: &syn::Lit) -> Result<Self>355 fn from_value(value: &syn::Lit) -> Result<Self> { 356 if let syn::Lit::Str(ref v) = *value { 357 v.parse().map_err(|_| Error::unknown_lit_str_value(v)) 358 } else { 359 Err(Error::unexpected_lit_type(value)) 360 } 361 } 362 from_expr(expr: &Expr) -> Result<Self>363 fn from_expr(expr: &Expr) -> Result<Self> { 364 match expr { 365 Expr::Lit(lit) => Self::from_value(&lit.lit), 366 // All idents are paths, but not all paths are idents - 367 // the get_ident() method does additional validation to 368 // make sure the path is actually an ident. 369 Expr::Path(path) => match path.path.get_ident() { 370 Some(ident) => Ok(ident.clone()), 371 None => Err(Error::unexpected_expr_type(expr)), 372 }, 373 Expr::Group(group) => Self::from_expr(&group.expr), // see FromMeta::from_expr 374 _ => Err(Error::unexpected_expr_type(expr)), 375 } 376 } 377 } 378 379 /// Adapter for various expression types. 380 /// 381 /// Prior to syn 2.0, darling supported arbitrary expressions as long as they 382 /// were wrapped in quotation marks. This was helpful for people writing 383 /// libraries that needed expressions, but it now creates an ambiguity when 384 /// parsing a meta item. 385 /// 386 /// To address this, the macro supports both formats; if it cannot parse the 387 /// item as an expression of the right type and the passed-in expression is 388 /// a string literal, it will fall back to parsing the string contents. 389 macro_rules! from_syn_expr_type { 390 ($ty:path, $variant:ident) => { 391 impl FromMeta for $ty { 392 fn from_expr(expr: &syn::Expr) -> Result<Self> { 393 match expr { 394 syn::Expr::$variant(body) => Ok(body.clone()), 395 syn::Expr::Lit(expr_lit) => Self::from_value(&expr_lit.lit), 396 syn::Expr::Group(group) => Self::from_expr(&group.expr), // see FromMeta::from_expr 397 _ => Err(Error::unexpected_expr_type(expr)), 398 } 399 } 400 401 fn from_value(value: &::syn::Lit) -> Result<Self> { 402 if let syn::Lit::Str(body) = &value { 403 body.parse::<$ty>() 404 .map_err(|_| Error::unknown_lit_str_value(body)) 405 } else { 406 Err(Error::unexpected_lit_type(value)) 407 } 408 } 409 } 410 }; 411 } 412 413 from_syn_expr_type!(syn::ExprArray, Array); 414 from_syn_expr_type!(syn::ExprPath, Path); 415 416 /// Adapter from `syn::parse::Parse` to `FromMeta` for items that cannot 417 /// be expressed in a [`syn::MetaNameValue`]. 418 /// 419 /// This cannot be a blanket impl, due to the `syn::Lit` family's need to handle non-string values. 420 /// Therefore, we use a macro and a lot of impls. 421 macro_rules! from_syn_parse { 422 ($ty:path) => { 423 impl FromMeta for $ty { 424 fn from_string(value: &str) -> Result<Self> { 425 syn::parse_str(value).map_err(|_| Error::unknown_value(value)) 426 } 427 428 fn from_value(value: &::syn::Lit) -> Result<Self> { 429 if let ::syn::Lit::Str(ref v) = *value { 430 v.parse::<$ty>() 431 .map_err(|_| Error::unknown_lit_str_value(v)) 432 } else { 433 Err(Error::unexpected_lit_type(value)) 434 } 435 } 436 } 437 }; 438 } 439 440 from_syn_parse!(syn::Type); 441 from_syn_parse!(syn::TypeArray); 442 from_syn_parse!(syn::TypeBareFn); 443 from_syn_parse!(syn::TypeGroup); 444 from_syn_parse!(syn::TypeImplTrait); 445 from_syn_parse!(syn::TypeInfer); 446 from_syn_parse!(syn::TypeMacro); 447 from_syn_parse!(syn::TypeNever); 448 from_syn_parse!(syn::TypeParam); 449 from_syn_parse!(syn::TypeParen); 450 from_syn_parse!(syn::TypePath); 451 from_syn_parse!(syn::TypePtr); 452 from_syn_parse!(syn::TypeReference); 453 from_syn_parse!(syn::TypeSlice); 454 from_syn_parse!(syn::TypeTraitObject); 455 from_syn_parse!(syn::TypeTuple); 456 from_syn_parse!(syn::Visibility); 457 from_syn_parse!(syn::WhereClause); 458 459 macro_rules! from_numeric_array { 460 ($ty:ident) => { 461 /// Parsing an unsigned integer array, i.e. `example = "[1, 2, 3, 4]"`. 462 impl FromMeta for Vec<$ty> { 463 fn from_expr(expr: &syn::Expr) -> Result<Self> { 464 match expr { 465 syn::Expr::Array(expr_array) => expr_array 466 .elems 467 .iter() 468 .map(|expr| { 469 let unexpected = || { 470 Error::custom("Expected array of unsigned integers").with_span(expr) 471 }; 472 match expr { 473 Expr::Lit(lit) => $ty::from_value(&lit.lit), 474 Expr::Group(group) => match &*group.expr { 475 Expr::Lit(lit) => $ty::from_value(&lit.lit), 476 _ => Err(unexpected()), 477 }, 478 _ => Err(unexpected()), 479 } 480 }) 481 .collect::<Result<Vec<$ty>>>(), 482 syn::Expr::Lit(expr_lit) => Self::from_value(&expr_lit.lit), 483 syn::Expr::Group(group) => Self::from_expr(&group.expr), // see FromMeta::from_expr 484 _ => Err(Error::unexpected_expr_type(expr)), 485 } 486 } 487 488 fn from_value(value: &Lit) -> Result<Self> { 489 let expr_array = syn::ExprArray::from_value(value)?; 490 Self::from_expr(&syn::Expr::Array(expr_array)) 491 } 492 } 493 }; 494 } 495 496 from_numeric_array!(u8); 497 from_numeric_array!(u16); 498 from_numeric_array!(u32); 499 from_numeric_array!(u64); 500 from_numeric_array!(usize); 501 502 impl FromMeta for syn::Lit { from_value(value: &Lit) -> Result<Self>503 fn from_value(value: &Lit) -> Result<Self> { 504 Ok(value.clone()) 505 } 506 } 507 508 macro_rules! from_meta_lit { 509 ($impl_ty:path, $lit_variant:path) => { 510 impl FromMeta for $impl_ty { 511 fn from_value(value: &Lit) -> Result<Self> { 512 if let $lit_variant(ref value) = *value { 513 Ok(value.clone()) 514 } else { 515 Err(Error::unexpected_lit_type(value)) 516 } 517 } 518 } 519 520 impl FromMeta for Vec<$impl_ty> { 521 fn from_list(items: &[NestedMeta]) -> Result<Self> { 522 items 523 .iter() 524 .map(<$impl_ty as FromMeta>::from_nested_meta) 525 .collect() 526 } 527 528 fn from_value(value: &syn::Lit) -> Result<Self> { 529 let expr_array = syn::ExprArray::from_value(value)?; 530 Self::from_expr(&syn::Expr::Array(expr_array)) 531 } 532 533 fn from_expr(expr: &syn::Expr) -> Result<Self> { 534 match expr { 535 syn::Expr::Array(expr_array) => expr_array 536 .elems 537 .iter() 538 .map(<$impl_ty as FromMeta>::from_expr) 539 .collect::<Result<Vec<_>>>(), 540 syn::Expr::Lit(expr_lit) => Self::from_value(&expr_lit.lit), 541 syn::Expr::Group(g) => Self::from_expr(&g.expr), 542 _ => Err(Error::unexpected_expr_type(expr)), 543 } 544 } 545 } 546 }; 547 } 548 549 from_meta_lit!(syn::LitInt, Lit::Int); 550 from_meta_lit!(syn::LitFloat, Lit::Float); 551 from_meta_lit!(syn::LitStr, Lit::Str); 552 from_meta_lit!(syn::LitByte, Lit::Byte); 553 from_meta_lit!(syn::LitByteStr, Lit::ByteStr); 554 from_meta_lit!(syn::LitChar, Lit::Char); 555 from_meta_lit!(syn::LitBool, Lit::Bool); 556 from_meta_lit!(proc_macro2::Literal, Lit::Verbatim); 557 558 impl FromMeta for syn::Meta { from_meta(value: &syn::Meta) -> Result<Self>559 fn from_meta(value: &syn::Meta) -> Result<Self> { 560 Ok(value.clone()) 561 } 562 } 563 564 impl FromMeta for Vec<syn::WherePredicate> { from_string(value: &str) -> Result<Self>565 fn from_string(value: &str) -> Result<Self> { 566 syn::WhereClause::from_string(&format!("where {}", value)) 567 .map(|c| c.predicates.into_iter().collect()) 568 } 569 from_value(value: &Lit) -> Result<Self>570 fn from_value(value: &Lit) -> Result<Self> { 571 if let syn::Lit::Str(s) = value { 572 syn::WhereClause::from_value(&syn::Lit::Str(syn::LitStr::new( 573 &format!("where {}", s.value()), 574 value.span(), 575 ))) 576 .map(|c| c.predicates.into_iter().collect()) 577 } else { 578 Err(Error::unexpected_lit_type(value)) 579 } 580 } 581 } 582 583 impl FromMeta for ident_case::RenameRule { from_string(value: &str) -> Result<Self>584 fn from_string(value: &str) -> Result<Self> { 585 value.parse().map_err(|_| Error::unknown_value(value)) 586 } 587 } 588 589 impl<T: FromMeta> FromMeta for Option<T> { from_none() -> Option<Self>590 fn from_none() -> Option<Self> { 591 Some(None) 592 } 593 from_meta(item: &Meta) -> Result<Self>594 fn from_meta(item: &Meta) -> Result<Self> { 595 FromMeta::from_meta(item).map(Some) 596 } 597 } 598 599 impl<T: FromMeta> FromMeta for Box<T> { from_none() -> Option<Self>600 fn from_none() -> Option<Self> { 601 T::from_none().map(Box::new) 602 } 603 from_meta(item: &Meta) -> Result<Self>604 fn from_meta(item: &Meta) -> Result<Self> { 605 FromMeta::from_meta(item).map(Box::new) 606 } 607 } 608 609 impl<T: FromMeta> FromMeta for Result<T> { from_none() -> Option<Self>610 fn from_none() -> Option<Self> { 611 T::from_none().map(Ok) 612 } 613 from_meta(item: &Meta) -> Result<Self>614 fn from_meta(item: &Meta) -> Result<Self> { 615 Ok(FromMeta::from_meta(item)) 616 } 617 } 618 619 /// Parses the meta-item, and in case of error preserves a copy of the input for 620 /// later analysis. 621 impl<T: FromMeta> FromMeta for ::std::result::Result<T, Meta> { from_meta(item: &Meta) -> Result<Self>622 fn from_meta(item: &Meta) -> Result<Self> { 623 T::from_meta(item) 624 .map(Ok) 625 .or_else(|_| Ok(Err(item.clone()))) 626 } 627 } 628 629 impl<T: FromMeta> FromMeta for Rc<T> { from_none() -> Option<Self>630 fn from_none() -> Option<Self> { 631 T::from_none().map(Rc::new) 632 } 633 from_meta(item: &Meta) -> Result<Self>634 fn from_meta(item: &Meta) -> Result<Self> { 635 FromMeta::from_meta(item).map(Rc::new) 636 } 637 } 638 639 impl<T: FromMeta> FromMeta for Arc<T> { from_none() -> Option<Self>640 fn from_none() -> Option<Self> { 641 T::from_none().map(Arc::new) 642 } 643 from_meta(item: &Meta) -> Result<Self>644 fn from_meta(item: &Meta) -> Result<Self> { 645 FromMeta::from_meta(item).map(Arc::new) 646 } 647 } 648 649 impl<T: FromMeta> FromMeta for RefCell<T> { from_none() -> Option<Self>650 fn from_none() -> Option<Self> { 651 T::from_none().map(RefCell::new) 652 } 653 from_meta(item: &Meta) -> Result<Self>654 fn from_meta(item: &Meta) -> Result<Self> { 655 FromMeta::from_meta(item).map(RefCell::new) 656 } 657 } 658 659 /// Trait to convert from a path into an owned key for a map. 660 trait KeyFromPath: Sized { from_path(path: &syn::Path) -> Result<Self>661 fn from_path(path: &syn::Path) -> Result<Self>; to_display(&self) -> Cow<'_, str>662 fn to_display(&self) -> Cow<'_, str>; 663 } 664 665 impl KeyFromPath for String { from_path(path: &syn::Path) -> Result<Self>666 fn from_path(path: &syn::Path) -> Result<Self> { 667 Ok(path_to_string(path)) 668 } 669 to_display(&self) -> Cow<'_, str>670 fn to_display(&self) -> Cow<'_, str> { 671 Cow::Borrowed(self) 672 } 673 } 674 675 impl KeyFromPath for syn::Path { from_path(path: &syn::Path) -> Result<Self>676 fn from_path(path: &syn::Path) -> Result<Self> { 677 Ok(path.clone()) 678 } 679 to_display(&self) -> Cow<'_, str>680 fn to_display(&self) -> Cow<'_, str> { 681 Cow::Owned(path_to_string(self)) 682 } 683 } 684 685 impl KeyFromPath for syn::Ident { from_path(path: &syn::Path) -> Result<Self>686 fn from_path(path: &syn::Path) -> Result<Self> { 687 if path.segments.len() == 1 688 && path.leading_colon.is_none() 689 && path.segments[0].arguments.is_empty() 690 { 691 Ok(path.segments[0].ident.clone()) 692 } else { 693 Err(Error::custom("Key must be an identifier").with_span(path)) 694 } 695 } 696 to_display(&self) -> Cow<'_, str>697 fn to_display(&self) -> Cow<'_, str> { 698 Cow::Owned(self.to_string()) 699 } 700 } 701 702 macro_rules! hash_map { 703 ($key:ty) => { 704 impl<V: FromMeta, S: BuildHasher + Default> FromMeta for HashMap<$key, V, S> { 705 fn from_list(nested: &[NestedMeta]) -> Result<Self> { 706 // Convert the nested meta items into a sequence of (path, value result) result tuples. 707 // An outer Err means no (key, value) structured could be found, while an Err in the 708 // second position of the tuple means that value was rejected by FromMeta. 709 // 710 // We defer key conversion into $key so that we don't lose span information in the case 711 // of String keys; we'll need it for good duplicate key errors later. 712 let pairs = nested 713 .iter() 714 .map(|item| -> Result<(&syn::Path, Result<V>)> { 715 match *item { 716 NestedMeta::Meta(ref inner) => { 717 let path = inner.path(); 718 Ok(( 719 path, 720 FromMeta::from_meta(inner).map_err(|e| e.at_path(&path)), 721 )) 722 } 723 NestedMeta::Lit(_) => Err(Error::unsupported_format("expression")), 724 } 725 }); 726 727 let mut errors = Error::accumulator(); 728 // We need to track seen keys separately from the final map, since a seen key with an 729 // Err value won't go into the final map but should trigger a duplicate field error. 730 // 731 // This is a set of $key rather than Path to avoid the possibility that a key type 732 // parses two paths of different values to the same key value. 733 let mut seen_keys = HashSet::with_capacity(nested.len()); 734 735 // The map to return in the Ok case. Its size will always be exactly nested.len(), 736 // since otherwise ≥1 field had a problem and the entire map is dropped immediately 737 // when the function returns `Err`. 738 let mut map = HashMap::with_capacity_and_hasher(nested.len(), Default::default()); 739 740 for item in pairs { 741 if let Some((path, value)) = errors.handle(item) { 742 let key: $key = match KeyFromPath::from_path(path) { 743 Ok(k) => k, 744 Err(e) => { 745 errors.push(e); 746 747 // Surface value errors even under invalid keys 748 errors.handle(value); 749 750 continue; 751 } 752 }; 753 754 let already_seen = seen_keys.contains(&key); 755 756 if already_seen { 757 errors.push(Error::duplicate_field(&key.to_display()).with_span(path)); 758 } 759 760 match value { 761 Ok(_) if already_seen => {} 762 Ok(val) => { 763 map.insert(key.clone(), val); 764 } 765 Err(e) => { 766 errors.push(e); 767 } 768 } 769 770 seen_keys.insert(key); 771 } 772 } 773 774 errors.finish_with(map) 775 } 776 } 777 }; 778 } 779 780 // This is done as a macro rather than a blanket impl to avoid breaking backwards compatibility 781 // with 0.12.x, while still sharing the same impl. 782 hash_map!(String); 783 hash_map!(syn::Ident); 784 hash_map!(syn::Path); 785 786 /// Tests for `FromMeta` implementations. Wherever the word `ignore` appears in test input, 787 /// it should not be considered by the parsing. 788 #[cfg(test)] 789 mod tests { 790 use proc_macro2::TokenStream; 791 use quote::quote; 792 use syn::parse_quote; 793 794 use crate::{Error, FromMeta, Result}; 795 796 /// parse a string as a syn::Meta instance. pm(tokens: TokenStream) -> ::std::result::Result<syn::Meta, String>797 fn pm(tokens: TokenStream) -> ::std::result::Result<syn::Meta, String> { 798 let attribute: syn::Attribute = parse_quote!(#[#tokens]); 799 Ok(attribute.meta) 800 } 801 802 #[track_caller] fm<T: FromMeta>(tokens: TokenStream) -> T803 fn fm<T: FromMeta>(tokens: TokenStream) -> T { 804 FromMeta::from_meta(&pm(tokens).expect("Tests should pass well-formed input")) 805 .expect("Tests should pass valid input") 806 } 807 808 #[test] unit_succeeds()809 fn unit_succeeds() { 810 fm::<()>(quote!(ignore)); 811 } 812 813 #[test] 814 #[allow(clippy::bool_assert_comparison)] bool_succeeds()815 fn bool_succeeds() { 816 // word format 817 assert_eq!(fm::<bool>(quote!(ignore)), true); 818 819 // bool literal 820 assert_eq!(fm::<bool>(quote!(ignore = true)), true); 821 assert_eq!(fm::<bool>(quote!(ignore = false)), false); 822 823 // string literals 824 assert_eq!(fm::<bool>(quote!(ignore = "true")), true); 825 assert_eq!(fm::<bool>(quote!(ignore = "false")), false); 826 } 827 828 #[test] char_succeeds()829 fn char_succeeds() { 830 // char literal 831 assert_eq!(fm::<char>(quote!(ignore = '')), ''); 832 833 // string literal 834 assert_eq!(fm::<char>(quote!(ignore = "")), ''); 835 } 836 837 #[test] string_succeeds()838 fn string_succeeds() { 839 // cooked form 840 assert_eq!(&fm::<String>(quote!(ignore = "world")), "world"); 841 842 // raw form 843 assert_eq!(&fm::<String>(quote!(ignore = r#"world"#)), "world"); 844 } 845 846 #[test] pathbuf_succeeds()847 fn pathbuf_succeeds() { 848 assert_eq!( 849 fm::<std::path::PathBuf>(quote!(ignore = r#"C:\"#)), 850 std::path::PathBuf::from(r#"C:\"#) 851 ); 852 } 853 854 #[test] 855 #[allow(clippy::float_cmp)] // we want exact equality number_succeeds()856 fn number_succeeds() { 857 assert_eq!(fm::<u8>(quote!(ignore = "2")), 2u8); 858 assert_eq!(fm::<i16>(quote!(ignore = "-25")), -25i16); 859 assert_eq!(fm::<f64>(quote!(ignore = "1.4e10")), 1.4e10); 860 } 861 862 #[test] int_without_quotes()863 fn int_without_quotes() { 864 assert_eq!(fm::<u8>(quote!(ignore = 2)), 2u8); 865 assert_eq!(fm::<u16>(quote!(ignore = 255)), 255u16); 866 assert_eq!(fm::<u32>(quote!(ignore = 5000)), 5000u32); 867 868 // Check that we aren't tripped up by incorrect suffixes 869 assert_eq!(fm::<u32>(quote!(ignore = 5000i32)), 5000u32); 870 } 871 872 #[test] negative_int_without_quotes()873 fn negative_int_without_quotes() { 874 assert_eq!(fm::<i8>(quote!(ignore = -2)), -2i8); 875 assert_eq!(fm::<i32>(quote!(ignore = -255)), -255i32); 876 } 877 878 #[test] 879 #[allow(clippy::float_cmp)] // we want exact equality float_without_quotes()880 fn float_without_quotes() { 881 assert_eq!(fm::<f32>(quote!(ignore = 2.)), 2.0f32); 882 assert_eq!(fm::<f32>(quote!(ignore = 2.0)), 2.0f32); 883 assert_eq!(fm::<f64>(quote!(ignore = 1.4e10)), 1.4e10f64); 884 } 885 886 #[test] meta_succeeds()887 fn meta_succeeds() { 888 use syn::Meta; 889 890 assert_eq!( 891 fm::<Meta>(quote!(hello(world, today))), 892 pm(quote!(hello(world, today))).unwrap() 893 ); 894 } 895 896 #[test] hash_map_succeeds()897 fn hash_map_succeeds() { 898 use std::collections::HashMap; 899 900 let comparison = { 901 let mut c = HashMap::new(); 902 c.insert("hello".to_string(), true); 903 c.insert("world".to_string(), false); 904 c.insert("there".to_string(), true); 905 c 906 }; 907 908 assert_eq!( 909 fm::<HashMap<String, bool>>(quote!(ignore(hello, world = false, there = "true"))), 910 comparison 911 ); 912 } 913 914 /// Check that a `HashMap` cannot have duplicate keys, and that the generated error 915 /// is assigned a span to correctly target the diagnostic message. 916 #[test] hash_map_duplicate()917 fn hash_map_duplicate() { 918 use std::collections::HashMap; 919 920 let err: Result<HashMap<String, bool>> = 921 FromMeta::from_meta(&pm(quote!(ignore(hello, hello = false))).unwrap()); 922 923 let err = err.expect_err("Duplicate keys in HashMap should error"); 924 925 assert!(err.has_span()); 926 assert_eq!(err.to_string(), Error::duplicate_field("hello").to_string()); 927 } 928 929 #[test] hash_map_multiple_errors()930 fn hash_map_multiple_errors() { 931 use std::collections::HashMap; 932 933 let err = HashMap::<String, bool>::from_meta( 934 &pm(quote!(ignore(hello, hello = 3, hello = false))).unwrap(), 935 ) 936 .expect_err("Duplicates and bad values should error"); 937 938 assert_eq!(err.len(), 3); 939 let errors = err.into_iter().collect::<Vec<_>>(); 940 assert!(errors[0].has_span()); 941 assert!(errors[1].has_span()); 942 assert!(errors[2].has_span()); 943 } 944 945 #[test] hash_map_ident_succeeds()946 fn hash_map_ident_succeeds() { 947 use std::collections::HashMap; 948 use syn::parse_quote; 949 950 let comparison = { 951 let mut c = HashMap::<syn::Ident, bool>::new(); 952 c.insert(parse_quote!(first), true); 953 c.insert(parse_quote!(second), false); 954 c 955 }; 956 957 assert_eq!( 958 fm::<HashMap<syn::Ident, bool>>(quote!(ignore(first, second = false))), 959 comparison 960 ); 961 } 962 963 #[test] hash_map_ident_rejects_non_idents()964 fn hash_map_ident_rejects_non_idents() { 965 use std::collections::HashMap; 966 967 let err: Result<HashMap<syn::Ident, bool>> = 968 FromMeta::from_meta(&pm(quote!(ignore(first, the::second))).unwrap()); 969 970 err.unwrap_err(); 971 } 972 973 #[test] hash_map_path_succeeds()974 fn hash_map_path_succeeds() { 975 use std::collections::HashMap; 976 use syn::parse_quote; 977 978 let comparison = { 979 let mut c = HashMap::<syn::Path, bool>::new(); 980 c.insert(parse_quote!(first), true); 981 c.insert(parse_quote!(the::second), false); 982 c 983 }; 984 985 assert_eq!( 986 fm::<HashMap<syn::Path, bool>>(quote!(ignore(first, the::second = false))), 987 comparison 988 ); 989 } 990 991 /// Tests that fallible parsing will always produce an outer `Ok` (from `fm`), 992 /// and will accurately preserve the inner contents. 993 #[test] darling_result_succeeds()994 fn darling_result_succeeds() { 995 fm::<Result<()>>(quote!(ignore)).unwrap(); 996 fm::<Result<()>>(quote!(ignore(world))).unwrap_err(); 997 } 998 999 /// Test punctuated 1000 #[test] test_punctuated()1001 fn test_punctuated() { 1002 fm::<syn::punctuated::Punctuated<syn::FnArg, syn::token::Comma>>(quote!( 1003 ignore = "a: u8, b: Type" 1004 )); 1005 fm::<syn::punctuated::Punctuated<syn::Expr, syn::token::Comma>>(quote!(ignore = "a, b, c")); 1006 } 1007 1008 #[test] test_expr_array()1009 fn test_expr_array() { 1010 fm::<syn::ExprArray>(quote!(ignore = "[0x1, 0x2]")); 1011 fm::<syn::ExprArray>(quote!(ignore = "[\"Hello World\", \"Test Array\"]")); 1012 } 1013 1014 #[test] test_expr()1015 fn test_expr() { 1016 fm::<syn::Expr>(quote!(ignore = "x + y")); 1017 fm::<syn::Expr>(quote!(ignore = "an_object.method_call()")); 1018 fm::<syn::Expr>(quote!(ignore = "{ a_statement(); in_a_block }")); 1019 } 1020 1021 #[test] test_expr_without_quotes()1022 fn test_expr_without_quotes() { 1023 fm::<syn::Expr>(quote!(ignore = x + y)); 1024 fm::<syn::Expr>(quote!(ignore = an_object.method_call())); 1025 fm::<syn::Expr>(quote!( 1026 ignore = { 1027 a_statement(); 1028 in_a_block 1029 } 1030 )); 1031 } 1032 1033 #[test] test_expr_path()1034 fn test_expr_path() { 1035 fm::<syn::ExprPath>(quote!(ignore = "std::mem::replace")); 1036 fm::<syn::ExprPath>(quote!(ignore = "x")); 1037 fm::<syn::ExprPath>(quote!(ignore = "example::<Test>")); 1038 } 1039 1040 #[test] test_expr_path_without_quotes()1041 fn test_expr_path_without_quotes() { 1042 fm::<syn::ExprPath>(quote!(ignore = std::mem::replace)); 1043 fm::<syn::ExprPath>(quote!(ignore = x)); 1044 fm::<syn::ExprPath>(quote!(ignore = example::<Test>)); 1045 } 1046 1047 #[test] test_path_without_quotes()1048 fn test_path_without_quotes() { 1049 fm::<syn::Path>(quote!(ignore = std::mem::replace)); 1050 fm::<syn::Path>(quote!(ignore = x)); 1051 fm::<syn::Path>(quote!(ignore = example::<Test>)); 1052 } 1053 1054 #[test] test_number_array()1055 fn test_number_array() { 1056 assert_eq!(fm::<Vec<u8>>(quote!(ignore = [16, 0xff])), vec![0x10, 0xff]); 1057 assert_eq!( 1058 fm::<Vec<u16>>(quote!(ignore = "[32, 0xffff]")), 1059 vec![0x20, 0xffff] 1060 ); 1061 assert_eq!( 1062 fm::<Vec<u32>>(quote!(ignore = "[48, 0xffffffff]")), 1063 vec![0x30, 0xffffffff] 1064 ); 1065 assert_eq!( 1066 fm::<Vec<u64>>(quote!(ignore = "[64, 0xffffffffffffffff]")), 1067 vec![0x40, 0xffffffffffffffff] 1068 ); 1069 assert_eq!( 1070 fm::<Vec<usize>>(quote!(ignore = "[80, 0xffffffff]")), 1071 vec![0x50, 0xffffffff] 1072 ); 1073 } 1074 1075 #[test] test_lit_array()1076 fn test_lit_array() { 1077 fm::<Vec<syn::LitStr>>(quote!(ignore = "[\"Hello World\", \"Test Array\"]")); 1078 fm::<Vec<syn::LitStr>>(quote!(ignore = ["Hello World", "Test Array"])); 1079 fm::<Vec<syn::LitChar>>(quote!(ignore = "['a', 'b', 'c']")); 1080 fm::<Vec<syn::LitBool>>(quote!(ignore = "[true]")); 1081 fm::<Vec<syn::LitStr>>(quote!(ignore = "[]")); 1082 fm::<Vec<syn::LitStr>>(quote!(ignore = [])); 1083 fm::<Vec<syn::LitBool>>(quote!(ignore = [true, false])); 1084 } 1085 } 1086