use crate::gui::pages::types::running_page::RunningPage;
use crate::gui::pages::types::settings_page::SettingsPage;
use crate::gui::types::config_window::ConfigWindow;
use crate::gui::types::export_pcap::ExportPcap;
use crate::gui::types::favorite::Favorites;
use crate::gui::types::filters::Filters;
use crate::gui::types::settings::Settings;
use crate::networking::types::capture_context::CaptureSourcePicklist;
use crate::networking::types::config_device::ConfigDevice;
use crate::networking::types::data_representation::DataRepr;
use crate::report::types::sort_type::SortType;
#[cfg(not(test))]
use crate::utils::error_logger::{ErrorLogger, Location};
#[cfg(not(test))]
use crate::{SNIFFNET_LOWERCASE, location};
#[cfg(not(test))]
use confy::ConfyError;
use serde::{Deserialize, Deserializer, Serialize};
pub static CONF: std::sync::LazyLock<Conf> = std::sync::LazyLock::new(Conf::load);
#[derive(Serialize, Deserialize, Default, Clone, PartialEq, Debug)]
#[serde(default)]
pub struct Conf {
#[serde(deserialize_with = "deserialize_or_default")]
pub capture_source_picklist: CaptureSourcePicklist,
#[serde(deserialize_with = "deserialize_or_default")]
pub import_pcap_path: String,
#[serde(deserialize_with = "deserialize_or_default")]
pub last_opened_setting: SettingsPage,
#[serde(deserialize_with = "deserialize_or_default")]
pub last_opened_page: RunningPage,
#[serde(deserialize_with = "deserialize_or_default")]
pub data_repr: DataRepr,
#[serde(deserialize_with = "deserialize_or_default")]
pub host_sort_type: SortType,
#[serde(deserialize_with = "deserialize_or_default")]
pub service_sort_type: SortType,
#[serde(deserialize_with = "deserialize_or_default")]
pub program_sort_type: SortType,
#[serde(deserialize_with = "deserialize_or_default")]
pub report_sort_type: SortType,
#[serde(deserialize_with = "deserialize_or_default")]
pub host_favorites_filter: bool,
#[serde(deserialize_with = "deserialize_or_default")]
pub service_favorites_filter: bool,
#[serde(deserialize_with = "deserialize_or_default")]
pub program_favorites_filter: bool,
#[serde(deserialize_with = "deserialize_or_default")]
pub window: ConfigWindow,
#[serde(deserialize_with = "deserialize_or_default")]
pub device: ConfigDevice,
#[serde(deserialize_with = "deserialize_or_default")]
pub filters: Filters,
#[serde(deserialize_with = "deserialize_or_default")]
pub export_pcap: ExportPcap,
#[serde(deserialize_with = "deserialize_or_default")]
pub settings: Settings,
#[serde(deserialize_with = "deserialize_or_default")]
pub favorites: Favorites,
}
impl Conf {
pub(crate) const FILE_NAME: &'static str = "conf";
#[cfg(not(test))]
fn load() -> Self {
let mut conf = if let Ok(conf) = confy::load::<Conf>(SNIFFNET_LOWERCASE, Self::FILE_NAME) {
conf
} else {
let _ = Conf::default().store();
Conf::default()
};
if !(0.3..=3.0).contains(&conf.settings.scale_factor) {
conf.settings.scale_factor = 1.0;
}
conf.window.sanitize(conf.settings.scale_factor);
if !(0..=100).contains(&conf.settings.notifications.volume) {
conf.settings.notifications.volume = 50;
}
conf
}
#[cfg(not(test))]
pub fn store(&self) -> Result<(), ConfyError> {
confy::store(SNIFFNET_LOWERCASE, Self::FILE_NAME, self).log_err(location!())
}
}
#[allow(clippy::unnecessary_wraps)]
pub(crate) fn deserialize_or_default<'de, T, D>(deserializer: D) -> Result<T, D::Error>
where
T: Deserialize<'de> + Default,
D: Deserializer<'de>,
{
Ok(T::deserialize(deserializer).unwrap_or_default())
}
#[cfg(test)]
mod tests {
use crate::gui::types::conf::Conf;
impl Conf {
pub fn test_path() -> String {
format!("{}/{}.toml", env!("CARGO_MANIFEST_DIR"), Self::FILE_NAME)
}
pub fn load() -> Self {
confy::load_path::<Conf>(Conf::test_path()).unwrap_or_else(|_| Conf::default())
}
pub fn store(&self) -> Result<(), confy::ConfyError> {
confy::store_path(Conf::test_path(), self)
}
}
}