1use std::fs::File;
2use std::io::{self, Read};
3
4pub type Result<T> = std::result::Result<T, String>;
6
7#[cfg(any(feature = "html_root_url_updated", feature = "markdown_deps_updated"))]
8fn join<T>(iter: T, sep: &str) -> String
9where
10 T: IntoIterator,
11 T::Item: std::fmt::Display,
12{
13 let mut buf = String::new();
14 let mut iter = iter.into_iter();
15 if let Some(item) = iter.next() {
16 let item = item.to_string();
17 buf.push_str(&item);
18 } else {
19 return buf;
20 }
21 for item in iter {
22 buf.push_str(sep);
23 let item = item.to_string();
24 buf.push_str(&item);
25 }
26 buf
27}
28
29pub fn read_file(path: &str) -> io::Result<String> {
33 let mut file = File::open(path)?;
34 let mut buf = String::new();
35 file.read_to_string(&mut buf)?;
36 Ok(buf.replace("\r\n", "\n"))
37}
38
39#[cfg(any(feature = "html_root_url_updated", feature = "markdown_deps_updated"))]
41pub fn indent(text: &str) -> String {
42 join(text.lines().map(|line| String::from(" ") + line), "\n")
43}
44
45#[cfg(any(
47 feature = "html_root_url_updated",
48 feature = "markdown_deps_updated",
49 feature = "contains_regex"
50))]
51pub fn version_matches_request(
52 version: &semver::Version,
53 request: &semver::VersionReq,
54) -> Result<()> {
55 use semver::Op;
56
57 for comparator in &request.comparators {
58 match comparator.op {
59 Op::Tilde | Op::Caret | Op::Exact | Op::Greater | Op::GreaterEq | Op::Wildcard => {
60 if comparator.major != version.major {
61 return Err(format!(
62 "expected major version {}, found {}",
63 version.major, comparator.major,
64 ));
65 }
66 if let Some(minor) = comparator.minor {
67 if minor != version.minor {
68 return Err(format!(
69 "expected minor version {}, found {}",
70 version.minor, minor
71 ));
72 }
73 }
74 if let Some(patch) = comparator.patch {
75 if patch != version.patch {
76 return Err(format!(
77 "expected patch version {}, found {}",
78 version.patch, patch
79 ));
80 }
81 }
82 if comparator.pre != version.pre {
83 return Err(format!(
84 "expected pre-release \"{}\", found \"{}\"",
85 version.pre, comparator.pre
86 ));
87 }
88 }
89 _ => {} }
91 }
92
93 Ok(())
94}
95
96#[cfg(test)]
97mod tests {
98 #[cfg(any(feature = "html_root_url_updated", feature = "markdown_deps_updated"))]
99 use semver::{Version, VersionReq};
100
101 #[cfg(any(feature = "html_root_url_updated", feature = "markdown_deps_updated"))]
102 use super::*;
103
104 #[cfg(any(feature = "html_root_url_updated", feature = "markdown_deps_updated"))]
105 mod test_version_matches_request {
106 use super::*;
107
108 #[test]
109 fn implicit_compatible() {
110 let version = Version::parse("1.2.3").unwrap();
111 let request = VersionReq::parse("1.2.3").unwrap();
112 assert_eq!(version_matches_request(&version, &request), Ok(()));
113
114 let request = VersionReq::parse("1.2.0").unwrap();
115 assert!(version_matches_request(&version, &request).is_err());
116 }
117
118 #[test]
119 fn compatible() {
120 let version = Version::parse("1.2.3").unwrap();
121 let request = VersionReq::parse("^1.2.3").unwrap();
122 assert_eq!(version_matches_request(&version, &request), Ok(()));
123
124 let request = VersionReq::parse("^1.2.0").unwrap();
125 assert!(version_matches_request(&version, &request).is_err());
126 }
127
128 #[test]
129 fn tilde() {
130 let version = Version::parse("1.2.3").unwrap();
131 let request = VersionReq::parse("~1.2.3").unwrap();
132 assert_eq!(version_matches_request(&version, &request), Ok(()));
133
134 let request = VersionReq::parse("~1.2.0").unwrap();
135 assert!(version_matches_request(&version, &request).is_err());
136 }
137
138 #[test]
139 fn exact() {
140 let version = Version::parse("1.2.3").unwrap();
141 let request = VersionReq::parse("=1.2.3").unwrap();
142 assert_eq!(version_matches_request(&version, &request), Ok(()));
143
144 let request = VersionReq::parse("=1.2.0").unwrap();
145 assert!(version_matches_request(&version, &request).is_err());
146 }
147
148 #[test]
149 fn greater_or_equal() {
150 let version = Version::parse("1.2.3").unwrap();
151 let request = VersionReq::parse(">=1.2.3").unwrap();
152 assert_eq!(version_matches_request(&version, &request), Ok(()));
153
154 let request = VersionReq::parse(">=1.2.0").unwrap();
155 assert!(version_matches_request(&version, &request).is_err());
156 }
157
158 #[test]
159 fn wildcard() {
160 let version = Version::parse("1.2.3").unwrap();
161 let request = VersionReq::parse("1.2.*").unwrap();
162 assert_eq!(version_matches_request(&version, &request), Ok(()));
163
164 let request = VersionReq::parse("1.3.*").unwrap();
165 assert!(version_matches_request(&version, &request).is_err());
166 }
167
168 #[test]
169 fn greater() {
170 let version = Version::parse("1.2.3").unwrap();
171 let request = VersionReq::parse(">1.2.3").unwrap();
172 assert_eq!(version_matches_request(&version, &request), Ok(()));
173
174 let request = VersionReq::parse(">1.2.0").unwrap();
175 assert!(version_matches_request(&version, &request).is_err());
176 }
177
178 #[test]
179 fn no_patch() {
180 let version = Version::parse("1.2.3").unwrap();
181 let request = VersionReq::parse("1.2").unwrap();
182 assert_eq!(version_matches_request(&version, &request), Ok(()));
183 }
184
185 #[test]
186 fn no_minor() {
187 let version = Version::parse("1.2.3").unwrap();
188 let request = VersionReq::parse("1").unwrap();
189 assert_eq!(version_matches_request(&version, &request), Ok(()));
190 }
191
192 #[test]
193 fn multiple_comparators() {
194 let version = Version::parse("1.2.3").unwrap();
195 let request = VersionReq::parse(">= 1.2.3, < 2.0").unwrap();
196 assert_eq!(version_matches_request(&version, &request), Ok(()));
197
198 let request = VersionReq::parse(">= 1.2.0, < 2.0").unwrap();
199 assert!(version_matches_request(&version, &request).is_err());
200 }
201
202 #[test]
203 fn unhandled_operator() {
204 let version = Version::parse("1.2.3").unwrap();
205 let request = VersionReq::parse("< 2.0").unwrap();
206 assert_eq!(version_matches_request(&version, &request), Ok(()));
207 }
208
209 #[test]
210 fn bad_major() {
211 let version = Version::parse("2.0.0").unwrap();
212 let request = VersionReq::parse("1.2.3").unwrap();
213 assert_eq!(
214 version_matches_request(&version, &request),
215 Err(String::from("expected major version 2, found 1"))
216 );
217 }
218
219 #[test]
220 fn bad_minor() {
221 let version = Version::parse("1.3.0").unwrap();
222 let request = VersionReq::parse("1.2.3").unwrap();
223 assert_eq!(
224 version_matches_request(&version, &request),
225 Err(String::from("expected minor version 3, found 2"))
226 );
227 }
228
229 #[test]
230 fn bad_patch() {
231 let version = Version::parse("1.2.4").unwrap();
232 let request = VersionReq::parse("1.2.3").unwrap();
233 assert_eq!(
234 version_matches_request(&version, &request),
235 Err(String::from("expected patch version 4, found 3"))
236 );
237 }
238
239 #[test]
240 fn bad_pre_release() {
241 let version = Version::parse("1.2.3-rc2").unwrap();
242 let request = VersionReq::parse("1.2.3-rc1").unwrap();
243 assert_eq!(
244 version_matches_request(&version, &request),
245 Err(String::from("expected pre-release \"rc2\", found \"rc1\""))
246 );
247 }
248 }
249}