reproto_core/
rp_name.rs

1//! Describes a fully qualified name as a model
2
3use errors::Result;
4use serde::Serialize;
5use std::fmt;
6use {CoreFlavor, Diagnostics, Flavor, Loc, Translate, Translator};
7
8#[derive(Debug, Clone, Serialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
9#[serde(bound = "F::Package: Serialize")]
10pub struct RpName<F: 'static>
11where
12    F: Flavor,
13{
14    /// Alias used if the name was imported from another package.
15    #[serde(skip_serializing_if = "Option::is_none")]
16    pub prefix: Option<Loc<String>>,
17    /// Package that name belongs to.
18    pub package: F::Package,
19    /// Absolute parts of the name, from the root of the package.
20    pub parts: Vec<String>,
21}
22
23impl<F: 'static> RpName<F>
24where
25    F: Flavor,
26{
27    pub fn new(prefix: Option<Loc<String>>, package: F::Package, parts: Vec<String>) -> Self {
28        Self {
29            prefix: prefix,
30            package: package,
31            parts: parts,
32        }
33    }
34
35    pub fn extend<I>(&self, it: I) -> Self
36    where
37        I: IntoIterator<Item = String>,
38    {
39        let mut parts = self.parts.clone();
40        parts.extend(it);
41
42        Self {
43            prefix: self.prefix.clone(),
44            package: self.package.clone(),
45            parts: parts,
46        }
47    }
48
49    pub fn push(&self, part: String) -> Self {
50        let mut parts = self.parts.clone();
51        parts.push(part);
52
53        Self {
54            prefix: self.prefix.clone(),
55            package: self.package.clone(),
56            parts: parts,
57        }
58    }
59
60    pub fn join<S: AsRef<str>>(&self, joiner: S) -> String {
61        self.parts.join(joiner.as_ref())
62    }
63
64    /// Convert to a name without a prefix component.
65    pub fn without_prefix(self) -> Self {
66        Self {
67            prefix: None,
68            package: self.package,
69            parts: self.parts,
70        }
71    }
72
73    pub fn with_package(self, package: F::Package) -> Self {
74        Self {
75            prefix: self.prefix,
76            package: package,
77            parts: self.parts,
78        }
79    }
80
81    /// Build a new name out if the given paths.
82    pub fn with_parts(self, parts: Vec<String>) -> Self {
83        Self {
84            prefix: self.prefix,
85            package: self.package,
86            parts: parts,
87        }
88    }
89
90    pub fn is_same(&self, other: &Self) -> bool {
91        self.package == other.package && self.parts == other.parts
92    }
93}
94
95impl RpName<CoreFlavor> {
96    /// Convert to a name without a version component.
97    pub fn without_version(self) -> Self {
98        Self {
99            prefix: self.prefix,
100            package: self.package.without_version(),
101            parts: self.parts,
102        }
103    }
104
105    /// Localize name.
106    ///
107    /// Strips version of any type which is _not_ imported.
108    pub fn localize(self) -> Self {
109        if self.prefix.is_some() {
110            return self;
111        }
112
113        self.without_version()
114    }
115}
116
117impl<F: 'static> fmt::Display for RpName<F>
118where
119    F: Flavor,
120{
121    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
122        if let Some(ref prefix) = self.prefix {
123            write!(f, "{}::{}", prefix, self.parts.join("::"))
124        } else {
125            write!(f, "{}", self.parts.join("::"))
126        }
127    }
128}
129
130impl<F: 'static, T> Translate<T> for RpName<F>
131where
132    F: Flavor,
133    T: Translator<Source = F>,
134{
135    type Source = F;
136    type Out = RpName<T::Target>;
137
138    /// Translate into different flavor.
139    fn translate(self, _: &mut Diagnostics, translator: &T) -> Result<RpName<T::Target>> {
140        Ok(RpName {
141            prefix: self.prefix,
142            package: translator.translate_package(self.package)?,
143            parts: self.parts,
144        })
145    }
146}