use std::collections::HashMap;
use crate::config::{lurk_config_file, Settings, LURK_CONFIG};
use crate::field::LanguageField;
use camino::Utf8PathBuf;
use config::{Config, ConfigError, Environment, File};
use once_cell::sync::OnceCell;
use serde::Deserialize;
use super::backend::Backend;
use super::paths::{circom_default_dir, commits_default_dir, proofs_default_dir};
pub(crate) static CLI_CONFIG: OnceCell<CliSettings> = OnceCell::new();
pub(crate) fn cli_config(
config_file: Option<&Utf8PathBuf>,
settings: Option<&HashMap<&str, String>>,
) -> &'static CliSettings {
LURK_CONFIG
.set(Settings::from_config(lurk_config_file(config_file), settings).unwrap_or_default())
.unwrap_or(());
CLI_CONFIG.get_or_init(|| {
CliSettings::from_config(lurk_config_file(config_file), settings).unwrap_or_default()
})
}
#[derive(Debug, Deserialize)]
pub(crate) struct CliSettings {
pub(crate) proofs_dir: Utf8PathBuf,
pub(crate) commits_dir: Utf8PathBuf,
pub(crate) circom_dir: Utf8PathBuf,
pub(crate) backend: Backend,
pub(crate) field: LanguageField,
pub(crate) rc: usize,
pub(crate) limit: usize,
}
impl CliSettings {
pub(crate) fn from_config(
config_file: &Utf8PathBuf,
cli_settings: Option<&HashMap<&str, String>>,
) -> Result<Self, ConfigError> {
let (proofs, commits, circom, backend, field, rc, limit) = (
"proofs_dir",
"commits_dir",
"circom_dir",
"backend",
"field",
"rc",
"limit",
);
Config::builder()
.set_default(proofs, proofs_default_dir().to_string())?
.set_default(commits, commits_default_dir().to_string())?
.set_default(circom, circom_default_dir().to_string())?
.set_default(backend, Backend::default().to_string())?
.set_default(field, LanguageField::default().to_string())?
.set_default(rc, 10)?
.set_default(limit, 100_000_000)?
.add_source(File::with_name(config_file.as_str()).required(false))
.add_source(Environment::with_prefix("LURK"))
.set_override_option(proofs, cli_settings.and_then(|s| s.get(proofs).cloned()))?
.set_override_option(commits, cli_settings.and_then(|s| s.get(commits).cloned()))?
.set_override_option(circom, cli_settings.and_then(|s| s.get(circom).cloned()))?
.set_override_option(backend, cli_settings.and_then(|s| s.get(backend).cloned()))?
.set_override_option(field, cli_settings.and_then(|s| s.get(field).cloned()))?
.set_override_option(rc, cli_settings.and_then(|s| s.get(rc).cloned()))?
.set_override_option(limit, cli_settings.and_then(|s| s.get(limit).cloned()))?
.build()
.and_then(|c| c.try_deserialize())
}
}
impl Default for CliSettings {
fn default() -> Self {
Self {
proofs_dir: proofs_default_dir(),
commits_dir: commits_default_dir(),
circom_dir: circom_default_dir(),
backend: Backend::default(),
field: LanguageField::default(),
rc: 10,
limit: 100_000_000,
}
}
}
#[cfg(test)]
mod tests {
use camino::Utf8Path;
use std::io::prelude::*;
use tempfile::Builder;
use crate::cli::backend::Backend;
use crate::cli::config::CliSettings;
use crate::config::Settings;
use crate::field::LanguageField;
#[test]
fn test_config_cli() {
let tmp_dir = Builder::new().prefix("tmp").tempdir().unwrap();
let tmp_dir = Utf8Path::from_path(tmp_dir.path()).unwrap();
let config_dir = tmp_dir.join("lurk.toml");
let public_params_dir = tmp_dir.join("public_params").into_string();
let proofs_dir = tmp_dir.join("proofs").into_string();
let commits_dir = tmp_dir.join("commits").into_string();
let circom_dir = tmp_dir.join("circom").into_string();
let backend = "Nova";
let field = "Pallas";
let rc = 100;
let limit = 100_000;
let mut config_file = std::fs::File::create(config_dir.clone()).unwrap();
config_file
.write_all(format!("public_params_dir = \"{public_params_dir}\"\n").as_bytes())
.unwrap();
config_file
.write_all(format!("proofs_dir = \"{proofs_dir}\"\n").as_bytes())
.unwrap();
config_file
.write_all(format!("commits_dir = \"{commits_dir}\"\n").as_bytes())
.unwrap();
config_file
.write_all(format!("circom_dir = \"{circom_dir}\"\n").as_bytes())
.unwrap();
config_file
.write_all(format!("backend = \"{backend}\"\n").as_bytes())
.unwrap();
config_file
.write_all(format!("field = \"{field}\"\n").as_bytes())
.unwrap();
config_file
.write_all(format!("rc = {rc}\n").as_bytes())
.unwrap();
config_file
.write_all(format!("limit = {limit}\n").as_bytes())
.unwrap();
let cli_config = CliSettings::from_config(&config_dir, None).unwrap();
let lurk_config = Settings::from_config(&config_dir, None).unwrap();
assert_eq!(lurk_config.public_params_dir, public_params_dir);
assert_eq!(cli_config.proofs_dir, proofs_dir);
assert_eq!(cli_config.commits_dir, commits_dir);
assert_eq!(cli_config.circom_dir, circom_dir);
assert_eq!(cli_config.backend, Backend::Nova);
assert_eq!(cli_config.field, LanguageField::Pallas);
assert_eq!(cli_config.rc, rc);
assert_eq!(cli_config.limit, limit);
}
}