linked_data_core/
rdf_metadata.rs

1use std::marker::PhantomData;
2
3use iref::IriBuf;
4use proc_macro_error::abort;
5use syn::DeriveInput;
6use syn::spanned::Spanned;
7use syn::visit::Visit;
8
9use crate::attributes::field::RdfFieldAttributes;
10use crate::attributes::r#type::{RdfEnumAttributes, RdfStructAttributes};
11use crate::attributes::variant::{PredicatePath, RdfVariantAttributes};
12use crate::prefix_mappings::PrefixMappings;
13use crate::{Error, TokenGenerator};
14
15pub enum RdfType<F> {
16  Enum(RdfEnum<F>),
17  Struct(RdfStruct<F>),
18}
19
20pub struct RdfEnum<G> {
21  attributes: RdfEnumAttributes,
22  pub ident: syn::Ident,
23  pub variants: Vec<RdfVariant<G>>,
24}
25
26pub struct RdfVariant<G> {
27  attributes: RdfVariantAttributes,
28  pub ty: syn::Type,
29  _generator: PhantomData<G>,
30}
31
32pub struct RdfStruct<G> {
33  attributes: RdfStructAttributes,
34  pub ident: syn::Ident,
35  pub fields: Vec<RdfField<G>>,
36}
37
38#[derive(Debug)]
39pub struct RdfField<G> {
40  attributes: RdfFieldAttributes,
41  pub ty: syn::Type,
42  _generator: PhantomData<G>,
43}
44
45pub fn unwrap_or_abort<T>(result: Result<T, Error>) -> T {
46  match result {
47    Ok(value) => value,
48    Err(error) => abort!(error.span(), error),
49  }
50}
51
52impl<G: TokenGenerator> RdfType<G> {
53  pub fn from_derive(derive_input: DeriveInput) -> Self {
54    unwrap_or_abort(Self::try_from_derive(derive_input))
55  }
56
57  fn try_from_derive(derive_input: DeriveInput) -> Result<Self, Error> {
58    match derive_input.data {
59      syn::Data::Struct(data) => {
60        let mut r#struct = RdfStruct {
61          ident: derive_input.ident,
62          attributes: derive_input.attrs.try_into()?,
63          fields: vec![],
64        };
65        r#struct.visit_data_struct(&data);
66        Ok(RdfType::Struct(r#struct))
67      }
68      syn::Data::Enum(data) => {
69        let mut r#enum = RdfEnum {
70          ident: derive_input.ident,
71          attributes: derive_input.attrs.try_into()?,
72          variants: vec![],
73        };
74        r#enum.visit_data_enum(&data);
75        Ok(RdfType::Enum(r#enum))
76      }
77      syn::Data::Union(data_union) => Err(Error::UnionType {
78        span: data_union.union_token.span(),
79      }),
80    }
81  }
82}
83
84impl<'ast, F> Visit<'ast> for RdfEnum<F> {
85  fn visit_variant(&mut self, variant: &'ast syn::Variant) {
86    let variant = unwrap_or_abort(RdfVariant::from_variant(
87      variant.clone(),
88      &self.attributes.prefix_mappings,
89    ));
90    self.variants.push(variant);
91  }
92}
93
94impl<F> RdfVariant<F> {
95  fn from_variant(variant: syn::Variant, prefix_mappings: &PrefixMappings) -> Result<Self, Error> {
96    let mut fields = variant.fields.iter();
97
98    let Some(field) = fields.next() else {
99      return Err(Error::UnitVariant {
100        span: variant.span(),
101      });
102    };
103
104    if let Some(field) = fields.next() {
105      return Err(Error::StructVariant { span: field.span() });
106    }
107
108    Ok(RdfVariant {
109      attributes: RdfVariantAttributes::try_from_attrs(
110        &variant,
111        field.attrs.clone(),
112        variant.attrs.clone(),
113        prefix_mappings,
114      )?,
115      ty: field.ty.clone(),
116      _generator: PhantomData,
117    })
118  }
119
120  pub fn predicate_path(&self) -> &PredicatePath {
121    &self.attributes.predicate_path
122  }
123}
124
125impl<G> RdfStruct<G> {
126  pub fn type_iri(&self) -> Option<&IriBuf> {
127    self.attributes.r#type.as_ref()
128  }
129
130  pub fn prefix_mappings(&self) -> &PrefixMappings {
131    &self.attributes.prefix_mappings
132  }
133}
134
135impl<'ast, F> Visit<'ast> for RdfStruct<F> {
136  fn visit_field(&mut self, field: &'ast syn::Field) {
137    let rdf_field = unwrap_or_abort(RdfField::try_from_field(
138      field.clone(),
139      &self.attributes.prefix_mappings,
140    ));
141    self.fields.push(rdf_field);
142  }
143}
144
145impl<F> RdfField<F> {
146  fn try_from_field(field: syn::Field, prefix_mappings: &PrefixMappings) -> Result<Self, Error> {
147    let attributes = RdfFieldAttributes::try_from_attrs(field.attrs, prefix_mappings)?;
148
149    Ok(RdfField {
150      attributes,
151      ty: field.ty,
152      _generator: PhantomData,
153    })
154  }
155
156  pub fn is_flattened(&self) -> bool {
157    self.attributes.flatten
158  }
159
160  pub fn is_graph(&self) -> bool {
161    self.attributes.is_graph
162  }
163
164  pub fn is_ignored(&self) -> bool {
165    self.attributes.ignore
166  }
167
168  pub fn predicate(&self) -> Option<&IriBuf> {
169    self.attributes.predicate.as_ref()
170  }
171
172  pub fn is_id(&self) -> bool {
173    self.attributes.is_id
174  }
175}