use crate::{BuildMetadata, Comparator, Op, Prerelease, Version, VersionReq}; use core::fmt::{self, Alignment, Debug, Display, Write}; impl Display for Version { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let do_display = |formatter: &mut fmt::Formatter| -> fmt::Result { write!(formatter, "{}.{}.{}", self.major, self.minor, self.patch)?; if !self.pre.is_empty() { write!(formatter, "-{}", self.pre)?; } if !self.build.is_empty() { write!(formatter, "+{}", self.build)?; } Ok(()) }; let do_len = || -> usize { digits(self.major) + 1 + digits(self.minor) + 1 + digits(self.patch) + !self.pre.is_empty() as usize + self.pre.len() + !self.build.is_empty() as usize + self.build.len() }; pad(formatter, do_display, do_len) } } impl Display for VersionReq { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { if self.comparators.is_empty() { return formatter.write_str("*"); } for (i, comparator) in self.comparators.iter().enumerate() { if i > 0 { formatter.write_str(", ")?; } write!(formatter, "{}", comparator)?; } Ok(()) } } impl Display for Comparator { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let op = match self.op { Op::Exact => "=", Op::Greater => ">", Op::GreaterEq => ">=", Op::Less => "<", Op::LessEq => "<=", Op::Tilde => "~", Op::Caret => "^", Op::Wildcard => "", #[cfg(no_non_exhaustive)] Op::__NonExhaustive => unreachable!(), }; formatter.write_str(op)?; write!(formatter, "{}", self.major)?; if let Some(minor) = &self.minor { write!(formatter, ".{}", minor)?; if let Some(patch) = &self.patch { write!(formatter, ".{}", patch)?; if !self.pre.is_empty() { write!(formatter, "-{}", self.pre)?; } } else if self.op == Op::Wildcard { formatter.write_str(".*")?; } } else if self.op == Op::Wildcard { formatter.write_str(".*")?; } Ok(()) } } impl Display for Prerelease { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str(self.as_str()) } } impl Display for BuildMetadata { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str(self.as_str()) } } impl Debug for Version { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let mut debug = formatter.debug_struct("Version"); debug .field("major", &self.major) .field("minor", &self.minor) .field("patch", &self.patch); if !self.pre.is_empty() { debug.field("pre", &self.pre); } if !self.build.is_empty() { debug.field("build", &self.build); } debug.finish() } } impl Debug for Prerelease { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "Prerelease(\"{}\")", self) } } impl Debug for BuildMetadata { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "BuildMetadata(\"{}\")", self) } } fn pad( formatter: &mut fmt::Formatter, do_display: impl FnOnce(&mut fmt::Formatter) -> fmt::Result, do_len: impl FnOnce() -> usize, ) -> fmt::Result { let min_width = match formatter.width() { Some(min_width) => min_width, None => return do_display(formatter), }; let len = do_len(); if len >= min_width { return do_display(formatter); } let default_align = Alignment::Left; let align = formatter.align().unwrap_or(default_align); let padding = min_width - len; let (pre_pad, post_pad) = match align { Alignment::Left => (0, padding), Alignment::Right => (padding, 0), Alignment::Center => (padding / 2, (padding + 1) / 2), }; let fill = formatter.fill(); for _ in 0..pre_pad { formatter.write_char(fill)?; } do_display(formatter)?; for _ in 0..post_pad { formatter.write_char(fill)?; } Ok(()) } fn digits(val: u64) -> usize { if val < 10 { 1 } else { 1 + digits(val / 10) } }