1 use crate::{BuildMetadata, Comparator, Op, Prerelease, Version, VersionReq};
2 use core::fmt::{self, Alignment, Debug, Display, Write};
3
4 impl Display for Version {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result5 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
33 impl Display for VersionReq {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result34 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
48 impl Display for Comparator {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result49 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 #[cfg(no_non_exhaustive)]
60 Op::__NonExhaustive => unreachable!(),
61 };
62 formatter.write_str(op)?;
63 write!(formatter, "{}", self.major)?;
64 if let Some(minor) = &self.minor {
65 write!(formatter, ".{}", minor)?;
66 if let Some(patch) = &self.patch {
67 write!(formatter, ".{}", patch)?;
68 if !self.pre.is_empty() {
69 write!(formatter, "-{}", self.pre)?;
70 }
71 } else if self.op == Op::Wildcard {
72 formatter.write_str(".*")?;
73 }
74 } else if self.op == Op::Wildcard {
75 formatter.write_str(".*")?;
76 }
77 Ok(())
78 }
79 }
80
81 impl Display for Prerelease {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result82 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
83 formatter.write_str(self.as_str())
84 }
85 }
86
87 impl Display for BuildMetadata {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result88 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
89 formatter.write_str(self.as_str())
90 }
91 }
92
93 impl Debug for Version {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result94 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
95 let mut debug = formatter.debug_struct("Version");
96 debug
97 .field("major", &self.major)
98 .field("minor", &self.minor)
99 .field("patch", &self.patch);
100 if !self.pre.is_empty() {
101 debug.field("pre", &self.pre);
102 }
103 if !self.build.is_empty() {
104 debug.field("build", &self.build);
105 }
106 debug.finish()
107 }
108 }
109
110 impl Debug for Prerelease {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result111 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
112 write!(formatter, "Prerelease(\"{}\")", self)
113 }
114 }
115
116 impl Debug for BuildMetadata {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result117 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
118 write!(formatter, "BuildMetadata(\"{}\")", self)
119 }
120 }
121
pad( formatter: &mut fmt::Formatter, do_display: impl FnOnce(&mut fmt::Formatter) -> fmt::Result, do_len: impl FnOnce() -> usize, ) -> fmt::Result122 fn pad(
123 formatter: &mut fmt::Formatter,
124 do_display: impl FnOnce(&mut fmt::Formatter) -> fmt::Result,
125 do_len: impl FnOnce() -> usize,
126 ) -> fmt::Result {
127 let min_width = match formatter.width() {
128 Some(min_width) => min_width,
129 None => return do_display(formatter),
130 };
131
132 let len = do_len();
133 if len >= min_width {
134 return do_display(formatter);
135 }
136
137 let default_align = Alignment::Left;
138 let align = formatter.align().unwrap_or(default_align);
139 let padding = min_width - len;
140 let (pre_pad, post_pad) = match align {
141 Alignment::Left => (0, padding),
142 Alignment::Right => (padding, 0),
143 Alignment::Center => (padding / 2, (padding + 1) / 2),
144 };
145
146 let fill = formatter.fill();
147 for _ in 0..pre_pad {
148 formatter.write_char(fill)?;
149 }
150
151 do_display(formatter)?;
152
153 for _ in 0..post_pad {
154 formatter.write_char(fill)?;
155 }
156 Ok(())
157 }
158
digits(val: u64) -> usize159 fn digits(val: u64) -> usize {
160 if val < 10 {
161 1
162 } else {
163 1 + digits(val / 10)
164 }
165 }
166