@@ -20,7 +20,7 @@ extern crate rusb;
20
20
use std:: fmt:: Display ;
21
21
use std:: fmt:: Formatter ;
22
22
use std:: num:: ParseIntError ;
23
- use std:: ops:: Range ;
23
+ use std:: ops:: RangeInclusive ;
24
24
use std:: time:: Duration ;
25
25
26
26
use getopts:: { Matches , Options } ;
@@ -29,18 +29,22 @@ use rusb::{Device, GlobalContext};
29
29
use crate :: DeviceParam :: { FanSpeed , PumpSpeed } ;
30
30
31
31
fn main ( ) {
32
+ if let Err ( e) = run ( ) {
33
+ eprintln ! ( "Error: {}" , e) ;
34
+ std:: process:: exit ( 1 ) ;
35
+ }
36
+ }
37
+
38
+ fn run < ' e > ( ) -> Result < ( ) , CliValidationError < ' e > > {
32
39
let args: Vec < String > = std:: env:: args ( ) . collect ( ) ;
33
40
let program = args[ 0 ] . clone ( ) ;
34
41
let opts = build_options ( ) ;
35
42
let opt_matches = match_opts ( args, & opts) ;
36
43
37
44
if opt_matches. opt_present ( "h" ) || no_options_present ( & opt_matches) {
38
- print_usage ( program, opts)
45
+ Ok ( print_usage ( program, opts) )
39
46
} else {
40
- match validate ( opt_matches) {
41
- Ok ( params) => set_params ( params) ,
42
- Err ( f) => eprintln ! ( "Invalid options: {}" , f) ,
43
- }
47
+ validate ( opt_matches) . map ( set_params)
44
48
}
45
49
}
46
50
@@ -54,30 +58,61 @@ fn set_params(params: Vec<DeviceParam>) {
54
58
kraken. reattach ( ) ;
55
59
}
56
60
57
- fn validate ( opt_matches : Matches ) -> Result < Vec < DeviceParam > , ParseIntError > {
58
- let range: Range < u8 > = 10 ..100 ;
59
-
60
- let mut params: Vec < DeviceParam > = Vec :: new ( ) ;
61
+ #[ derive( Debug ) ]
62
+ struct CliValidationError < ' e > {
63
+ value : String ,
64
+ param : & ' e str ,
65
+ reason : String ,
66
+ }
61
67
62
- if let Some ( fan_speed) = opt_matches. opt_get ( "f" ) ? {
63
- assert ! (
64
- range. contains( & fan_speed) ,
65
- "FANSPEED should be within range 10-100"
66
- ) ;
67
- params. push ( FanSpeed ( fan_speed) )
68
+ impl Display for CliValidationError < ' _ > {
69
+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
70
+ write ! (
71
+ f,
72
+ "Value '{}' is not valid for parameter '{}': {}. Try --help." ,
73
+ self . value, self . param, self . reason
74
+ )
68
75
}
76
+ }
69
77
70
- if let Some ( pump_speed) = opt_matches. opt_get ( "p" ) ? {
71
- assert ! (
72
- range. contains( & pump_speed) ,
73
- "PUMPSPEED should be within range 10-100"
74
- ) ;
75
- params. push ( PumpSpeed ( pump_speed) )
76
- }
78
+ fn validate < ' e > ( opt_matches : Matches ) -> Result < Vec < DeviceParam > , CliValidationError < ' e > > {
79
+ let range = 10 ..=100 ;
77
80
81
+ let mut params: Vec < DeviceParam > = Vec :: new ( ) ;
82
+ parse_param ( & opt_matches, & range, "fan-speed" , FanSpeed ) ?. map ( |dp| params. push ( dp) ) ;
83
+ parse_param ( & opt_matches, & range, "pump-speed" , PumpSpeed ) ?. map ( |dp| params. push ( dp) ) ;
78
84
Ok ( params)
79
85
}
80
86
87
+ fn parse_param < ' e > (
88
+ opt_matches : & Matches ,
89
+ range : & RangeInclusive < u8 > ,
90
+ param : & ' e str ,
91
+ creator : fn ( u8 ) -> DeviceParam ,
92
+ ) -> Result < Option < DeviceParam > , CliValidationError < ' e > > {
93
+ opt_matches
94
+ . opt_get ( param)
95
+ . or_else ( |f : ParseIntError | {
96
+ Err ( CliValidationError {
97
+ param,
98
+ value : opt_matches. opt_str ( param) . unwrap ( ) ,
99
+ reason : f. to_string ( ) ,
100
+ } )
101
+ } ) ?
102
+ . map ( |fan_speed| {
103
+ if range. contains ( & fan_speed) {
104
+ Ok ( Some ( creator ( fan_speed) ) )
105
+ } else {
106
+ Err ( CliValidationError {
107
+ param,
108
+ value : fan_speed. to_string ( ) ,
109
+ reason : "out of range" . to_string ( ) ,
110
+ } )
111
+ }
112
+ } )
113
+ . unwrap_or_else ( || Ok ( None ) )
114
+ }
115
+
81
116
fn no_options_present ( opt_matches : & Matches ) -> bool {
82
117
!opt_matches. opt_present ( "f" ) && !opt_matches. opt_present ( "p" )
83
118
}
@@ -104,7 +139,7 @@ fn build_options() -> Options {
104
139
"p" ,
105
140
"pump-speed" ,
106
141
"Pump speed in 10 - 100 range." ,
107
- "PUMPSEED " ,
142
+ "PUMPSPEED " ,
108
143
) ;
109
144
opts
110
145
}
@@ -176,6 +211,7 @@ impl KrakenControl for Kraken {
176
211
}
177
212
}
178
213
214
+ #[ derive( Debug , PartialOrd , PartialEq ) ]
179
215
enum DeviceParam {
180
216
FanSpeed ( u8 ) ,
181
217
PumpSpeed ( u8 ) ,
0 commit comments