use oxiri::Iri;
use snafu::ResultExt;
use syn::spanned::Spanned;
use crate::attributes::ast::VariantAttribute;
use crate::attributes::parse_ld_attributes;
use crate::prefix_mappings::PrefixMappings;
use crate::{Error, InvalidMappingSnafu};
pub struct RdfVariantAttributes {
pub predicate_path: PredicatePath,
}
pub enum PredicatePath {
ChainedPath {
to_blank: Iri<String>,
from_blank: Iri<String>,
},
Predicate(Iri<String>),
}
impl RdfVariantAttributes {
pub fn try_from_attrs(
variant: &syn::Variant,
inner_attrs: Vec<syn::Attribute>,
outer_attrs: Vec<syn::Attribute>,
prefix_mappings: &PrefixMappings,
) -> Result<Self, Error> {
let inner_attrs: Vec<VariantAttribute> = parse_ld_attributes(&inner_attrs)?;
let outer_attrs: Vec<VariantAttribute> = parse_ld_attributes(&outer_attrs)?;
let unpack_variant_attrs = |attrs: &[VariantAttribute]| -> Result<Option<Iri<String>>, Error> {
if let Some(VariantAttribute::Iri(iri)) = attrs.get(1) {
Err(Error::MultipleIris { span: iri.span() })
} else {
attrs
.first()
.map(|variant_attr| match variant_attr {
VariantAttribute::Iri(lit_str) => lit_str,
})
.map(|lit_str| {
prefix_mappings
.expand(lit_str.value())
.context(InvalidMappingSnafu {
span: lit_str.span(),
})
})
.transpose()
}
};
let inner_attr = unpack_variant_attrs(&inner_attrs)?;
let outer_attr = unpack_variant_attrs(&outer_attrs)?;
match (inner_attr, outer_attr) {
(None, None) => Err(Error::MissingIriAttribute {
span: variant.span(),
}),
(None, Some(outer_iri)) => Ok(RdfVariantAttributes {
predicate_path: PredicatePath::Predicate(outer_iri),
}),
(Some(inner_iri), None) => Ok(RdfVariantAttributes {
predicate_path: PredicatePath::Predicate(inner_iri),
}),
(Some(to_blank), Some(from_blank)) => Ok(RdfVariantAttributes {
predicate_path: PredicatePath::ChainedPath {
to_blank,
from_blank,
},
}),
}
}
}