Skip to main content

linked_data_core/
rdf_metadata.rs

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