linked_data_core/
rdf_metadata.rs1use 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}