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