gryf_derive/
lib.rs

1mod util;
2
3use proc_macro::TokenStream;
4use quote::quote;
5use syn::{DeriveInput, parse_macro_input};
6
7#[proc_macro_derive(GraphBase, attributes(graph, gryf_crate))]
8pub fn graph_base(tokens: TokenStream) -> TokenStream {
9    let input = parse_macro_input!(tokens as DeriveInput);
10
11    let gryf = util::get_gryf_path(&input);
12
13    let name = &input.ident;
14    let field = util::get_graph_field(&input);
15
16    let field_name = field.ident.as_ref().unwrap();
17    let field_type = &field.ty;
18
19    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
20    let where_clause = util::augment_where_clause(
21        where_clause,
22        vec![(field_type.clone(), quote! { #gryf::core::GraphBase })],
23    );
24
25    let implemented = quote! {
26        impl #impl_generics #gryf::core::GraphBase for #name #ty_generics #where_clause {
27            type VertexId = <#field_type as #gryf::core::GraphBase>::VertexId;
28            type EdgeId = <#field_type as #gryf::core::GraphBase>::EdgeId;
29            type EdgeType = <#field_type as #gryf::core::GraphBase>::EdgeType;
30
31            fn vertex_count_hint(&self) -> Option<usize> {
32                <#field_type as #gryf::core::GraphBase>::vertex_count_hint(&self.#field_name)
33            }
34
35            fn edge_count_hint(&self) -> Option<usize> {
36                <#field_type as #gryf::core::GraphBase>::edge_count_hint(&self.#field_name)
37            }
38        }
39    };
40
41    TokenStream::from(implemented)
42}
43
44#[proc_macro_derive(Neighbors, attributes(graph, gryf_crate))]
45pub fn neighbors(tokens: TokenStream) -> TokenStream {
46    let input = parse_macro_input!(tokens as DeriveInput);
47
48    let gryf = util::get_gryf_path(&input);
49
50    let name = &input.ident;
51    let field = util::get_graph_field(&input);
52
53    let field_name = field.ident.as_ref().unwrap();
54    let field_type = &field.ty;
55
56    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
57    let where_clause = util::augment_where_clause(
58        where_clause,
59        vec![(field_type.clone(), quote! { #gryf::core::Neighbors })],
60    );
61
62    let implemented = quote! {
63        impl #impl_generics #gryf::core::Neighbors for #name #ty_generics #where_clause {
64            type NeighborRef<'a> = <#field_type as #gryf::core::Neighbors>::NeighborRef<'a>
65            where
66                Self: 'a;
67
68            type NeighborsIter<'a> = <#field_type as #gryf::core::Neighbors>::NeighborsIter<'a>
69            where
70                Self: 'a;
71
72            fn neighbors_undirected(&self, from: &Self::VertexId) -> Self::NeighborsIter<'_> {
73                <#field_type as #gryf::core::Neighbors>::neighbors_undirected(&self.#field_name, from)
74            }
75
76            fn neighbors_directed(&self, from: &Self::VertexId, dir: #gryf::core::marker::Direction) -> Self::NeighborsIter<'_> {
77                <#field_type as #gryf::core::Neighbors>::neighbors_directed(&self.#field_name, from, dir)
78            }
79
80            fn degree_undirected(&self, id: &Self::VertexId) -> usize {
81                <#field_type as #gryf::core::Neighbors>::degree_undirected(&self.#field_name, id)
82            }
83
84            fn degree_directed(&self, id: &Self::VertexId, dir: #gryf::core::marker::Direction) -> usize {
85                <#field_type as #gryf::core::Neighbors>::degree_directed(&self.#field_name, id, dir)
86            }
87        }
88    };
89
90    TokenStream::from(implemented)
91}
92
93#[proc_macro_derive(VertexSet, attributes(graph, gryf_crate))]
94pub fn vertex_set(tokens: TokenStream) -> TokenStream {
95    let input = parse_macro_input!(tokens as DeriveInput);
96
97    let gryf = util::get_gryf_path(&input);
98
99    let name = &input.ident;
100    let field = util::get_graph_field(&input);
101
102    let field_name = field.ident.as_ref().unwrap();
103    let field_type = &field.ty;
104
105    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
106    let where_clause = util::augment_where_clause(
107        where_clause,
108        vec![(field_type.clone(), quote! { #gryf::core::VertexSet })],
109    );
110
111    let implemented = quote! {
112        impl #impl_generics #gryf::core::VertexSet for #name #ty_generics #where_clause {
113            type VerticesByIdIter<'a> = <#field_type as #gryf::core::VertexSet>::VerticesByIdIter<'a>
114            where
115                Self: 'a;
116
117            fn vertices_by_id(&self) -> Self::VerticesByIdIter<'_> {
118                <#field_type as #gryf::core::VertexSet>::vertices_by_id(&self.#field_name)
119            }
120
121            fn vertex_count(&self) -> usize {
122                <#field_type as #gryf::core::VertexSet>::vertex_count(&self.#field_name)
123            }
124
125            fn vertex_bound(&self) -> usize
126            where
127                Self::VertexId: #gryf::core::id::IntegerIdType,
128            {
129                <#field_type as #gryf::core::VertexSet>::vertex_bound(&self.#field_name)
130            }
131
132            fn contains_vertex(&self, id: &Self::VertexId) -> bool {
133                <#field_type as #gryf::core::VertexSet>::contains_vertex(&self.#field_name, id)
134            }
135
136            fn vertex_id_map(&self) -> #gryf::core::id::CompactIdMap<Self::VertexId> {
137                <#field_type as #gryf::core::VertexSet>::vertex_id_map(&self.#field_name)
138            }
139        }
140    };
141
142    TokenStream::from(implemented)
143}
144
145#[proc_macro_derive(EdgeSet, attributes(graph, gryf_crate))]
146pub fn edge_set(tokens: TokenStream) -> TokenStream {
147    let input = parse_macro_input!(tokens as DeriveInput);
148
149    let gryf = util::get_gryf_path(&input);
150
151    let name = &input.ident;
152    let field = util::get_graph_field(&input);
153
154    let field_name = field.ident.as_ref().unwrap();
155    let field_type = &field.ty;
156
157    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
158    let where_clause = util::augment_where_clause(
159        where_clause,
160        vec![(field_type.clone(), quote! { #gryf::core::EdgeSet })],
161    );
162
163    let implemented = quote! {
164        impl #impl_generics #gryf::core::EdgeSet for #name #ty_generics #where_clause {
165            type EdgesByIdIter<'a> = <#field_type as #gryf::core::EdgeSet>::EdgesByIdIter<'a>
166            where
167                Self: 'a;
168
169            type EdgeIdIter<'a> = <#field_type as #gryf::core::EdgeSet>::EdgeIdIter<'a>
170            where
171                Self: 'a;
172
173            fn edges_by_id(&self) -> Self::EdgesByIdIter<'_> {
174                <#field_type as #gryf::core::EdgeSet>::edges_by_id(&self.#field_name)
175            }
176
177            fn edge_id(&self, from: &Self::VertexId, to: &Self::VertexId) -> Self::EdgeIdIter<'_> {
178                <#field_type as #gryf::core::EdgeSet>::edge_id(&self.#field_name, from, to)
179            }
180
181            fn endpoints(&self, id: &Self::EdgeId) -> Option<(Self::VertexId, Self::VertexId)> {
182                <#field_type as #gryf::core::EdgeSet>::endpoints(&self.#field_name, id)
183            }
184
185            fn edge_count(&self) -> usize {
186                <#field_type as #gryf::core::EdgeSet>::edge_count(&self.#field_name)
187            }
188
189            fn edge_bound(&self) -> usize
190            where
191                Self::EdgeId: #gryf::core::id::IntegerIdType,
192            {
193                <#field_type as #gryf::core::EdgeSet>::edge_bound(&self.#field_name)
194            }
195
196            fn contains_edge(&self, id: &Self::EdgeId) -> bool {
197                <#field_type as #gryf::core::EdgeSet>::contains_edge(&self.#field_name, id)
198            }
199
200            fn contains_edge_between(&self, from: &Self::VertexId, to: &Self::VertexId) -> bool {
201                <#field_type as #gryf::core::EdgeSet>::contains_edge_between(&self.#field_name, from, to)
202            }
203
204            fn edge_id_any(&self, from: &Self::VertexId, to: &Self::VertexId) -> Option<Self::EdgeId> {
205                <#field_type as #gryf::core::EdgeSet>::edge_id_any(&self.#field_name, from, to)
206            }
207
208            fn edge_id_map(&self) -> #gryf::core::id::CompactIdMap<Self::EdgeId> {
209                <#field_type as #gryf::core::EdgeSet>::edge_id_map(&self.#field_name)
210            }
211        }
212    };
213
214    TokenStream::from(implemented)
215}
216
217#[proc_macro_derive(GraphRef, attributes(graph, gryf_crate))]
218pub fn graph_ref(tokens: TokenStream) -> TokenStream {
219    let input = parse_macro_input!(tokens as DeriveInput);
220
221    let gryf = util::get_gryf_path(&input);
222
223    let name = &input.ident;
224    let field = util::get_graph_field(&input);
225
226    let field_name = field.ident.as_ref().unwrap();
227    let field_type = &field.ty;
228
229    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
230    let impl_generics = util::augment_impl_generics_if_necessary(impl_generics, vec!["V", "E"]);
231    let where_clause = util::augment_where_clause(
232        where_clause,
233        vec![(field_type.clone(), quote! { #gryf::core::GraphRef<V, E> })],
234    );
235
236    let implemented = quote! {
237        impl #impl_generics #gryf::core::GraphRef<V, E> for #name #ty_generics #where_clause {
238            type VertexRef<'a> = <#field_type as #gryf::core::GraphRef<V, E>>::VertexRef<'a>
239            where
240                Self: 'a,
241                V: 'a;
242
243            type VerticesIter<'a> = <#field_type as #gryf::core::GraphRef<V, E>>::VerticesIter<'a>
244            where
245                Self: 'a,
246                V: 'a;
247
248            type EdgeRef<'a> = <#field_type as #gryf::core::GraphRef<V, E>>::EdgeRef<'a>
249            where
250                Self: 'a,
251                E: 'a;
252
253            type EdgesIter<'a> = <#field_type as #gryf::core::GraphRef<V, E>>::EdgesIter<'a>
254            where
255                Self: 'a,
256                E: 'a;
257
258            fn vertices(&self) -> Self::VerticesIter<'_> {
259                <#field_type as #gryf::core::GraphRef<V, E>>::vertices(&self.#field_name)
260            }
261
262            fn edges(&self) -> Self::EdgesIter<'_> {
263                <#field_type as #gryf::core::GraphRef<V, E>>::edges(&self.#field_name)
264            }
265
266            fn vertex(&self, id: &Self::VertexId) -> Option<&V> {
267                <#field_type as #gryf::core::GraphRef<V, E>>::vertex(&self.#field_name, id)
268            }
269
270            fn edge(&self, id: &Self::EdgeId) -> Option<&E> {
271                <#field_type as #gryf::core::GraphRef<V, E>>::edge(&self.#field_name, id)
272            }
273
274            fn find_vertex(&self, vertex: &V) -> Option<Self::VertexId>
275            where
276                V: Eq,
277            {
278                <#field_type as #gryf::core::GraphRef<V, E>>::find_vertex(&self.#field_name, vertex)
279            }
280        }
281    };
282
283    TokenStream::from(implemented)
284}
285
286#[proc_macro_derive(GraphMut, attributes(graph, gryf_crate))]
287pub fn graph_mut(tokens: TokenStream) -> TokenStream {
288    let input = parse_macro_input!(tokens as DeriveInput);
289
290    let gryf = util::get_gryf_path(&input);
291
292    let name = &input.ident;
293    let field = util::get_graph_field(&input);
294
295    let field_name = field.ident.as_ref().unwrap();
296    let field_type = &field.ty;
297
298    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
299    let impl_generics = util::augment_impl_generics_if_necessary(impl_generics, vec!["V", "E"]);
300    let where_clause = util::augment_where_clause(
301        where_clause,
302        vec![(field_type.clone(), quote! { #gryf::core::GraphMut<V, E> })],
303    );
304
305    let implemented = quote! {
306        impl #impl_generics #gryf::core::GraphMut<V, E> for #name #ty_generics #where_clause {
307            fn vertex_mut(&mut self, id: &Self::VertexId) -> Option<&mut V> {
308                <#field_type as #gryf::core::GraphMut<V, E>>::vertex_mut(&mut self.#field_name, id)
309            }
310
311            fn edge_mut(&mut self, id: &Self::EdgeId) -> Option<&mut E> {
312                <#field_type as #gryf::core::GraphMut<V, E>>::edge_mut(&mut self.#field_name, id)
313            }
314
315            fn try_replace_vertex(
316                &mut self,
317                id: &Self::VertexId,
318                vertex: V,
319            ) -> Result<V, #gryf::core::error::ReplaceVertexError<V>> {
320                <#field_type as #gryf::core::GraphMut<V, E>>::try_replace_vertex(&mut self.#field_name, id, vertex)
321            }
322
323            fn replace_vertex(&mut self, id: &Self::VertexId, vertex: V) -> V {
324                <#field_type as #gryf::core::GraphMut<V, E>>::replace_vertex(&mut self.#field_name, id, vertex)
325            }
326
327            fn try_replace_edge(&mut self, id: &Self::EdgeId, edge: E) -> Result<E, #gryf::core::error::ReplaceEdgeError<E>> {
328                <#field_type as #gryf::core::GraphMut<V, E>>::try_replace_edge(&mut self.#field_name, id, edge)
329            }
330
331            fn replace_edge(&mut self, id: &Self::EdgeId, edge: E) -> E {
332                <#field_type as #gryf::core::GraphMut<V, E>>::replace_edge(&mut self.#field_name, id, edge)
333            }
334        }
335    };
336
337    TokenStream::from(implemented)
338}
339
340#[proc_macro_derive(GraphAdd, attributes(graph, gryf_crate))]
341pub fn graph_add(tokens: TokenStream) -> TokenStream {
342    let input = parse_macro_input!(tokens as DeriveInput);
343
344    let gryf = util::get_gryf_path(&input);
345
346    let name = &input.ident;
347    let field = util::get_graph_field(&input);
348
349    let field_name = field.ident.as_ref().unwrap();
350    let field_type = &field.ty;
351
352    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
353    let impl_generics = util::augment_impl_generics_if_necessary(impl_generics, vec!["V", "E"]);
354    let where_clause = util::augment_where_clause(
355        where_clause,
356        vec![(field_type.clone(), quote! { #gryf::core::GraphAdd<V, E> })],
357    );
358
359    let implemented = quote! {
360        impl #impl_generics #gryf::core::GraphAdd<V, E> for #name #ty_generics #where_clause {
361            fn try_add_vertex(&mut self, vertex: V) -> Result<Self::VertexId, #gryf::core::error::AddVertexError<V>> {
362                <#field_type as #gryf::core::GraphAdd<V, E>>::try_add_vertex(&mut self.#field_name, vertex)
363            }
364
365            fn try_add_edge(
366                &mut self,
367                from: &Self::VertexId,
368                to: &Self::VertexId,
369                edge: E,
370            ) -> Result<Self::EdgeId, #gryf::core::error::AddEdgeError<E>> {
371                <#field_type as #gryf::core::GraphAdd<V, E>>::try_add_edge(&mut self.#field_name, from, to, edge)
372            }
373
374            fn add_vertex(&mut self, vertex: V) -> Self::VertexId {
375                <#field_type as #gryf::core::GraphAdd<V, E>>::add_vertex(&mut self.#field_name, vertex)
376            }
377
378            fn try_get_or_add_vertex(&mut self, vertex: V) -> Result<Self::VertexId, #gryf::core::error::AddVertexError<V>>
379            where
380                V: Eq,
381            {
382                <#field_type as #gryf::core::GraphAdd<V, E>>::try_get_or_add_vertex(&mut self.#field_name, vertex)
383            }
384
385            fn get_or_add_vertex(&mut self, vertex: V) -> Self::VertexId
386            where
387                V: Eq,
388            {
389                <#field_type as #gryf::core::GraphAdd<V, E>>::get_or_add_vertex(&mut self.#field_name, vertex)
390            }
391
392            fn add_edge(&mut self, from: &Self::VertexId, to: &Self::VertexId, edge: E) -> Self::EdgeId {
393                <#field_type as #gryf::core::GraphAdd<V, E>>::add_edge(&mut self.#field_name, from, to, edge)
394            }
395
396            fn try_add_edge_connecting(
397                &mut self,
398                from: V,
399                to: V,
400                edge: E,
401            ) -> Result<Self::EdgeId, #gryf::core::error::AddEdgeConnectingError<V, E>>
402            where
403                V: Eq,
404            {
405                <#field_type as #gryf::core::GraphAdd<V, E>>::try_add_edge_connecting(&mut self.#field_name, from, to, edge)
406            }
407
408            fn add_edge_connecting(&mut self, from: V, to: V, edge: E) -> Self::EdgeId
409            where
410                V: Eq,
411            {
412                <#field_type as #gryf::core::GraphAdd<V, E>>::add_edge_connecting(&mut self.#field_name, from, to, edge)
413            }
414        }
415    };
416
417    TokenStream::from(implemented)
418}
419
420#[proc_macro_derive(GraphFull, attributes(graph, gryf_crate))]
421pub fn graph_full(tokens: TokenStream) -> TokenStream {
422    let input = parse_macro_input!(tokens as DeriveInput);
423
424    let gryf = util::get_gryf_path(&input);
425
426    let name = &input.ident;
427    let field = util::get_graph_field(&input);
428
429    let field_name = field.ident.as_ref().unwrap();
430    let field_type = &field.ty;
431
432    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
433    let impl_generics = util::augment_impl_generics_if_necessary(impl_generics, vec!["V", "E"]);
434    let where_clause = util::augment_where_clause(
435        where_clause,
436        vec![(field_type.clone(), quote! { #gryf::core::GraphFull<V, E> })],
437    );
438
439    let implemented = quote! {
440        impl #impl_generics #gryf::core::GraphFull<V, E> for #name #ty_generics #where_clause {
441            fn remove_vertex(&mut self, id: &Self::VertexId) -> Option<V> {
442                <#field_type as #gryf::core::GraphFull<V, E>>::remove_vertex(&mut self.#field_name, id)
443            }
444
445            fn remove_edge(&mut self, id: &Self::EdgeId) -> Option<E> {
446                <#field_type as #gryf::core::GraphFull<V, E>>::remove_edge(&mut self.#field_name, id)
447            }
448
449            fn clear(&mut self) {
450                <#field_type as #gryf::core::GraphFull<V, E>>::clear(&mut self.#field_name)
451            }
452
453            fn remove_edges_between(&mut self, from: &Self::VertexId, to: &Self::VertexId) {
454                <#field_type as #gryf::core::GraphFull<V, E>>::remove_edges_between(&mut self.#field_name, from, to)
455            }
456
457            fn remove_edge_any_between(&mut self, from: &Self::VertexId, to: &Self::VertexId) -> Option<E> {
458                <#field_type as #gryf::core::GraphFull<V, E>>::remove_edge_any_between(&mut self.#field_name, from, to)
459            }
460
461            fn clear_edges(&mut self) {
462                <#field_type as #gryf::core::GraphFull<V, E>>::clear_edges(&mut self.#field_name)
463            }
464        }
465    };
466
467    TokenStream::from(implemented)
468}
469
470#[proc_macro_derive(MultiEdge, attributes(graph, gryf_crate))]
471pub fn multi_edge(tokens: TokenStream) -> TokenStream {
472    let input = parse_macro_input!(tokens as DeriveInput);
473
474    let gryf = util::get_gryf_path(&input);
475
476    let name = &input.ident;
477    let field = util::get_graph_field(&input);
478
479    let field_type = &field.ty;
480
481    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
482    let where_clause = util::augment_where_clause(
483        where_clause,
484        vec![(field_type.clone(), quote! { #gryf::core::props::MultiEdge })],
485    );
486
487    let implemented = quote! {
488        impl #impl_generics #gryf::core::props::MultiEdge for #name #ty_generics #where_clause {}
489    };
490
491    TokenStream::from(implemented)
492}
493
494#[proc_macro_derive(Guarantee, attributes(graph, gryf_crate))]
495pub fn guarantee(tokens: TokenStream) -> TokenStream {
496    let input = parse_macro_input!(tokens as DeriveInput);
497
498    let gryf = util::get_gryf_path(&input);
499
500    let name = &input.ident;
501    let field = util::get_graph_field(&input);
502
503    let field_type = &field.ty;
504
505    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
506    let where_clause = util::augment_where_clause(
507        where_clause,
508        vec![(field_type.clone(), quote! { #gryf::core::props::Guarantee })],
509    );
510
511    let implemented = quote! {
512        impl #impl_generics #gryf::core::props::Guarantee for #name #ty_generics #where_clause {
513            fn is_loop_free() -> bool {
514                <#field_type as #gryf::core::props::Guarantee>::is_loop_free()
515            }
516
517            fn has_paths_only() -> bool {
518                <#field_type as #gryf::core::props::Guarantee>::has_paths_only()
519            }
520
521            fn has_trees_only() -> bool {
522                <#field_type as #gryf::core::props::Guarantee>::has_trees_only()
523            }
524
525            fn has_bipartite_only() -> bool {
526                <#field_type as #gryf::core::props::Guarantee>::has_bipartite_only()
527            }
528
529            fn is_connected() -> bool {
530                <#field_type as #gryf::core::props::Guarantee>::is_connected()
531            }
532        }
533    };
534
535    TokenStream::from(implemented)
536}