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