1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
//! Generic configuration parsing utilities.
//!
//! This module provides generic TOML parsing functionality that can be used
//! with any configuration structure that implements the appropriate serde traits.
//! It includes enhanced error reporting with file path context.
//!
//! # Features
//!
//! - **Generic Parsing**: Works with any `DeserializeOwned` type
//! - **Rich Error Context**: Includes file paths in error messages
//! - **TOML Focus**: Specifically designed for TOML configuration files
//! - **Path Safety**: Handles file system errors gracefully
//!
//! # Design Philosophy
//!
//! The parser is designed to be:
//! - **Simple**: Minimal API surface with clear semantics
//! - **Generic**: Reusable across different configuration types
//! - **Informative**: Provides clear error messages for debugging
//! - **Safe**: Handles file system and parsing errors appropriately
//!
//! # Usage Patterns
//!
//! ## Direct Parsing
//!
//! ```rust,no_run
//! use agpm_cli::config::parse_config;
//! use serde::Deserialize;
//! use std::path::Path;
//!
//! #[derive(Deserialize)]
//! struct MyConfig {
//! name: String,
//! version: String,
//! }
//!
//! # fn example() -> anyhow::Result<()> {
//! let config: MyConfig = parse_config(Path::new("config.toml"))?;
//! println!("Config: {} v{}", config.name, config.version);
//! # Ok(())
//! # }
//! ```
//!
//! # Error Handling
//!
//! The parser provides detailed error messages that include:
//!
//! - **File Context**: Which file failed to parse
//! - **Operation Context**: Whether it was a read or parse failure
//! - **Underlying Error**: The specific I/O or TOML parsing error
//!
//! Example error output:
//! ```text
//! Failed to parse config file: /path/to/config.toml
//! Caused by:
//! invalid TOML value, expected string
//! ```
//!
//! # Integration
//!
//! This parser is used throughout AGPM for:
//!
//! - Generic configuration file parsing
//! - Test fixtures and development tools
use ;
use Path;
/// Parse a TOML configuration file into the specified type.
///
/// Generic function that reads a TOML file and deserializes it into any type
/// that implements [`serde::de::DeserializeOwned`]. Provides enhanced error
/// messages that include the file path context.
///
/// # Type Parameters
///
/// - `T`: The target type that implements `DeserializeOwned`
///
/// # Parameters
///
/// - `path`: Path to the TOML configuration file to parse
///
/// # Returns
///
/// The parsed configuration object of type `T`.
///
/// # Examples
///
/// ## Basic Usage
///
/// ```rust,no_run
/// use agpm_cli::config::parse_config;
/// use serde::Deserialize;
/// use std::path::Path;
///
/// #[derive(Deserialize)]
/// struct Config {
/// name: String,
/// port: u16,
/// }
///
/// # fn example() -> anyhow::Result<()> {
/// let config: Config = parse_config(Path::new("server.toml"))?;
/// println!("Starting {} on port {}", config.name, config.port);
/// # Ok(())
/// # }
/// ```
///
/// ## Error Handling
///
/// ```rust,no_run
/// use agpm_cli::config::parse_config;
/// use serde::Deserialize;
/// use std::path::Path;
///
/// #[derive(Deserialize)]
/// struct Config { name: String }
///
/// # fn example() {
/// match parse_config::<Config>(Path::new("missing.toml")) {
/// Ok(config) => println!("Config loaded: {}", config.name),
/// Err(e) => eprintln!("Failed to load config: {}", e),
/// }
/// # }
/// ```
///
/// # Error Conditions
///
/// This function returns an error if:
///
/// ## File System Errors
/// - File does not exist
/// - Insufficient permissions to read the file
/// - I/O errors during file reading
/// - Path is a directory, not a file
///
/// ## Parsing Errors
/// - File contains invalid TOML syntax
/// - TOML structure doesn't match the target type `T`
/// - Required fields are missing
/// - Field types don't match expectations
/// - TOML contains unsupported features for the target type
///
/// # Error Messages
///
/// The function provides two levels of error context:
///
/// 1. **File Operation Context**: "Failed to read config file: /path/to/file.toml"
/// 2. **Parsing Context**: "Failed to parse config file: /path/to/file.toml"
///
/// The underlying error (file system or TOML parsing) is preserved as the cause.
///
/// # Performance
///
/// - Reads the entire file into memory before parsing
/// - TOML parsing is generally fast for typical configuration file sizes
/// - No caching - each call performs a fresh read and parse
///
/// # Thread Safety
///
/// This function is thread-safe and can be called concurrently from multiple threads.
/// Each call operates independently on the file system.