xsd_parser/models/data/
path_data.rs

1use std::ops::Deref;
2
3use proc_macro2::TokenStream;
4use quote::quote;
5use smallvec::{smallvec, SmallVec};
6
7use crate::models::code::{IdentPath, ModulePath};
8
9/// Represents a type ready to be resolved and rendered for a specific module.
10///
11/// It contains information like the actual path to the type, a list of generics
12/// and a list of usings to add to the module.
13#[derive(Debug, Clone)]
14pub struct PathData {
15    /// Actual path of the target type.
16    pub path: IdentPath,
17
18    /// Usings to add for this target type.
19    pub usings: SmallVec<[String; 1]>,
20
21    /// Generics of this target type.
22    pub generics: SmallVec<[IdentPath; 1]>,
23}
24
25impl PathData {
26    /// Create a new [`PathData`] instance from the passed `path`.
27    #[must_use]
28    pub fn from_path(path: IdentPath) -> Self {
29        Self {
30            path,
31            usings: smallvec![],
32            generics: smallvec![],
33        }
34    }
35
36    /// Add a generic argument to the path data.
37    #[must_use]
38    pub fn with_generic(mut self, path: IdentPath) -> Self {
39        self.generics.push(path);
40
41        self
42    }
43
44    /// Add a using to the path data.
45    #[must_use]
46    pub fn with_using<P: Into<String>>(mut self, path: P) -> Self {
47        self.usings.push(path.into());
48
49        self
50    }
51
52    /// Make the path data to an included path data instead of a absolute one.
53    #[must_use]
54    pub fn into_included(self) -> Self {
55        if self.path.module().is_some() {
56            let using = format!("{}", &self.path);
57            let (ident, _, _) = self.path.into_parts();
58
59            Self::from_path(IdentPath::from_ident(ident)).with_using(using)
60        } else {
61            self
62        }
63    }
64
65    /// Resolves the target type relative to the passed module `path` and
66    /// returns the rendered type as [`TokenStream`].
67    #[must_use]
68    pub fn resolve_relative_to(&self, path: &ModulePath) -> TokenStream {
69        let mut ret = self.path.relative_to(path);
70
71        if !self.generics.is_empty() {
72            ret.extend(quote!(<));
73
74            for x in &self.generics {
75                ret.extend(x.relative_to(path));
76            }
77
78            ret.extend(quote!(>));
79        }
80
81        ret
82    }
83}
84
85impl Deref for PathData {
86    type Target = IdentPath;
87
88    fn deref(&self) -> &Self::Target {
89        &self.path
90    }
91}