reproto_core/
rp_package.rs1use errors::Result;
2use serde;
3use std::borrow::Cow;
4use std::collections::HashMap;
5use std::fmt;
6use std::mem;
7use std::result;
8use std::slice;
9use {AsPackage, RpVersionedPackage};
10
11pub struct Parts<'a> {
13 iter: slice::Iter<'a, String>,
14}
15
16impl<'a> Iterator for Parts<'a> {
17 type Item = <slice::Iter<'a, String> as Iterator>::Item;
18
19 fn next(&mut self) -> Option<Self::Item> {
20 self.iter.next()
21 }
22}
23
24impl<'a> DoubleEndedIterator for Parts<'a> {
25 fn next_back(&mut self) -> Option<Self::Item> {
26 self.iter.next_back()
27 }
28}
29
30impl<'a> Parts<'a> {
31 pub fn as_slice(&self) -> &'a [String] {
32 self.iter.as_slice()
33 }
34}
35
36#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
37pub struct RpPackage {
38 parts: Vec<String>,
39}
40
41impl AsPackage for RpPackage {
42 fn try_as_package<'a>(&'a self) -> Result<Cow<'a, RpPackage>> {
43 Ok(Cow::Borrowed(self))
44 }
45
46 fn prefix_with(self, prefix: RpPackage) -> Self {
47 prefix.join_package(self)
48 }
49}
50
51impl RpPackage {
52 pub fn new(parts: Vec<String>) -> RpPackage {
53 RpPackage { parts: parts }
54 }
55
56 pub fn len(&self) -> usize {
58 self.parts.len()
59 }
60
61 pub fn parse(input: &str) -> RpPackage {
69 if input.is_empty() {
70 return Self::empty();
71 }
72
73 RpPackage::new(input.split('.').map(ToOwned::to_owned).collect())
74 }
75
76 pub fn empty() -> RpPackage {
78 RpPackage { parts: vec![] }
79 }
80
81 pub fn join_package(mut self, other: RpPackage) -> RpPackage {
83 self.parts.extend(other.parts);
84 self
85 }
86
87 pub fn join_versioned(&self, other: RpVersionedPackage) -> RpVersionedPackage {
89 let mut parts = self.parts.clone();
90 parts.extend(other.package.parts);
91 RpVersionedPackage::new(RpPackage::new(parts), other.version)
92 }
93
94 pub fn join(&self, separator: &str) -> String {
96 self.parts.join(separator)
97 }
98
99 pub fn join_part<S: AsRef<str>>(mut self, other: S) -> RpPackage {
101 self.parts.push(other.as_ref().to_string());
102 self
103 }
104
105 pub fn starts_with(&self, other: &RpPackage) -> bool {
107 if self.parts.len() < other.parts.len() {
108 return false;
109 }
110
111 self.parts
112 .iter()
113 .zip(other.parts.iter())
114 .all(|(a, b)| a == b)
115 }
116
117 pub fn with_replacements(mut self, keywords: &HashMap<String, String>) -> Self {
119 for p in self.parts.iter_mut() {
120 if let Some(keyword) = keywords.get(p.as_str()) {
121 mem::replace(p, keyword.to_string());
122 }
123 }
124
125 self
126 }
127
128 pub fn with_naming<N>(mut self, naming: N) -> Self
130 where
131 N: Fn(&str) -> String,
132 {
133 for p in self.parts.iter_mut() {
134 let new_name = naming(p);
135 mem::replace(p, new_name);
136 }
137
138 self
139 }
140
141 pub fn parts(&self) -> Parts {
143 Parts {
144 iter: self.parts.iter(),
145 }
146 }
147}
148
149impl fmt::Display for RpPackage {
150 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
151 write!(f, "{}", self.parts.join("."))
152 }
153}
154
155impl serde::Serialize for RpPackage {
156 fn serialize<S>(&self, serializer: S) -> result::Result<S::Ok, S::Error>
157 where
158 S: serde::Serializer,
159 {
160 serializer.collect_str(self)
161 }
162}
163
164impl<'de> serde::Deserialize<'de> for RpPackage {
165 fn deserialize<D>(deserializer: D) -> result::Result<Self, D::Error>
166 where
167 D: serde::Deserializer<'de>,
168 {
169 struct RpPackageVisitor;
170
171 impl<'de> serde::de::Visitor<'de> for RpPackageVisitor {
172 type Value = RpPackage;
173
174 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
175 formatter.write_str("a SemVer version as a string")
176 }
177
178 fn visit_str<E>(self, v: &str) -> result::Result<Self::Value, E>
179 where
180 E: serde::de::Error,
181 {
182 Ok(RpPackage::parse(v))
183 }
184 }
185
186 deserializer.deserialize_str(RpPackageVisitor)
187 }
188}