use std::convert::TryFrom;
use syn::{Expr, ExprLit, ExprPath, Ident, Lit, LitBool, LitStr, Member};
use crate::api::RawMetadata;
pub struct Metadata {
pub description: LitStr,
pub method: Ident,
pub name: LitStr,
pub path: LitStr,
pub rate_limited: LitBool,
pub requires_authentication: LitBool,
}
impl TryFrom<RawMetadata> for Metadata {
type Error = syn::Error;
fn try_from(raw: RawMetadata) -> syn::Result<Self> {
let mut description = None;
let mut method = None;
let mut name = None;
let mut path = None;
let mut rate_limited = None;
let mut requires_authentication = None;
for field_value in raw.field_values {
let identifier = match field_value.member.clone() {
Member::Named(identifier) => identifier,
_ => panic!("expected Member::Named"),
};
let expr = field_value.expr.clone();
match &identifier.to_string()[..] {
"description" => match expr {
Expr::Lit(ExprLit { lit: Lit::Str(literal), .. }) => {
description = Some(literal);
}
_ => return Err(syn::Error::new_spanned(expr, "expected a string literal")),
},
"method" => match expr {
Expr::Path(ExprPath { ref path, .. }) if path.segments.len() == 1 => {
method = Some(path.segments[0].ident.clone());
}
_ => return Err(syn::Error::new_spanned(expr, "expected an identifier")),
},
"name" => match expr {
Expr::Lit(ExprLit { lit: Lit::Str(literal), .. }) => {
name = Some(literal);
}
_ => return Err(syn::Error::new_spanned(expr, "expected a string literal")),
},
"path" => match expr {
Expr::Lit(ExprLit { lit: Lit::Str(literal), .. }) => {
path = Some(literal);
}
_ => return Err(syn::Error::new_spanned(expr, "expected a string literal")),
},
"rate_limited" => match expr {
Expr::Lit(ExprLit { lit: Lit::Bool(literal), .. }) => {
rate_limited = Some(literal);
}
_ => return Err(syn::Error::new_spanned(expr, "expected a bool literal")),
},
"requires_authentication" => match expr {
Expr::Lit(ExprLit { lit: Lit::Bool(literal), .. }) => {
requires_authentication = Some(literal);
}
_ => return Err(syn::Error::new_spanned(expr, "expected a bool literal")),
},
_ => return Err(syn::Error::new_spanned(field_value, "unexpected field")),
}
}
let metadata_kw = raw.metadata_kw;
let missing_field =
|name| syn::Error::new_spanned(metadata_kw, format!("missing field `{}`", name));
Ok(Self {
description: description.ok_or_else(|| missing_field("description"))?,
method: method.ok_or_else(|| missing_field("method"))?,
name: name.ok_or_else(|| missing_field("name"))?,
path: path.ok_or_else(|| missing_field("path"))?,
rate_limited: rate_limited.ok_or_else(|| missing_field("rate_limited"))?,
requires_authentication: requires_authentication
.ok_or_else(|| missing_field("requires_authentication"))?,
})
}
}