blob: 6d661ba760687699975d16c66ad323b129e80a91 [file] [log] [blame]
David Tolnay7db73692019-10-20 14:51:12 -04001use crate::syntax::{Derive, Doc};
2use proc_macro2::Ident;
3use syn::parse::{ParseStream, Parser};
4use syn::{Attribute, Error, LitStr, Path, Result, Token};
5
6pub(super) fn parse_doc(attrs: &[Attribute]) -> Result<Doc> {
7 let mut doc = Doc::new();
8 let derives = None;
9 parse(attrs, &mut doc, derives)?;
10 Ok(doc)
11}
12
13pub(super) fn parse(
14 attrs: &[Attribute],
15 doc: &mut Doc,
16 mut derives: Option<&mut Vec<Ident>>,
17) -> Result<()> {
18 for attr in attrs {
19 if attr.path.is_ident("doc") {
20 let lit = parse_doc_attribute.parse2(attr.tokens.clone())?;
21 doc.push(lit);
22 continue;
23 } else if attr.path.is_ident("derive") {
24 if let Some(derives) = &mut derives {
25 derives.extend(attr.parse_args_with(parse_derive_attribute)?);
26 continue;
27 }
28 }
29 return Err(Error::new_spanned(attr, "unsupported attribute"));
30 }
31 Ok(())
32}
33
34fn parse_doc_attribute(input: ParseStream) -> Result<LitStr> {
35 input.parse::<Token![=]>()?;
36 let lit: LitStr = input.parse()?;
37 Ok(lit)
38}
39
40fn parse_derive_attribute(input: ParseStream) -> Result<Vec<Ident>> {
41 input
42 .parse_terminated::<Path, Token![,]>(Path::parse_mod_style)?
43 .into_iter()
44 .map(|path| match path.get_ident() {
45 Some(ident) if Derive::from(ident).is_some() => Ok(ident.clone()),
46 _ => Err(Error::new_spanned(path, "unsupported derive")),
47 })
48 .collect()
49}
50
51impl Derive {
52 pub fn from(ident: &Ident) -> Option<Self> {
53 match ident.to_string().as_str() {
54 "Clone" => Some(Derive::Clone),
55 "Copy" => Some(Derive::Copy),
56 _ => None,
57 }
58 }
59}
60
61impl AsRef<str> for Derive {
62 fn as_ref(&self) -> &str {
63 match self {
64 Derive::Clone => "Clone",
65 Derive::Copy => "Copy",
66 }
67 }
68}