1
- use std:: { collections :: HashMap , env , sync:: RwLock } ;
1
+ use std:: { env , path :: Path , sync:: RwLock } ;
2
2
3
3
use clap:: { command, Arg , ArgMatches } ;
4
4
use config:: { builder:: DefaultState , Config , ConfigBuilder } ;
5
5
use console:: Style ;
6
6
use indicatif:: { ProgressBar , ProgressStyle } ;
7
7
use log:: { info, LevelFilter :: Info } ;
8
+ use mandelbrot:: mandelbrot_ascii;
8
9
use once_cell:: sync:: Lazy ;
9
10
use pretty_env_logger:: env_logger:: Builder ;
11
+ use serde:: { Deserialize , Serialize } ;
10
12
11
13
const ITERATIONS : u32 = 255 ;
12
14
const WIDTH : u32 = 800 ;
13
15
const HEIGHT : u32 = 800 ;
14
16
const DEFAULT_SETTINGS_FILE : & str = "settings.toml" ;
15
17
const DEFAULT_IMAGE_PATH : & str = "mandelbrot.png" ;
18
+ const DEFAULT_TEXT_PATH : & str = "mandelbrot.txt" ;
16
19
17
20
static CONFIG_BUILDER : Lazy < RwLock < ConfigBuilder < DefaultState > > > =
18
21
Lazy :: new ( || RwLock :: new ( Config :: builder ( ) ) ) ;
@@ -29,18 +32,15 @@ fn main() {
29
32
fn try_main ( ) -> anyhow:: Result < ( ) > {
30
33
let mut curr_path = env:: current_dir ( ) . unwrap ( ) ;
31
34
curr_path. push ( DEFAULT_SETTINGS_FILE ) ;
32
- // TODO: Directly mutate `CONFIG_BUILDER` without assigning it.
33
- let settings_builder: ConfigBuilder < DefaultState > = CONFIG_BUILDER
35
+ let settings_new: Config = CONFIG_BUILDER
34
36
. write ( )
35
37
. unwrap ( )
36
38
. clone ( )
37
39
. set_default ( "verbose" , "1" ) ? // This is not in the settings file.
38
40
. add_source ( config:: File :: with_name ( & curr_path. to_string_lossy ( ) ) )
39
- . add_source ( config:: Environment :: with_prefix ( "APP" ) ) ;
40
- // Does not take ownership of `ConfigBuilder` to allow later reuse.
41
- let settings_new: Config = settings_builder. build_cloned ( ) ?;
42
- // {"key": "189rjfadoisfj8923fjio", "verbose": "1", "priority": "32", "debug": "false"}
43
- let _map_new = settings_new. try_deserialize :: < HashMap < String , String > > ( ) ?;
41
+ . add_source ( config:: Environment :: with_prefix ( "APP" ) )
42
+ . build_cloned ( ) ?;
43
+ let config_manager: ConfigManager = settings_new. try_deserialize ( ) ?;
44
44
45
45
// Parse clap args.
46
46
let matches: ArgMatches = command ! ( )
@@ -69,9 +69,9 @@ fn try_main() -> anyhow::Result<()> {
69
69
info ! ( "Rendering image Mandelbrot set as {}" , Style :: new( ) . bold( ) . apply_to( "ASCII" ) ) ;
70
70
let pb = ProgressBar :: new ( WIDTH as u64 * HEIGHT as u64 ) ;
71
71
style_progress_bar ( & pb) ;
72
- let image = mandelbrot :: mandelbrot_ascii:: collect_ascii ( ) ;
72
+ let image = mandelbrot_ascii:: collect_ascii ( ) ;
73
73
pb. finish ( ) ;
74
- mandelbrot :: mandelbrot_ascii:: print_ascii ( image) ;
74
+ mandelbrot_ascii:: print_ascii ( image) ;
75
75
}
76
76
77
77
if let Some ( _text) = matches. get_one :: < String > ( "text" ) {
@@ -81,8 +81,8 @@ fn try_main() -> anyhow::Result<()> {
81
81
) ;
82
82
let pb = ProgressBar :: new ( WIDTH as u64 * HEIGHT as u64 ) ;
83
83
style_progress_bar ( & pb) ;
84
- let image = mandelbrot :: mandelbrot_ascii:: collect_ascii ( ) ;
85
- mandelbrot :: mandelbrot_ascii:: write_ascii_to_file ( image) ;
84
+ let image = mandelbrot_ascii:: collect_ascii ( ) ;
85
+ mandelbrot_ascii:: write_ascii_to_file ( image, Path :: new ( & config_manager . text ) ) ;
86
86
pb. finish_with_message ( "Wrote ascii to file" ) ;
87
87
}
88
88
@@ -93,7 +93,13 @@ fn try_main() -> anyhow::Result<()> {
93
93
) ;
94
94
let pb = ProgressBar :: new ( WIDTH as u64 * HEIGHT as u64 ) ;
95
95
style_progress_bar ( & pb) ;
96
- mandelbrot:: mandelbrot_img:: compose ( WIDTH , HEIGHT , ITERATIONS ) . save ( DEFAULT_IMAGE_PATH ) ?;
96
+ if config_manager. image . is_empty ( ) {
97
+ mandelbrot:: mandelbrot_img:: compose ( WIDTH , HEIGHT , ITERATIONS )
98
+ . save ( DEFAULT_IMAGE_PATH ) ?;
99
+ } else {
100
+ mandelbrot:: mandelbrot_img:: compose ( WIDTH , HEIGHT , ITERATIONS )
101
+ . save ( config_manager. image ) ?;
102
+ }
97
103
pb. finish_with_message ( "Saved image to file" ) ;
98
104
}
99
105
@@ -111,36 +117,36 @@ fn style_progress_bar(pb: &ProgressBar) {
111
117
112
118
/// `build_config_settings` is a wrapper around `config` crate.
113
119
///
114
- /// # Examples
115
- ///
116
- /// ```rust,ignore
117
- /// use config::Config;
118
- /// use mandelbrot::build_config_settings;
119
- ///
120
- /// fn main() {
121
- /// // TODO: Add `tempfile` crate or `include_str!()`.
122
- /// let settings = build_config_settings("settings.toml")?;
123
- /// let map = settings.try_deserialize::<HashMap<String, String>>().unwrap();
124
- /// let expect = r#"{"key": "189rjfadoisfj8923fjio", "debug": "false", "priority": "32"}"#;
125
- /// assert_eq!(map, expect);
126
- /// }
127
- /// ```
128
- /// # Panics
129
- ///
130
- /// Panics if .
131
- ///
132
- /// # Errors
133
- ///
134
- /// This function will return an error if .
120
+ /// * `build_cloned` method - Does not take ownership of `ConfigBuilder` to allow later reuse.
121
+ /// let map_new = settings_new.try_deserialize::<HashMap<String, String>>()?;
122
+ // NOTE: Directly mutate `CONFIG_BUILDER` without assigning it.
135
123
pub fn build_config_settings ( path : & str ) -> Result < Config , config:: ConfigError > {
136
124
let mut curr_path = env:: current_dir ( ) . unwrap ( ) ;
137
125
curr_path. push ( path) ;
138
126
127
+ // Add in `./settings.toml`
128
+ // Add in settings from the environment (with a prefix of APP)
129
+ // Eg.. `APP_DEBUG=1 ./target/app` would set the `debug` key
139
130
Config :: builder ( )
140
- // Add in `./settings.toml`
141
131
. add_source ( config:: File :: with_name ( & curr_path. to_string_lossy ( ) ) )
142
- // Add in settings from the environment (with a prefix of APP)
143
- // Eg.. `APP_DEBUG=1 ./target/app` would set the `debug` key
144
132
. add_source ( config:: Environment :: with_prefix ( "APP" ) )
145
133
. build ( )
146
134
}
135
+
136
+ #[ derive( Debug , Deserialize , Serialize ) ]
137
+ struct ConfigManager {
138
+ text : String ,
139
+ image : String ,
140
+ }
141
+
142
+ impl Default for ConfigManager {
143
+ fn default ( ) -> Self {
144
+ Self :: new ( )
145
+ }
146
+ }
147
+
148
+ impl ConfigManager {
149
+ fn new ( ) -> Self {
150
+ Self { text : DEFAULT_TEXT_PATH . to_string ( ) , image : DEFAULT_IMAGE_PATH . to_string ( ) }
151
+ }
152
+ }
0 commit comments