use std::collections::BTreeMap;
use std::error;
use std::fs::{File, OpenOptions};
use std::io::{BufReader, Write};
use serde::{Deserialize, Serialize};
pub fn read_config(
config_file_path: &str,
) -> Result<BTreeMap<String, ConfigCategory>, Box<dyn error::Error>> {
let f = File::open(config_file_path)?;
let reader = BufReader::new(f);
let config: BTreeMap<String, ConfigCategory> = serde_yaml::from_reader(reader)?;
Ok(config)
}
pub fn write_config(
config_file_path: &str,
config: BTreeMap<String, ConfigCategory>,
) -> Result<(), Box<dyn error::Error>> {
let mut f = OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(config_file_path)?;
let yaml = serde_yaml::to_string(&config).unwrap();
f.write_all(&yaml.into_bytes())?;
Ok(())
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "snake_case")]
#[serde(tag = "model")]
pub enum ConfigCategory {
Even { choices: Vec<String> },
Gaussian {
#[serde(default = "default_stddev_scaling_factor")]
stddev_scaling_factor: f64,
choices: Vec<String>,
},
Inventory { choices: Vec<InventoryChoice> },
#[serde(rename = "lru")]
Lru { choices: Vec<String> },
Lottery { choices: Vec<LotteryChoice> },
Weighted { choices: Vec<WeightedChoice> },
}
#[derive(Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct InventoryChoice {
pub name: String,
#[serde(default = "default_weight")]
pub tickets: u64,
}
#[derive(Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct LotteryChoice {
pub name: String,
#[serde(default = "default_reset")]
pub reset: u64,
#[serde(default = "default_weight")]
pub tickets: u64,
#[serde(default = "default_weight")]
pub weight: u64,
}
#[derive(Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct WeightedChoice {
pub name: String,
#[serde(default = "default_weight")]
pub weight: u64,
}
fn default_stddev_scaling_factor() -> f64 {
3.0
}
fn default_reset() -> u64 {
0
}
fn default_weight() -> u64 {
1
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_defaults() {
assert!((default_stddev_scaling_factor() - 3.0).abs() < 0.000_001);
assert_eq!(default_weight(), 1);
assert_eq!(default_reset(), 0);
}
}