routee_compass_macros/
lib.rs

1extern crate proc_macro;
2extern crate proc_macro_error;
3extern crate quote;
4extern crate syn;
5
6use proc_macro::TokenStream;
7use proc_macro_error::proc_macro_error;
8use quote::quote;
9use syn::{parse_macro_input, DeriveInput};
10
11/// A procedural macro that generates python bindings for a struct that implements the `CompassAppBindings` trait.
12/// This allows custom applications to be exposed to python in a similar manner as the original python compass app.
13#[proc_macro_error]
14#[proc_macro_attribute]
15pub fn pybindings(_attr: TokenStream, item: TokenStream) -> TokenStream {
16    let input = parse_macro_input!(item as DeriveInput);
17
18    let name = &input.ident;
19
20    let expanded = quote! {
21        use pyo3::{exceptions::PyException, prelude::*, types::PyType, PyResult};
22
23        #[pyclass]
24        #input
25
26        #[pymethods]
27        impl #name {
28            #[pyo3(signature = (edge_id, edge_list_id=None))]
29            fn graph_edge_origin(&self, edge_id: usize, edge_list_id: Option<usize>) -> PyResult<usize> {
30                CompassAppBindings::graph_edge_origin(self, edge_list_id, edge_id).map_err(|e| {
31                    PyException::new_err(format!(
32                        "error retrieving edge origin for edge_id {}: {}",
33                        edge_id, e
34                    ))
35                })
36            }
37            #[pyo3(signature = (edge_id, edge_list_id=None))]
38            fn graph_edge_destination(&self, edge_id: usize, edge_list_id: Option<usize>) -> PyResult<usize> {
39                CompassAppBindings::graph_edge_destination(self, edge_list_id, edge_id).map_err(|e| {
40                    PyException::new_err(format!(
41                        "error retrieving edge destination for edge_id {}: {}",
42                        edge_id, e
43                    ))
44                })
45            }
46            #[pyo3(signature = (edge_id, edge_list_id=None, distance_unit=None))]
47            fn graph_edge_distance(&self, edge_id: usize, edge_list_id: Option<usize>, distance_unit: Option<String>) -> PyResult<f64> {
48                CompassAppBindings::graph_edge_distance(self, edge_list_id, edge_id, distance_unit).map_err(|e| {
49                    PyException::new_err(format!(
50                        "error retrieving edge distance for edge_id {}: {}",
51                        edge_id, e
52                    ))
53                })
54            }
55            fn graph_get_out_edge_ids(&self, vertex_id: usize) -> Vec<(usize, usize)> {
56                CompassAppBindings::graph_get_out_edge_ids(self, vertex_id)
57            }
58            fn graph_get_in_edge_ids(&self, vertex_id: usize) -> Vec<(usize, usize)> {
59                CompassAppBindings::graph_get_in_edge_ids(self, vertex_id)
60            }
61            #[staticmethod]
62            pub fn _from_config_toml_string(
63                config_string: String,
64                original_file_path: String,
65            ) -> PyResult<#name> {
66                CompassAppBindings::from_config_toml_string(config_string, original_file_path).map_err(
67                    |e| {
68                        PyException::new_err(format!(
69                            "Error while creating CompassApp from config toml string: {}",
70                            e
71                        ))
72                    },
73                )
74            }
75
76            #[pyo3(signature = (queries, config=None))]
77            pub fn _run_queries(
78                &self,
79                queries: Vec<String>,
80                config: Option<String>,
81            ) -> PyResult<Vec<String>> {
82                CompassAppBindings::run_queries(self, queries, config)
83                    .map_err(|e| PyException::new_err(format!("Error while running queries: {}", e)))
84            }
85        }
86    };
87
88    TokenStream::from(expanded)
89}