Skip to content

Commit eb599c0

Browse files
committed
chore: Refactor markdown content and code structure in config_man
1 parent 803df38 commit eb599c0

File tree

3 files changed

+40
-29
lines changed

3 files changed

+40
-29
lines changed

DesignModule04/Singleton.rs

+2-10
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ use std::collections::HashMap;
22
use std::sync::{Arc, Mutex, Once};
33
use std::fs;
44
use std::io;
5+
use std::thread;
56

67
struct ConfigManager {
78
config: HashMap<String, String>,
89
}
910

1011
impl ConfigManager {
1112
fn new() -> Result<Self, io::Error> {
12-
// Simulate loading configuration from a file
1313
let config_str = fs::read_to_string("config.toml")?;
1414
let config = parse_config(&config_str);
1515
Ok(ConfigManager { config })
@@ -24,7 +24,6 @@ impl ConfigManager {
2424
}
2525

2626
fn save(&self) -> Result<(), io::Error> {
27-
// Simulate saving configuration to a file
2827
let config_str = format_config(&self.config);
2928
fs::write("config.toml", config_str)
3029
}
@@ -52,7 +51,6 @@ fn get_config() -> Arc<Mutex<ConfigManager>> {
5251
}
5352

5453
fn parse_config(config_str: &str) -> HashMap<String, String> {
55-
// This is a simplified parser. In a real application, you'd use a proper TOML parser.
5654
config_str
5755
.lines()
5856
.filter_map(|line| {
@@ -74,26 +72,21 @@ fn format_config(config: &HashMap<String, String>) -> String {
7472
.join("\n")
7573
}
7674

77-
use std::thread;
7875

7976
fn main() -> Result<(), Box<dyn std::error::Error>> {
80-
// Simulate multiple parts of an application accessing and modifying the configuration
8177
let handles: Vec<_> = (0..3)
8278
.map(|i| {
8379
thread::spawn(move || {
8480
let config = get_config();
8581
let mut config = config.lock().unwrap();
8682

87-
// Read a configuration value
8883
let db_url = config.get("database_url").cloned().unwrap_or_default();
8984
println!("Thread {} read database_url: {}", i, db_url);
9085

91-
// Modify a configuration value
9286
let new_value = format!("new_value_from_thread_{}", i);
9387
config.set(format!("key_from_thread_{}", i), new_value.clone());
9488
println!("Thread {} set new value: {}", i, new_value);
9589

96-
// Simulate some work
9790
thread::sleep(std::time::Duration::from_millis(100));
9891
})
9992
})
@@ -103,11 +96,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
10396
handle.join().unwrap();
10497
}
10598

106-
// After all threads have finished, save the configuration
10799
let config = get_config();
108100
let config = config.lock().unwrap();
109101
config.save()?;
110102
println!("Configuration saved.");
111103

112104
Ok(())
113-
}
105+
}

DesignModule04/config_man/Readme.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# ConfigManager Singleton
22

3-
This project demonstrates the implementation of the Singleton pattern in Rust using a `ConfigManager` as a real-world example.
3+
This project demonstrates the Singleton pattern in Rust using a `ConfigManager` as a real-world example.
44

55
## Overview
66

@@ -10,8 +10,8 @@ The `ConfigManager` is a thread-safe, globally accessible configuration manager
1010

1111
- Thread-safe access to configuration
1212
- Lazy initialization
13-
- Ability to read and write configuration values
14-
- Persistence of configuration to a file
13+
- Read and write configuration values
14+
- Persist configuration to a file
1515

1616
## Mermaid Diagram
1717

@@ -32,7 +32,7 @@ graph TD
3232
G & H & I --> J[Save Config to File]
3333
```
3434

35-
## How it works
35+
## How It Works
3636

3737
1. The application requests access to the ConfigManager via the `get_config()` function.
3838
2. If it's the first access, a new ConfigManager is created, the configuration is loaded from a file, and the instance is stored in a static variable.
@@ -42,7 +42,7 @@ graph TD
4242

4343
## Usage
4444

45-
To use the ConfigManager in your code:
45+
To use the ConfigManager Singleton in your code:
4646

4747
```rust
4848
let config = get_config();
@@ -67,4 +67,4 @@ config_guard.save().unwrap();
6767

6868
## Notes
6969

70-
While the Singleton pattern can be useful for managing global state, it should be used judiciously. Consider whether dependency injection or simple module-level variables might be more appropriate for your use case.
70+
While the Singleton pattern can be useful for managing global state, it should be used judiciously. Consider whether dependency injection or simple module-level variables might be more appropriate for your use case.

DesignModule04/config_man/src/main.rs

+32-13
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ use std::collections::HashMap;
22
use std::sync::{Arc, Mutex, Once};
33
use std::fs;
44
use std::io;
5+
use std::thread;
56

67
struct ConfigManager {
78
config: HashMap<String, String>,
89
}
910

1011
impl ConfigManager {
1112
fn new() -> Result<Self, io::Error> {
12-
// Simulate loading configuration from a file
13-
let config_str = fs::read_to_string("config.toml")?;
13+
let config_str = fs::read_to_string("src/config.toml")?;
1414
let config = parse_config(&config_str);
1515
Ok(ConfigManager { config })
1616
}
@@ -24,7 +24,6 @@ impl ConfigManager {
2424
}
2525

2626
fn save(&self) -> Result<(), io::Error> {
27-
// Simulate saving configuration to a file
2827
let config_str = format_config(&self.config);
2928
fs::write("config.toml", config_str)
3029
}
@@ -52,7 +51,6 @@ fn get_config() -> Arc<Mutex<ConfigManager>> {
5251
}
5352

5453
fn parse_config(config_str: &str) -> HashMap<String, String> {
55-
// This is a simplified parser. In a real application, you'd use a proper TOML parser.
5654
config_str
5755
.lines()
5856
.filter_map(|line| {
@@ -67,33 +65,29 @@ fn parse_config(config_str: &str) -> HashMap<String, String> {
6765
}
6866

6967
fn format_config(config: &HashMap<String, String>) -> String {
70-
config
71-
.iter()
72-
.map(|(k, v)| format!("{} = {}", k, v))
68+
let mut keys: Vec<&String> = config.keys().collect();
69+
keys.sort();
70+
keys.iter()
71+
.map(|k| format!("{} = {}", k, config.get(*k).unwrap()))
7372
.collect::<Vec<String>>()
7473
.join("\n")
7574
}
7675

77-
use std::thread;
7876

7977
fn main() -> Result<(), Box<dyn std::error::Error>> {
80-
// Simulate multiple parts of an application accessing and modifying the configuration
8178
let handles: Vec<_> = (0..3)
8279
.map(|i| {
8380
thread::spawn(move || {
8481
let config = get_config();
8582
let mut config = config.lock().unwrap();
8683

87-
// Read a configuration value
8884
let db_url = config.get("database_url").cloned().unwrap_or_default();
8985
println!("Thread {} read database_url: {}", i, db_url);
9086

91-
// Modify a configuration value
9287
let new_value = format!("new_value_from_thread_{}", i);
9388
config.set(format!("key_from_thread_{}", i), new_value.clone());
9489
println!("Thread {} set new value: {}", i, new_value);
9590

96-
// Simulate some work
9791
thread::sleep(std::time::Duration::from_millis(100));
9892
})
9993
})
@@ -103,11 +97,36 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
10397
handle.join().unwrap();
10498
}
10599

106-
// After all threads have finished, save the configuration
107100
let config = get_config();
108101
let config = config.lock().unwrap();
109102
config.save()?;
110103
println!("Configuration saved.");
111104

112105
Ok(())
106+
}
107+
108+
#[cfg(test)]
109+
mod tests {
110+
use super::*;
111+
112+
#[test]
113+
fn test_parse_config() {
114+
let config_str = "key1 = value1\nkey2 = value2\nkey3 = value3";
115+
let config = parse_config(config_str);
116+
assert_eq!(config.len(), 3);
117+
assert_eq!(config.get("key1"), Some(&"value1".to_string()));
118+
assert_eq!(config.get("key2"), Some(&"value2".to_string()));
119+
assert_eq!(config.get("key3"), Some(&"value3".to_string()));
120+
}
121+
122+
#[test]
123+
fn test_format_config() {
124+
let mut config = HashMap::new();
125+
config.insert("key1".to_string(), "value1".to_string());
126+
config.insert("key2".to_string(), "value2".to_string());
127+
config.insert("key3".to_string(), "value3".to_string());
128+
129+
let config_str = format_config(&config);
130+
assert_eq!(config_str, "key1 = value1\nkey2 = value2\nkey3 = value3");
131+
}
113132
}

0 commit comments

Comments
 (0)