1+ use core:: fmt;
2+ use std:: { path:: PathBuf , process:: exit} ;
3+
4+ use ratatui:: layout:: Flex ;
15use toml;
26
37use dirs;
4- use serde:: Deserialize ;
8+ use serde:: {
9+ Deserialize , Deserializer ,
10+ de:: { self , Unexpected , Visitor } ,
11+ } ;
512
613#[ derive( Deserialize , Debug ) ]
714pub struct Config {
15+ #[ serde( default = "default_layout" , deserialize_with = "deserialize_layout" ) ]
16+ pub layout : Flex ,
17+
18+ #[ serde( default = "Width::default" ) ]
19+ pub width : Width ,
20+
821 #[ serde( default = "default_toggle_scanning" ) ]
922 pub toggle_scanning : char ,
1023
@@ -15,6 +28,65 @@ pub struct Config {
1528 pub paired_device : PairedDevice ,
1629}
1730
31+ #[ derive( Debug , Default ) ]
32+ pub enum Width {
33+ #[ default]
34+ Auto ,
35+ Size ( u16 ) ,
36+ }
37+
38+ struct WidthVisitor ;
39+
40+ impl < ' de > Visitor < ' de > for WidthVisitor {
41+ type Value = Width ;
42+
43+ fn expecting ( & self , formatter : & mut fmt:: Formatter ) -> fmt:: Result {
44+ formatter. write_str ( "the string \" auto\" or a positive integer (u16)" )
45+ }
46+
47+ fn visit_str < E > ( self , value : & str ) -> Result < Self :: Value , E >
48+ where
49+ E : de:: Error ,
50+ {
51+ match value {
52+ "auto" => Ok ( Width :: Auto ) ,
53+ _ => value
54+ . parse :: < u16 > ( )
55+ . map ( Width :: Size )
56+ . map_err ( |_| de:: Error :: invalid_value ( Unexpected :: Str ( value) , & self ) ) ,
57+ }
58+ }
59+
60+ fn visit_u64 < E > ( self , value : u64 ) -> Result < Self :: Value , E >
61+ where
62+ E : de:: Error ,
63+ {
64+ match u16:: try_from ( value) {
65+ Ok ( v) => Ok ( Width :: Size ( v) ) ,
66+ Err ( _) => Err ( de:: Error :: invalid_value ( Unexpected :: Unsigned ( value) , & self ) ) ,
67+ }
68+ }
69+
70+ fn visit_i64 < E > ( self , value : i64 ) -> Result < Self :: Value , E >
71+ where
72+ E : de:: Error ,
73+ {
74+ match u16:: try_from ( value) {
75+ Ok ( v) => Ok ( Width :: Size ( v) ) ,
76+ Err ( _) => Err ( de:: Error :: invalid_value ( Unexpected :: Signed ( value) , & self ) ) ,
77+ }
78+ }
79+ }
80+
81+ impl < ' de > Deserialize < ' de > for Width {
82+ fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
83+ where
84+ D : Deserializer < ' de > ,
85+ {
86+ deserializer. deserialize_any ( WidthVisitor )
87+ }
88+ }
89+
1890#[ derive( Deserialize , Debug ) ]
1991pub struct Adapter {
2092 #[ serde( default = "default_toggle_adapter_pairing" ) ]
@@ -59,6 +131,33 @@ impl Default for PairedDevice {
59131 }
60132}
61133
134+ fn deserialize_layout < ' de , D > ( deserializer : D ) -> Result < Flex , D :: Error >
135+ where
136+ D : Deserializer < ' de > ,
137+ {
138+ let s = String :: deserialize ( deserializer) ?;
139+
140+ match s. as_str ( ) {
141+ "Legacy" => Ok ( Flex :: Legacy ) ,
142+ "Start" => Ok ( Flex :: Start ) ,
143+ "End" => Ok ( Flex :: End ) ,
144+ "Center" => Ok ( Flex :: Center ) ,
145+ "SpaceAround" => Ok ( Flex :: SpaceAround ) ,
146+ "SpaceBetween" => Ok ( Flex :: SpaceBetween ) ,
147+ _ => {
148+ eprintln ! ( "Wrong config: unknown layout variant {}" , s) ;
149+ eprintln ! (
150+ "The possible values are: Legacy, Start, End, Center, SpaceAround, SpaceBetween"
151+ ) ;
152+ std:: process:: exit ( 1 ) ;
153+ }
154+ }
155+ }
156+
157+ fn default_layout ( ) -> Flex {
158+ Flex :: SpaceAround
159+ }
160+
62161fn default_set_new_name ( ) -> char {
63162 'e'
64163}
@@ -88,21 +187,23 @@ fn default_toggle_device_trust() -> char {
88187}
89188
90189impl Config {
91- pub fn new ( ) -> Self {
92- let conf_path = dirs:: config_dir ( )
93- . unwrap ( )
94- . join ( "bluetui" )
95- . join ( "config.toml" ) ;
190+ pub fn new ( config_file_path : Option < PathBuf > ) -> Self {
191+ let conf_path = config_file_path. unwrap_or (
192+ dirs:: config_dir ( )
193+ . unwrap ( )
194+ . join ( "bluetui" )
195+ . join ( "config.toml" ) ,
196+ ) ;
96197
97198 let config = std:: fs:: read_to_string ( conf_path) . unwrap_or_default ( ) ;
98- let app_config: Config = toml:: from_str ( & config) . unwrap ( ) ;
199+ let app_config: Config = match toml:: from_str ( & config) {
200+ Ok ( c) => c,
201+ Err ( e) => {
202+ eprintln ! ( "{}" , e) ;
203+ exit ( 1 ) ;
204+ }
205+ } ;
99206
100207 app_config
101208 }
102209}
103-
104- impl Default for Config {
105- fn default ( ) -> Self {
106- Self :: new ( )
107- }
108- }
0 commit comments