xml-data-derive 0.0.1

Derive macros for generic XML parsing and serializing
Documentation
use syn::{
	Attribute,
	Lit,
	Meta,
	NestedMeta,
};

pub fn all_attributes(attrs: &[Attribute]) -> impl Iterator<Item = NestedMeta> + '_ {
	attrs.iter().filter_map(|attr| {
		if attr.path.is_ident("xml_data") {
			match attr.parse_meta() {
				Ok(Meta::List(meta)) => Some(meta.nested.into_iter()),
				Ok(_) => {
					panic!("expected #[xml_data(...)]");
				}
				Err(err) => {
					panic!("#[xml_data]: {}", err);
				}
			}
		} else {
			None
		}
	}).flatten()
}

pub fn single_nested(meta: &Meta) -> Option<&NestedMeta> {
	match meta {
		Meta::Path(_) => None,
		Meta::List(l) => {
			if l.nested.len() > 1 {
				panic!("only single argument allowed for argument");
			}
			l.nested.first()
		}
		Meta::NameValue(_) => panic!("Expect single nested argument"),
	}
}

pub fn single_lit(meta: &Meta) -> Option<&syn::Lit> {
	match meta {
		Meta::Path(_) => None,
		Meta::List(l) => {
			if l.nested.len() > 1 {
				panic!("only single argument allowed for argument");
			}
			match l.nested.first() {
				Some(NestedMeta::Lit(l)) => Some(l),
				Some(NestedMeta::Meta(m)) => single_lit(m),
				None => None,
			}
		}
		Meta::NameValue(nv) => Some(&nv.lit),
	}
}

pub fn string_lit(meta: &Meta) -> Option<String> {
	single_lit(meta).map(|l| {
		if let Lit::Str(s) = l {
			s.value()
		} else {
			panic!("invalid literal; expected string");
		}
	})
}