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(data:"*");
37 }
38 for (i: usize, comparator: &Comparator) in self.comparators.iter().enumerate() {
39 if i > 0 {
40 formatter.write_str(data:", ")?;
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 #[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
81impl Display for Prerelease {
82 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
83 formatter.write_str(self.as_str())
84 }
85}
86
87impl Display for BuildMetadata {
88 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
89 formatter.write_str(self.as_str())
90 }
91}
92
93impl Debug for Version {
94 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
95 let mut debug: DebugStruct<'_, '_> = formatter.debug_struct(name:"Version");
96 debug
97 .field("major", &self.major)
98 .field("minor", &self.minor)
99 .field(name:"patch", &self.patch);
100 if !self.pre.is_empty() {
101 debug.field(name:"pre", &self.pre);
102 }
103 if !self.build.is_empty() {
104 debug.field(name:"build", &self.build);
105 }
106 debug.finish()
107 }
108}
109
110impl Debug for Prerelease {
111 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
112 write!(formatter, "Prerelease(\"{}\")", self)
113 }
114}
115
116impl Debug for BuildMetadata {
117 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
118 write!(formatter, "BuildMetadata(\"{}\")", self)
119 }
120}
121
122fn 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
159fn digits(val: u64) -> usize {
160 if val < 10 {
161 1
162 } else {
163 1 + digits(val:val / 10)
164 }
165}
166