1use serde::{Deserialize, Serialize};
2use std::fmt;
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
5pub struct Config {
6 pub api_key: String,
7 pub model_id: String,
8}
9
10impl Config {
11 pub fn load_from_path(path: &std::path::Path) -> Result<Self, ConfigError> {
12 let content = std::fs::read_to_string(path)?;
13 let config: Config =
14 serde_json::from_str(&content).map_err(|_| ConfigError::MalformedJson)?;
15 Ok(config)
16 }
17
18 pub fn save(&self, path: &std::path::Path) -> Result<(), ConfigError> {
19 let tmp_path = path.with_extension("json.tmp");
20 {
21 let mut file = std::fs::File::create(&tmp_path)?;
22 serde_json::to_writer_pretty(&mut file, self)?;
23 }
24
25 #[cfg(unix)]
26 {
27 use std::os::unix::fs::PermissionsExt;
28 let mut perms = std::fs::metadata(&tmp_path)?.permissions();
29 perms.set_mode(0o600);
30 std::fs::set_permissions(&tmp_path, perms)?;
31 }
32
33 std::fs::rename(&tmp_path, path)?;
34
35 Ok(())
36 }
37}
38
39#[derive(Debug)]
40pub enum ConfigError {
41 IoError(std::io::Error),
42 MalformedJson,
43 ApiError(String),
44}
45
46impl fmt::Display for ConfigError {
47 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48 match self {
49 ConfigError::IoError(e) => write!(f, "IO error: {}", e),
50 ConfigError::MalformedJson => write!(f, "Malformed JSON"),
51 ConfigError::ApiError(msg) => write!(f, "API error: {}", msg),
52 }
53 }
54}
55
56impl From<std::io::Error> for ConfigError {
57 fn from(e: std::io::Error) -> Self {
58 ConfigError::IoError(e)
59 }
60}
61
62impl From<serde_json::Error> for ConfigError {
63 fn from(_: serde_json::Error) -> Self {
64 ConfigError::MalformedJson
65 }
66}
67
68pub fn home_config_path() -> std::path::PathBuf {
69 let home = home::home_dir().expect("Cannot find home directory");
70 home.join(".comma.json")
71}