1use crate::parse::Error;
2use core::fmt::{self, Debug, Display};
3
4pub(crate) enum ErrorKind {
5 Empty,
6 UnexpectedEnd(Position),
7 UnexpectedChar(Position, char),
8 UnexpectedCharAfter(Position, char),
9 ExpectedCommaFound(Position, char),
10 LeadingZero(Position),
11 Overflow(Position),
12 EmptySegment(Position),
13 IllegalCharacter(Position),
14 WildcardNotTheOnlyComparator(char),
15 UnexpectedAfterWildcard,
16 ExcessiveComparators,
17}
18
19#[derive(Copy, Clone, Eq, PartialEq)]
20pub(crate) enum Position {
21 Major,
22 Minor,
23 Patch,
24 Pre,
25 Build,
26}
27
28#[cfg(feature = "std")]
29#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
30impl std::error::Error for Error {}
31
32impl Display for Error {
33 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
34 match &self.kind {
35 ErrorKind::Empty => formatter.write_str("empty string, expected a semver version"),
36 ErrorKind::UnexpectedEnd(pos) => {
37 write!(formatter, "unexpected end of input while parsing {}", pos)
38 }
39 ErrorKind::UnexpectedChar(pos, ch) => {
40 write!(
41 formatter,
42 "unexpected character {} while parsing {}",
43 QuotedChar(*ch),
44 pos,
45 )
46 }
47 ErrorKind::UnexpectedCharAfter(pos, ch) => {
48 write!(
49 formatter,
50 "unexpected character {} after {}",
51 QuotedChar(*ch),
52 pos,
53 )
54 }
55 ErrorKind::ExpectedCommaFound(pos, ch) => {
56 write!(
57 formatter,
58 "expected comma after {}, found {}",
59 pos,
60 QuotedChar(*ch),
61 )
62 }
63 ErrorKind::LeadingZero(pos) => {
64 write!(formatter, "invalid leading zero in {}", pos)
65 }
66 ErrorKind::Overflow(pos) => {
67 write!(formatter, "value of {} exceeds u64::MAX", pos)
68 }
69 ErrorKind::EmptySegment(pos) => {
70 write!(formatter, "empty identifier segment in {}", pos)
71 }
72 ErrorKind::IllegalCharacter(pos) => {
73 write!(formatter, "unexpected character in {}", pos)
74 }
75 ErrorKind::WildcardNotTheOnlyComparator(ch) => {
76 write!(
77 formatter,
78 "wildcard req ({}) must be the only comparator in the version req",
79 ch,
80 )
81 }
82 ErrorKind::UnexpectedAfterWildcard => {
83 formatter.write_str("unexpected character after wildcard in version req")
84 }
85 ErrorKind::ExcessiveComparators => {
86 formatter.write_str("excessive number of version comparators")
87 }
88 }
89 }
90}
91
92impl Display for Position {
93 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
94 formatter.write_str(data:match self {
95 Position::Major => "major version number",
96 Position::Minor => "minor version number",
97 Position::Patch => "patch version number",
98 Position::Pre => "pre-release identifier",
99 Position::Build => "build metadata",
100 })
101 }
102}
103
104impl Debug for Error {
105 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
106 formatter.write_str(data:"Error(\"")?;
107 Display::fmt(self, f:formatter)?;
108 formatter.write_str(data:"\")")?;
109 Ok(())
110 }
111}
112
113struct QuotedChar(char);
114
115impl Display for QuotedChar {
116 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
117 // Standard library versions prior to https://github.com/rust-lang/rust/pull/95345
118 // print character 0 as '\u{0}'. We prefer '\0' to keep error messages
119 // the same across all supported Rust versions.
120 if self.0 == '\0' {
121 formatter.write_str(data:"'\\0'")
122 } else {
123 write!(formatter, "{:?}", self.0)
124 }
125 }
126}
127