| 1 | use crate::{BuildMetadata, Comparator, Op, Prerelease, Version, VersionReq}; |
| 2 | use core::fmt::{self, Alignment, Debug, Display, Write}; |
| 3 | |
| 4 | impl 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 | |
| 33 | impl 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 | |
| 48 | impl 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 | |
| 81 | impl Display for Prerelease { |
| 82 | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { |
| 83 | formatter.write_str(self.as_str()) |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | impl Display for BuildMetadata { |
| 88 | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { |
| 89 | formatter.write_str(self.as_str()) |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | impl 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 | |
| 110 | impl Debug for Prerelease { |
| 111 | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { |
| 112 | write!(formatter, "Prerelease( \"{}\")" , self) |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | impl Debug for BuildMetadata { |
| 117 | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { |
| 118 | write!(formatter, "BuildMetadata( \"{}\")" , self) |
| 119 | } |
| 120 | } |
| 121 | |
| 122 | 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 | |
| 159 | fn digits(val: u64) -> usize { |
| 160 | if val < 10 { |
| 161 | 1 |
| 162 | } else { |
| 163 | 1 + digits(val:val / 10) |
| 164 | } |
| 165 | } |
| 166 | |