1//! Mapping of the analyzer data model to pyo3 classes
  2
  3use pyo3::prelude::*;
  4
  5use analyzer::data_model;
  6
  7#[pyclass]
  8#[derive(Clone)]
  9/// pyo3 representation of a crate
 10pub struct Crate {
 11    #[pyo3(get)]
 12    pub name: String,
 13    #[pyo3(get)]
 14    pub version: String,
 15}
 16
 17#[pymethods]
 18impl Crate {
 19    pub fn __repr__(&self) -> String {
 20        format!("Crate(name={:?}, version={:?})", self.name, self.version)
 21    }
 22    #[getter]
 23    pub fn path(&self) -> Vec<String> {
 24        vec![self.name.clone()]
 25    }
 26    #[getter]
 27    pub fn path_str(&self) -> String {
 28        self.name.clone()
 29    }
 30}
 31
 32impl From<data_model::Crate> for Crate {
 33    fn from(crate_: data_model::Crate) -> Self {
 34        Crate {
 35            name: crate_.name,
 36            version: crate_.version,
 37        }
 38    }
 39}
 40
 41#[pyclass]
 42#[derive(Clone)]
 43/// pyo3 representation of a module
 44pub struct Module {
 45    #[pyo3(get)]
 46    pub file: Option<String>,
 47    #[pyo3(get)]
 48    pub path: Vec<String>,
 49    #[pyo3(get)]
 50    pub docstring: String,
 51}
 52
 53#[pymethods]
 54impl Module {
 55    pub fn __repr__(&self) -> String {
 56        format!("Module({:?})", self.path_str())
 57    }
 58    #[getter]
 59    pub fn path_str(&self) -> String {
 60        self.path.join("::")
 61    }
 62    #[getter]
 63    pub fn name(&self) -> String {
 64        self.path.last().unwrap().clone()
 65    }
 66}
 67
 68impl From<data_model::Module> for Module {
 69    fn from(module: data_model::Module) -> Self {
 70        Module {
 71            file: module.file,
 72            path: module.path,
 73            docstring: module.docstring,
 74        }
 75    }
 76}
 77
 78#[pyclass]
 79#[derive(Clone)]
 80/// pyo3 representation of a struct field
 81pub struct Field {
 82    #[pyo3(get)]
 83    pub path: Vec<String>,
 84    #[pyo3(get)]
 85    pub docstring: String,
 86    #[pyo3(get)]
 87    pub type_: Vec<TypeSegment>,
 88}
 89
 90#[pymethods]
 91impl Field {
 92    pub fn __repr__(&self) -> String {
 93        format!("Field({:?})", self.path_str())
 94    }
 95    #[getter]
 96    pub fn path_str(&self) -> String {
 97        self.path.join("::")
 98    }
 99    #[getter]
100    pub fn name(&self) -> String {
101        self.path.last().unwrap().clone()
102    }
103}
104
105impl From<data_model::Field> for Field {
106    fn from(field: data_model::Field) -> Self {
107        Field {
108            path: field.path,
109            docstring: field.docstring,
110            type_: field.type_.into_iter().map(TypeSegment::from).collect(),
111        }
112    }
113}
114
115#[pyclass]
116#[derive(Clone)]
117/// pyo3 representation of a struct
118pub struct Struct {
119    #[pyo3(get)]
120    pub path: Vec<String>,
121    #[pyo3(get)]
122    pub docstring: String,
123    #[pyo3(get)]
124    pub fields: Vec<Field>,
125}
126
127#[pymethods]
128impl Struct {
129    pub fn __repr__(&self) -> String {
130        format!("Struct({:?})", self.path_str())
131    }
132    #[getter]
133    fn path_str(&self) -> String {
134        self.path.join("::")
135    }
136    #[getter]
137    pub fn name(&self) -> String {
138        self.path.last().unwrap().clone()
139    }
140}
141
142impl From<data_model::Struct> for Struct {
143    fn from(module: data_model::Struct) -> Self {
144        Struct {
145            path: module.path,
146            docstring: module.docstring,
147            fields: module.fields.into_iter().map(Field::from).collect(),
148        }
149    }
150}
151
152#[pyclass]
153#[derive(Clone)]
154/// pyo3 representation of an enum
155pub struct Enum {
156    #[pyo3(get)]
157    pub path: Vec<String>,
158    #[pyo3(get)]
159    pub docstring: String,
160    #[pyo3(get)]
161    pub variants: Vec<Variant>,
162}
163
164#[pymethods]
165impl Enum {
166    pub fn __repr__(&self) -> String {
167        format!("Enum({:?})", self.path_str())
168    }
169    #[getter]
170    fn path_str(&self) -> String {
171        self.path.join("::")
172    }
173    #[getter]
174    pub fn name(&self) -> String {
175        self.path.last().unwrap().clone()
176    }
177}
178
179impl From<data_model::Enum> for Enum {
180    fn from(module: data_model::Enum) -> Self {
181        Enum {
182            path: module.path,
183            docstring: module.docstring,
184            variants: module.variants.into_iter().map(Variant::from).collect(),
185        }
186    }
187}
188
189#[pyclass]
190#[derive(Clone)]
191/// pyo3 representation of an enum variant
192pub struct Variant {
193    #[pyo3(get)]
194    pub path: Vec<String>,
195    #[pyo3(get)]
196    pub docstring: String,
197    // TODO discriminant
198    #[pyo3(get)]
199    pub fields: Vec<Field>,
200}
201
202#[pymethods]
203impl Variant {
204    pub fn __repr__(&self) -> String {
205        format!("Variant({:?})", self.path_str())
206    }
207    #[getter]
208    fn path_str(&self) -> String {
209        self.path.join("::")
210    }
211    #[getter]
212    pub fn name(&self) -> String {
213        self.path.last().unwrap().clone()
214    }
215}
216
217impl From<data_model::Variant> for Variant {
218    fn from(var: data_model::Variant) -> Self {
219        Variant {
220            path: var.path,
221            docstring: var.docstring,
222            fields: var.fields.into_iter().map(Field::from).collect(),
223        }
224    }
225}
226
227#[pyclass]
228#[derive(Clone)]
229/// pyo3 representation of a segment of a type
230/// types are split into segments to allow for identification of referenceable elements
231pub struct TypeSegment {
232    #[pyo3(get)]
233    pub content: String,
234    #[pyo3(get)]
235    pub is_path: bool,
236}
237
238#[pymethods]
239impl TypeSegment {
240    pub fn __repr__(&self) -> String {
241        if self.is_path {
242            format!("ref({:?})", self.content)
243        } else {
244            format!("{:?}", self.content)
245        }
246    }
247}
248
249impl From<data_model::TypeSegment> for TypeSegment {
250    fn from(field: data_model::TypeSegment) -> Self {
251        match field {
252            data_model::TypeSegment::Path(content) => TypeSegment {
253                content,
254                is_path: true,
255            },
256            data_model::TypeSegment::String(content) => TypeSegment {
257                content,
258                is_path: false,
259            },
260        }
261    }
262}
263
264#[pyclass]
265#[derive(Clone)]
266/// pyo3 representation of a function
267pub struct Function {
268    #[pyo3(get)]
269    pub path: Vec<String>,
270    #[pyo3(get)]
271    pub docstring: String,
272}
273
274#[pymethods]
275impl Function {
276    pub fn __repr__(&self) -> String {
277        format!("Function({:?})", self.path_str())
278    }
279    #[getter]
280    pub fn path_str(&self) -> String {
281        self.path.join("::")
282    }
283    #[getter]
284    pub fn name(&self) -> String {
285        self.path.last().unwrap().clone()
286    }
287}
288
289impl From<data_model::Function> for Function {
290    fn from(field: data_model::Function) -> Self {
291        Function {
292            path: field.path,
293            docstring: field.docstring,
294        }
295    }
296}