1use core::fmt;
2use core::str::FromStr;
3
4#[derive(#[automatically_derived]impl ::core::fmt::Debug for DatabaseVersion {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f,
"DatabaseVersion major minor patch", &self.major, &self.minor,
&&self.patch)
}
}Debug, #[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
for DatabaseVersion {
}
#[automatically_derived]impl ::core::clone::Clone for DatabaseVersion {
#[inline]
fn clone(&self) -> Self {
let _: ::core::clone::AssertParamIsClone<u32>;
*self
}
}Clone, #[automatically_derived]impl ::core::marker::Copy for DatabaseVersion { }Copy, #[automatically_derived]impl ::core::marker::StructuralPartialEq for
DatabaseVersion {
}
#[automatically_derived]impl ::core::cmp::PartialEq for DatabaseVersion {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.major == other.major && self.minor == other.minor &&
self.patch == other.patch
}
}PartialEq, #[automatically_derived]impl ::core::cmp::Eq for DatabaseVersion {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<u32>;
}
}Eq, #[automatically_derived]impl ::core::cmp::PartialOrd for DatabaseVersion {
#[inline]
fn partial_cmp(&self, other: &Self)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
}
}PartialOrd, #[automatically_derived]impl ::core::cmp::Ord for DatabaseVersion {
#[inline]
fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
match ::core::cmp::Ord::cmp(&self.major, &other.major) {
::core::cmp::Ordering::Equal =>
match ::core::cmp::Ord::cmp(&self.minor, &other.minor) {
::core::cmp::Ordering::Equal =>
::core::cmp::Ord::cmp(&self.patch, &other.patch),
cmp => cmp,
},
cmp => cmp,
}
}
}Ord, #[automatically_derived]impl ::core::hash::Hash for DatabaseVersion {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.major, state);
::core::hash::Hash::hash(&self.minor, state);
::core::hash::Hash::hash(&self.patch, state)
}
}Hash)]
6pub struct DatabaseVersion {
7 major: u32,
8 minor: u32,
9 patch: u32,
10}
11
12impl DatabaseVersion {
13 pub const fn new(major: u32, minor: u32, patch: u32) -> Self {
15 Self {
16 major,
17 minor,
18 patch,
19 }
20 }
21
22 pub const fn major(&self) -> u32 {
24 self.major
25 }
26
27 pub const fn minor(&self) -> u32 {
29 self.minor
30 }
31
32 pub const fn patch(&self) -> u32 {
34 self.patch
35 }
36}
37
38impl fmt::Display for DatabaseVersion {
39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 f.write_fmt(format_args!("{0}.{1}.{2}", self.major, self.minor, self.patch))write!(f, "{}.{}.{}", self.major, self.minor, self.patch)
41 }
42}
43
44impl FromStr for DatabaseVersion {
54 type Err = ParseDatabaseVersionError;
55
56 fn from_str(version: &str) -> Result<Self, Self::Err> {
57 let mut components = version.split('.').map(|component| {
58 if component.bytes().all(|byte| byte.is_ascii_digit()) {
59 component.parse().ok()
60 } else {
61 None
62 }
63 });
64 match (
65 components.next(),
66 components.next(),
67 components.next(),
68 components.next(),
69 ) {
70 (Some(Some(major)), Some(Some(minor)), Some(Some(patch)), None) => {
71 Ok(Self::new(major, minor, patch))
72 }
73 _ => Err(ParseDatabaseVersionError),
74 }
75 }
76}
77
78#[derive(#[automatically_derived]impl ::core::fmt::Debug for ParseDatabaseVersionError
{
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "ParseDatabaseVersionError")
}
}Debug, #[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
for ParseDatabaseVersionError {
}
#[automatically_derived]impl ::core::clone::Clone for
ParseDatabaseVersionError {
#[inline]
fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]impl ::core::marker::Copy for
ParseDatabaseVersionError {
}Copy, #[automatically_derived]impl ::core::marker::StructuralPartialEq for
ParseDatabaseVersionError {
}
#[automatically_derived]impl ::core::cmp::PartialEq for
ParseDatabaseVersionError {
#[inline]
fn eq(&self, other: &Self) -> bool { true }
}PartialEq, #[automatically_derived]impl ::core::cmp::Eq for ParseDatabaseVersionError { }Eq, #[automatically_derived]impl ::core::hash::Hash for ParseDatabaseVersionError
{
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {}
}Hash)]
80pub struct ParseDatabaseVersionError;
81
82impl fmt::Display for ParseDatabaseVersionError {
83 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84 f.write_str("invalid database version, expected `major.minor.patch`")
85 }
86}
87
88impl core::error::Error for ParseDatabaseVersionError {}
89
90#[cfg(test)]
91mod tests {
92 use super::{DatabaseVersion, ParseDatabaseVersionError};
93
94 #[diesel_test_helper::test]
95 fn versions_order_by_major_then_minor_then_patch() {
96 assert!(DatabaseVersion::new(10, 0, 0) > DatabaseVersion::new(9, 6, 20));
97 assert!(DatabaseVersion::new(3, 10, 0) > DatabaseVersion::new(3, 9, 9));
98 assert!(DatabaseVersion::new(3, 9, 10) > DatabaseVersion::new(3, 9, 9));
99 }
100
101 #[diesel_test_helper::test]
102 fn parsing_inverts_display() {
103 for version in [
104 DatabaseVersion::new(0, 0, 0),
105 DatabaseVersion::new(8, 4, 11),
106 DatabaseVersion::new(u32::MAX, u32::MAX, u32::MAX),
107 ] {
108 assert_eq!(version.to_string().parse(), Ok(version));
109 }
110 }
111
112 #[diesel_test_helper::test]
113 fn parsing_rejects_anything_but_three_decimal_components() {
114 for input in [
115 "",
116 "8",
117 "8.4",
118 "8.4.11.2",
119 "8..4",
120 "8..4.11",
121 ".8.4.11",
122 "8.4.11.",
123 "+8.4.11",
124 "8.+4.11",
125 "8.4.-1",
126 " 8.4.11",
127 "8.4.11 ",
128 "8.4.4294967296",
129 "8.4.11-MariaDB",
130 ] {
131 assert_eq!(
132 input.parse::<DatabaseVersion>(),
133 Err(ParseDatabaseVersionError),
134 "{input:?}"
135 );
136 }
137 }
138}