1use crate::{BuildMetadata, Comparator, Op, Prerelease, Version, VersionReq};
2use core::fmt::{self, Alignment, Debug, Display, Write};
3
4impl Display for Version {
5 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
6 let do_display = |formatter: &mut fmt::Formatter| -> fmt::Result {
7 write!(formatter, "{}.{}.{}", self.major, self.minor, self.patch)?;
8 if !self.pre.is_empty() {
9 write!(formatter, "-{}", self.pre)?;
10 }
11 if !self.build.is_empty() {
12 write!(formatter, "+{}", self.build)?;
13 }
14 Ok(())
15 };
16
17 let do_len = || -> usize {
18 digits(self.major)
19 + 1
20 + digits(self.minor)
21 + 1
22 + digits(self.patch)
23 + !self.pre.is_empty() as usize
24 + self.pre.len()
25 + !self.build.is_empty() as usize
26 + self.build.len()
27 };
28
29 pad(formatter, do_display, do_len)
30 }
31}
32
33impl Display for VersionReq {
34 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
35 if self.comparators.is_empty() {
36 return formatter.write_str("*");
37 }
38 for (i, comparator) in self.comparators.iter().enumerate() {
39 if i > 0 {
40 formatter.write_str(", ")?;
41 }
42 write!(formatter, "{}", comparator)?;
43 }
44 Ok(())
45 }
46}
47
48impl Display for Comparator {
49 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
50 let op = match self.op {
51 Op::Exact => "=",
52 Op::Greater => ">",
53 Op::GreaterEq => ">=",
54 Op::Less => "<",
55 Op::LessEq => "<=",
56 Op::Tilde => "~",
57 Op::Caret => "^",
58 Op::Wildcard => "",
59 };
60 formatter.write_str(op)?;
61 write!(formatter, "{}", self.major)?;
62 if let Some(minor) = &self.minor {
63 write!(formatter, ".{}", minor)?;
64 if let Some(patch) = &self.patch {
65 write!(formatter, ".{}", patch)?;
66 if !self.pre.is_empty() {
67 write!(formatter, "-{}", self.pre)?;
68 }
69 } else if self.op == Op::Wildcard {
70 formatter.write_str(".*")?;
71 }
72 } else if self.op == Op::Wildcard {
73 formatter.write_str(".*")?;
74 }
75 Ok(())
76 }
77}
78
79impl Display for Prerelease {
80 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
81 formatter.write_str(self.as_str())
82 }
83}
84
85impl Display for BuildMetadata {
86 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
87 formatter.write_str(self.as_str())
88 }
89}
90
91impl Debug for Version {
92 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
93 let mut debug = formatter.debug_struct("Version");
94 debug
95 .field("major", &self.major)
96 .field("minor", &self.minor)
97 .field("patch", &self.patch);
98 if !self.pre.is_empty() {
99 debug.field("pre", &self.pre);
100 }
101 if !self.build.is_empty() {
102 debug.field("build", &self.build);
103 }
104 debug.finish()
105 }
106}
107
108impl Debug for Prerelease {
109 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
110 write!(formatter, "Prerelease(\"{}\")", self)
111 }
112}
113
114impl Debug for BuildMetadata {
115 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
116 write!(formatter, "BuildMetadata(\"{}\")", self)
117 }
118}
119
120fn pad(
121 formatter: &mut fmt::Formatter,
122 do_display: impl FnOnce(&mut fmt::Formatter) -> fmt::Result,
123 do_len: impl FnOnce() -> usize,
124) -> fmt::Result {
125 let min_width = match formatter.width() {
126 Some(min_width) => min_width,
127 None => return do_display(formatter),
128 };
129
130 let len = do_len();
131 if len >= min_width {
132 return do_display(formatter);
133 }
134
135 let default_align = Alignment::Left;
136 let align = formatter.align().unwrap_or(default_align);
137 let padding = min_width - len;
138 let (pre_pad, post_pad) = match align {
139 Alignment::Left => (0, padding),
140 Alignment::Right => (padding, 0),
141 Alignment::Center => (padding / 2, (padding + 1) / 2),
142 };
143
144 let fill = formatter.fill();
145 for _ in 0..pre_pad {
146 formatter.write_char(fill)?;
147 }
148
149 do_display(formatter)?;
150
151 for _ in 0..post_pad {
152 formatter.write_char(fill)?;
153 }
154 Ok(())
155}
156
157fn digits(val: u64) -> usize {
158 if val < 10 {
159 1
160 } else {
161 1 + digits(val / 10)
162 }
163}