use syn::LitStr;
use syn::Result;
use syn::Token;
use syn::meta::ParseNestedMeta;
use syn::token::Paren;
pub(crate) fn parse_serialize_name(meta: &ParseNestedMeta<'_>, control: &str) -> Result<Option<LitStr>> {
if meta.input.peek(Token![=]) {
return Ok(Some(meta.value()?.parse()?));
}
if !meta.input.peek(Paren) {
return Err(meta.error(format!(
"Redact serde expects `{control} = \"...\"` or `{control}(serialize = \"...\", deserialize = \"...\")`",
)));
}
let mut serialize = None;
let mut deserialize_seen = false;
let mut item_seen = false;
meta.parse_nested_meta(|direction| {
item_seen = true;
if direction.path.is_ident("serialize") {
if serialize.is_some() {
return Err(direction.error(format!("Redact serde `{control}` repeats `serialize`",)));
}
serialize = Some(direction.value()?.parse()?);
} else if direction.path.is_ident("deserialize") {
if deserialize_seen {
return Err(direction.error(format!("Redact serde `{control}` repeats `deserialize`",)));
}
let _: LitStr = direction.value()?.parse()?;
deserialize_seen = true;
} else {
return Err(direction.error(format!(
"Redact serde `{control}` supports only `serialize` and `deserialize`",
)));
}
Ok(())
})?;
if !item_seen {
return Err(meta.error(format!(
"Redact serde `{control}` requires `serialize` or `deserialize`",
)));
}
Ok(serialize)
}