caretta_sync_core/config/
mod.rs1pub mod error;
2mod iroh;
3mod rpc;
4mod storage;
5
6use crate::utils::{emptiable::Emptiable, mergeable::Mergeable};
7pub use error::ConfigError;
8use serde::{Deserialize, Serialize};
9use std::{
10 default::Default,
11 fs::File,
12 io::{Read, Write},
13 path::Path,
14};
15
16pub use iroh::{IrohConfig, PartialIrohConfig};
17pub use rpc::*;
18pub use storage::{PartialStorageConfig, StorageConfig};
19use tokio::io::{AsyncReadExt, AsyncWriteExt};
20
21#[cfg(feature = "cli")]
22use clap::Args;
23
24#[derive(Clone, Debug)]
25pub struct Config {
26 pub iroh: IrohConfig,
27 pub storage: StorageConfig,
28 pub rpc: RpcConfig,
29}
30
31impl AsRef<StorageConfig> for Config {
32 fn as_ref(&self) -> &StorageConfig {
33 &self.storage
34 }
35}
36
37impl AsRef<IrohConfig> for Config {
38 fn as_ref(&self) -> &IrohConfig {
39 &self.iroh
40 }
41}
42
43impl AsRef<RpcConfig> for Config {
44 fn as_ref(&self) -> &RpcConfig {
45 &self.rpc
46 }
47}
48
49impl TryFrom<PartialConfig> for Config {
50 type Error = crate::error::Error;
51 fn try_from(value: PartialConfig) -> Result<Self, Self::Error> {
52 Ok(Self {
53 rpc: value
54 .rpc
55 .ok_or(crate::error::Error::MissingConfig("rpc"))?
56 .try_into()?,
57 iroh: value
58 .iroh
59 .ok_or(crate::error::Error::MissingConfig("p2p"))?
60 .try_into()?,
61 storage: value
62 .storage
63 .ok_or(crate::error::Error::MissingConfig("storage"))?
64 .try_into()?,
65 })
66 }
67}
68
69#[cfg_attr(feature = "cli", derive(Args))]
70#[derive(Clone, Debug, Deserialize, Serialize)]
71pub struct PartialConfig {
72 #[cfg_attr(feature = "cli", command(flatten))]
73 pub iroh: Option<PartialIrohConfig>,
74 #[cfg_attr(feature = "cli", command(flatten))]
75 pub storage: Option<PartialStorageConfig>,
76 #[cfg_attr(feature = "cli", command(flatten))]
77 pub rpc: Option<PartialRpcConfig>,
78}
79
80impl Default for PartialConfig {
81 fn default() -> Self {
82 Self::new()
83 }
84}
85
86impl PartialConfig {
87 pub fn new() -> Self {
88 Self {
89 iroh: Some(PartialIrohConfig::empty().with_new_secret_key()),
90 storage: Some(PartialStorageConfig::empty()),
91 rpc: Some(PartialRpcConfig::empty()),
92 }
93 }
94 pub fn from_toml(s: &str) -> Result<Self, toml::de::Error> {
95 toml::from_str(s)
96 }
97 pub fn into_toml(&self) -> Result<String, toml::ser::Error> {
98 toml::to_string(self)
99 }
100 pub fn read_or_create<T>(path: T) -> Result<Self, ConfigError>
101 where
102 T: AsRef<Path>,
103 {
104 if !path.as_ref().exists() {
105 Self::new().write_to(&path)?;
106 }
107 Self::read_from(&path)
108 }
109 pub fn read_from<T>(path: T) -> Result<Self, ConfigError>
110 where
111 T: AsRef<Path>,
112 {
113 if !path.as_ref().exists() {
114 if let Some(x) = path.as_ref().parent() {
115 std::fs::create_dir_all(x)?;
116 };
117 let _ = File::create(&path)?;
118 }
119 let mut file = File::open(path.as_ref())?;
120 let mut content = String::new();
121 file.read_to_string(&mut content)?;
122 let config: Self = toml::from_str(&content)?;
123 Ok(config)
124 }
125 pub fn write_to<T>(&self, path: T) -> Result<(), ConfigError>
126 where
127 T: AsRef<Path>,
128 {
129 if !path.as_ref().exists() {
130 if let Some(x) = path.as_ref().parent() {
131 std::fs::create_dir_all(x)?;
132 };
133 let _ = File::create(&path)?;
134 }
135 let mut file = File::create(&path)?;
136 file.write_all(toml::to_string(self)?.as_bytes())?;
137 Ok(())
138 }
139 pub fn default(app_name: &'static str) -> Self {
140 Self {
141 iroh: Some(PartialIrohConfig::default()),
142 rpc: Some(PartialRpcConfig::default(app_name)),
143 storage: Some(PartialStorageConfig::default(app_name)),
144 }
145 }
146}
147
148impl From<Config> for PartialConfig {
149 fn from(value: Config) -> Self {
150 Self {
151 iroh: Some(value.iroh.into()),
152 storage: Some(value.storage.into()),
153 rpc: Some(value.rpc.into()),
154 }
155 }
156}
157
158impl Emptiable for PartialConfig {
159 fn empty() -> Self {
160 Self {
161 iroh: None,
162 storage: None,
163 rpc: None,
164 }
165 }
166
167 fn is_empty(&self) -> bool {
168 self.iroh.is_empty() && self.rpc.is_empty() && self.storage.is_empty()
169 }
170}
171
172impl Mergeable for PartialConfig {
173 fn merge(&mut self, other: Self) {
174 self.iroh.merge(other.iroh);
175 self.rpc.merge(other.rpc);
176 self.storage.merge(other.storage);
177 }
178}