1use std::fmt::Display;
2use std::str::FromStr;
3
4use serde::{Deserialize, Serialize};
5
6use super::super::util::TryFromStringVisitor;
7use super::Version;
8
9#[derive(Copy, Clone, Debug, Eq, PartialEq)]
11pub enum Relation {
12 Earlier,
14 EarlierEqual,
16 Equal,
18 LaterEqual,
20 Later,
22}
23
24impl Relation {
25 fn parse<'a, E: nom::error::ParseError<&'a str>>(
26 input: &'a str,
27 ) -> nom::IResult<&str, Self, E> {
28 use nom::branch::alt;
29 use nom::bytes::complete::tag;
30 use nom::combinator::value;
31 alt((
32 value(Relation::Earlier, tag("<<")),
33 value(Relation::EarlierEqual, tag("<=")),
34 value(Relation::Equal, tag("=")),
35 value(Relation::LaterEqual, tag(">=")),
36 value(Relation::Later, tag(">>")),
37 ))(input)
38 }
39}
40
41impl Display for Relation {
42 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43 match self {
44 Relation::Earlier => write!(f, "<<"),
45 Relation::EarlierEqual => write!(f, "<="),
46 Relation::Equal => write!(f, "="),
47 Relation::LaterEqual => write!(f, ">="),
48 Relation::Later => write!(f, ">>"),
49 }
50 }
51}
52
53#[derive(Debug, Eq, PartialEq)]
55pub struct VersionSet {
56 pub package: String,
58 pub constraint: Option<(Relation, Version)>,
61}
62
63impl Display for VersionSet {
64 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65 write!(f, "{}", self.package)?;
66
67 if let Some((relation, version)) = &self.constraint {
68 write!(f, " ({} {})", relation, version.as_str())?;
69 }
70
71 Ok(())
72 }
73}
74
75#[derive(Debug)]
77pub enum VersionSetParseError {
78 EmptyPackageName(String),
80
81 BadConstraintSpec(String),
84
85 BadVersion(<Version as TryFrom<&'static str>>::Error),
87}
88
89impl Display for VersionSetParseError {
90 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91 match self {
92 VersionSetParseError::EmptyPackageName(e) => {
93 write!(f, "Error parsing package name:\n{e}")
94 }
95 VersionSetParseError::BadConstraintSpec(e) => {
96 write!(f, "Error parsing constraint spec:\n{e}")
97 }
98 VersionSetParseError::BadVersion(e) => write!(f, "Error parsing version:\n{e}"),
99 }
100 }
101}
102
103impl FromStr for VersionSet {
104 type Err = VersionSetParseError;
105
106 fn from_str(input: &str) -> Result<Self, Self::Err> {
107 use nom::bytes::complete::*;
108 use nom::character::complete::*;
109 use nom::combinator::*;
110 use nom::error::{context, convert_error};
111 use nom::sequence::*;
112 use nom::Finish;
113
114 let (remaining, package) = terminated(
115 context(
116 "package name",
117 take_while1(|c: char| !c.is_whitespace() && c != '('),
118 ),
119 space0,
120 )(input)
121 .finish()
122 .map_err(|e| VersionSetParseError::EmptyPackageName(convert_error(input, e)))?;
123
124 let constraint = if remaining.is_empty() {
126 None
127 } else {
128 let (_, (relation, version)) = all_consuming(context(
129 "spec",
130 preceded(
131 char('('),
132 terminated(
133 separated_pair(
134 context("relation", Relation::parse),
135 space0,
136 context("version", take_until1(")")),
137 ),
138 tuple((char(')'), space0)),
139 ),
140 ),
141 ))(remaining)
142 .finish()
143 .map_err(|e| VersionSetParseError::BadConstraintSpec(convert_error(input, e)))?;
144 let version = Version::try_from(version).map_err(VersionSetParseError::BadVersion)?;
145 Some((relation, version))
146 };
147
148 Ok(Self {
149 package: package.to_string(),
150 constraint,
151 })
152 }
153}
154
155impl TryFrom<String> for VersionSet {
156 type Error = <Self as FromStr>::Err;
157
158 fn try_from(value: String) -> Result<Self, Self::Error> {
159 Self::from_str(&value)
160 }
161}
162
163impl TryFrom<&str> for VersionSet {
164 type Error = <Self as FromStr>::Err;
165
166 fn try_from(value: &str) -> Result<Self, Self::Error> {
167 Self::from_str(value)
168 }
169}
170
171impl Serialize for VersionSet {
172 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
173 serializer.collect_str(self)
174 }
175}
176
177impl<'de> Deserialize<'de> for VersionSet {
178 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
179 deserializer.deserialize_str(TryFromStringVisitor::new())
180 }
181}
182
183#[derive(Debug, Eq, PartialEq)]
185pub struct Dependency {
186 pub first: VersionSet,
188 pub alternates: Vec<VersionSet>,
190}
191
192impl Display for Dependency {
193 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
194 write!(f, "{}", self.first)?;
195
196 for alt in &self.alternates {
197 write!(f, " | {}", alt)?;
198 }
199
200 Ok(())
201 }
202}
203
204#[derive(Debug)]
206pub enum DependencyParseError {
207 Alternate(usize, VersionSetParseError),
209}
210
211impl Display for DependencyParseError {
212 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
213 match self {
214 DependencyParseError::Alternate(i, e) => write!(f, "Error parsing alternate {i}: {e}"),
215 }
216 }
217}
218
219impl FromStr for Dependency {
220 type Err = DependencyParseError;
221
222 fn from_str(input: &str) -> Result<Self, Self::Err> {
223 let (first, rest) = input.split_once('|').unwrap_or((input, ""));
224
225 let first = first
226 .trim()
227 .parse()
228 .map_err(|e| DependencyParseError::Alternate(0, e))?;
229 let alternates = if !rest.is_empty() {
230 rest.split('|')
231 .map(|s| s.trim())
232 .enumerate()
233 .map(|(i, s)| {
234 s.parse()
235 .map_err(|e| DependencyParseError::Alternate(i + 1, e))
236 })
237 .collect::<Result<_, _>>()?
238 } else {
239 vec![]
240 };
241
242 Ok(Self { first, alternates })
243 }
244}
245
246impl TryFrom<String> for Dependency {
247 type Error = <Self as FromStr>::Err;
248
249 fn try_from(value: String) -> Result<Self, Self::Error> {
250 Self::from_str(&value)
251 }
252}
253
254impl TryFrom<&str> for Dependency {
255 type Error = <Self as FromStr>::Err;
256
257 fn try_from(value: &str) -> Result<Self, Self::Error> {
258 Self::from_str(value)
259 }
260}
261
262impl Serialize for Dependency {
263 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
264 serializer.collect_str(self)
265 }
266}
267
268impl<'de> Deserialize<'de> for Dependency {
269 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
270 deserializer.deserialize_str(TryFromStringVisitor::new())
271 }
272}