1
1
use serde:: { Deserialize , Serialize } ;
2
+ use std:: { fmt, str:: FromStr } ;
3
+ use thiserror:: Error ;
2
4
3
5
#[ derive( Serialize , Deserialize , Debug ) ]
4
6
pub struct KeylimeVersion {
@@ -10,3 +12,148 @@ pub struct KeylimeRegistrarVersion {
10
12
pub current_version : String ,
11
13
pub supported_versions : Vec < String > ,
12
14
}
15
+
16
+ pub trait GetErrorInput {
17
+ fn input ( & self ) -> String ;
18
+ }
19
+
20
+ #[ derive( Error , Debug ) ]
21
+ pub enum VersionParsingError {
22
+ /// The version input was malformed
23
+ #[ error( "input '{input}' malformed as a version" ) ]
24
+ MalformedVersion { input : String } ,
25
+
26
+ /// The parts of the version were not numbers
27
+ #[ error( "parts of version '{input}' were not numbers" ) ]
28
+ ParseError {
29
+ input : String ,
30
+ source : std:: num:: ParseIntError ,
31
+ } ,
32
+ }
33
+
34
+ impl GetErrorInput for VersionParsingError {
35
+ fn input ( & self ) -> String {
36
+ match self {
37
+ VersionParsingError :: MalformedVersion { input } => input. into ( ) ,
38
+ VersionParsingError :: ParseError { input, source : _ } => {
39
+ input. into ( )
40
+ }
41
+ }
42
+ }
43
+ }
44
+
45
+ // Implement the trait for all the references
46
+ impl < T : GetErrorInput > GetErrorInput for & T
47
+ where
48
+ T : GetErrorInput ,
49
+ {
50
+ fn input ( & self ) -> String {
51
+ ( * * self ) . input ( )
52
+ }
53
+ }
54
+
55
+ #[ derive( Clone , Debug , Eq , PartialEq , PartialOrd , Ord ) ]
56
+ pub struct Version {
57
+ major : u32 ,
58
+ minor : u32 ,
59
+ }
60
+
61
+ impl fmt:: Display for Version {
62
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
63
+ write ! ( f, "{}.{}" , self . major, self . minor)
64
+ }
65
+ }
66
+
67
+ impl FromStr for Version {
68
+ type Err = VersionParsingError ;
69
+
70
+ fn from_str ( input : & str ) -> Result < Self , Self :: Err > {
71
+ let mut parts = input. split ( '.' ) ;
72
+ match ( parts. next ( ) , parts. next ( ) ) {
73
+ ( Some ( major) , Some ( minor) ) => Ok ( Version {
74
+ major : major. parse ( ) . map_err ( |e| {
75
+ VersionParsingError :: ParseError {
76
+ input : input. to_string ( ) ,
77
+ source : e,
78
+ }
79
+ } ) ?,
80
+ minor : minor. parse ( ) . map_err ( |e| {
81
+ VersionParsingError :: ParseError {
82
+ input : input. to_string ( ) ,
83
+ source : e,
84
+ }
85
+ } ) ?,
86
+ } ) ,
87
+ _ => Err ( VersionParsingError :: MalformedVersion {
88
+ input : input. to_string ( ) ,
89
+ } ) ,
90
+ }
91
+ }
92
+ }
93
+
94
+ impl TryFrom < & str > for Version {
95
+ type Error = VersionParsingError ;
96
+
97
+ fn try_from ( input : & str ) -> Result < Self , Self :: Error > {
98
+ Version :: from_str ( input)
99
+ }
100
+ }
101
+
102
+ impl TryFrom < String > for Version {
103
+ type Error = VersionParsingError ;
104
+
105
+ fn try_from ( input : String ) -> Result < Self , Self :: Error > {
106
+ Version :: from_str ( input. as_str ( ) )
107
+ }
108
+ }
109
+
110
+ #[ cfg( test) ]
111
+ mod test {
112
+ use super :: * ;
113
+
114
+ #[ test]
115
+ fn test_from_str ( ) {
116
+ let v = Version :: from_str ( "1.2" ) . unwrap ( ) ; //#[allow_ci]
117
+ assert_eq ! ( v, Version { major: 1 , minor: 2 } ) ;
118
+ let v2: Version = "3.4" . try_into ( ) . unwrap ( ) ; //#[allow_ci]
119
+ assert_eq ! ( v2, Version { major: 3 , minor: 4 } ) ;
120
+ let v3: Version = "5.6" . to_string ( ) . try_into ( ) . unwrap ( ) ; //#[allow_ci]
121
+ assert_eq ! ( v3, Version { major: 5 , minor: 6 } ) ;
122
+ }
123
+
124
+ #[ test]
125
+ fn test_display ( ) {
126
+ let s = format ! ( "{}" , Version { major: 1 , minor: 2 } ) ;
127
+ assert_eq ! ( s, "1.2" . to_string( ) ) ;
128
+ }
129
+
130
+ #[ test]
131
+ fn test_ord ( ) {
132
+ let v11: Version = "1.1" . try_into ( ) . unwrap ( ) ; //#[allow_ci]
133
+ let v12: Version = "1.2" . try_into ( ) . unwrap ( ) ; //#[allow_ci]
134
+ let v21: Version = "2.1" . try_into ( ) . unwrap ( ) ; //#[allow_ci]
135
+ let v110: Version = "1.10" . try_into ( ) . unwrap ( ) ; //#[allow_ci]
136
+ assert ! ( v11 < v12) ;
137
+ assert ! ( v12 < v110) ;
138
+ assert ! ( v110 < v21) ;
139
+
140
+ let mut v = vec ! [ v12. clone( ) , v110. clone( ) , v11. clone( ) ] ;
141
+ v. sort ( ) ;
142
+ let expected = vec ! [ v11, v12, v110] ;
143
+ assert_eq ! ( v, expected) ;
144
+ }
145
+
146
+ #[ test]
147
+ fn test_invalid ( ) {
148
+ let result = Version :: from_str ( "a.b" ) ;
149
+ assert ! ( result. is_err( ) ) ;
150
+ let result = Version :: from_str ( "1.b" ) ;
151
+ assert ! ( result. is_err( ) ) ;
152
+ let result = Version :: from_str ( "a.2" ) ;
153
+ assert ! ( result. is_err( ) ) ;
154
+ let result = Version :: from_str ( "22" ) ;
155
+ assert ! ( result. is_err( ) ) ;
156
+ let result = Version :: from_str ( ".12" ) ;
157
+ assert ! ( result. is_err( ) ) ;
158
+ }
159
+ }
0 commit comments