diff --git a/Cargo.lock b/Cargo.lock index c3c518c8e..fa11dde2b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,6 +19,12 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +[[package]] +name = "arraydeque" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" + [[package]] name = "autocfg" version = "1.1.0" @@ -41,9 +47,11 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" name = "dekoder" version = "0.0.1" dependencies = [ + "float-cmp", "glob", "hashbrown", "tar", + "yaml-rust2", ] [[package]] @@ -63,6 +71,15 @@ dependencies = [ "num", ] +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + [[package]] name = "errno" version = "0.3.9" @@ -110,6 +127,15 @@ dependencies = [ "allocator-api2", ] +[[package]] +name = "hashlink" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" +dependencies = [ + "hashbrown", +] + [[package]] name = "libc" version = "0.2.155" @@ -346,3 +372,14 @@ dependencies = [ "linux-raw-sys", "rustix", ] + +[[package]] +name = "yaml-rust2" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8902160c4e6f2fb145dbe9d6760a75e3c9522d8bf796ed7047c85919ac7115f8" +dependencies = [ + "arraydeque", + "encoding_rs", + "hashlink", +] diff --git a/crates/dekoder/Cargo.toml b/crates/dekoder/Cargo.toml index 1857a048d..619662a0b 100644 --- a/crates/dekoder/Cargo.toml +++ b/crates/dekoder/Cargo.toml @@ -23,3 +23,5 @@ crate-type = ["cdylib"] tar = "0.4.41" hashbrown = "0.14" glob = "0.3.1" +float-cmp = "0.9.0" +yaml-rust2 = "0.8" diff --git a/crates/dekoder/src/lib.rs b/crates/dekoder/src/lib.rs index d4028d1c7..4b50fc1f6 100644 --- a/crates/dekoder/src/lib.rs +++ b/crates/dekoder/src/lib.rs @@ -1,37 +1,79 @@ //! eko output reader. +use float_cmp::approx_eq; use glob::glob; use hashbrown::HashMap; -use std::fs::remove_dir_all; +use std::ffi::OsString; use std::fs::File; +use std::fs::{read_to_string, remove_dir_all}; use std::io::BufWriter; use std::path::PathBuf; +use yaml_rust2::{Yaml, YamlLoader}; +/// Headers are in yaml files. const HEADER_EXT: &'static str = "*.yaml"; -struct Inventory { + +/// Header type in an inventory. +trait HeaderT { + /// Load from yaml. + fn load(yml: &Yaml) -> Self; + /// Comparator. + fn eq(&self, other: &Self, ulps: i64) -> bool; +} + +/// A reference point in the evolution atlas. +pub struct EvolutionPoint { + /// Evolution scale. + scale: f64, + /// Number of flavors + nf: i64, +} + +impl HeaderT for EvolutionPoint { + /// Load from yaml. + fn load(yml: &Yaml) -> Self { + // work around float representation + let scale = yml["scale"].as_f64(); + let scale = if scale.is_some() { + scale.unwrap() + } else { + yml["scale"].as_i64().unwrap() as f64 + }; + Self { + scale: scale, + nf: yml["nf"].as_i64().unwrap(), + } + } + /// Comparator. + fn eq(&self, other: &Self, ulps: i64) -> bool { + self.nf == other.nf && approx_eq!(f64, self.scale, other.scale, ulps = ulps) + } +} + +/// Assets manager. +struct Inventory { /// Working directory path: PathBuf, /// Available items - keys: HashMap, + keys: HashMap, } -impl Inventory { - /// Load all available entries + +impl Inventory { + /// Load all available entries. pub fn load_keys(&mut self) { - for entry in glob(self.path.join(HEADER_EXT.to_owned()).to_str().unwrap()) + for entry in glob(self.path.join(&HEADER_EXT).to_str().unwrap()) .expect("Failed to read glob pattern") .filter(|x| x.is_ok()) + .map(|x| x.unwrap()) { - self.keys.insert( - (*entry.unwrap().file_name().unwrap()) - .to_os_string() - .into_string() - .unwrap(), - "Blub".to_string(), - ); + let cnt = YamlLoader::load_from_str(&read_to_string(&entry).unwrap()).unwrap(); + self.keys + .insert(entry.file_name().unwrap().to_os_string(), K::load(&cnt[0])); } } - pub fn has_key(&self, ep: String, ulps: f64) -> bool { - self.keys.values().find(|v| (*v).eq(&ep)).is_some() + /// Check if `k` is available (with given precision). + pub fn has_key(&self, k: K, ulps: i64) -> bool { + self.keys.values().find(|v| (*v).eq(&k, ulps)).is_some() } } @@ -44,10 +86,11 @@ pub struct EKO { /// allow content modifications? read_only: bool, /// final operators - operators: Inventory, + operators: Inventory, } -const DIR_OPERATORS: &'static str = "operators"; +/// Operators directory. +const DIR_OPERATORS: &'static str = "operators/"; impl EKO { /// Check our working directory is safe. @@ -152,7 +195,7 @@ impl EKO { } /// Check if the operator at the evolution point `ep` is available. - pub fn has_operator(&self, ep: String, ulps: f64) -> bool { + pub fn has_operator(&self, ep: EvolutionPoint, ulps: i64) -> bool { self.operators.has_key(ep, ulps) } } @@ -197,7 +240,7 @@ mod test { #[test] fn read_keys() { - use super::EKO; + use super::{EvolutionPoint, EKO}; use std::fs::remove_dir_all; use std::path::PathBuf; let base: PathBuf = [env!("CARGO_MANIFEST_DIR"), "tests"].iter().collect(); @@ -211,6 +254,12 @@ mod test { } // open let eko = EKO::read(src.to_owned(), dst.to_owned()); - assert!(eko.has_operator("Blub".to_string(), 1e-7)); + assert!(eko.has_operator( + EvolutionPoint { + scale: 10000., + nf: 4 + }, + 64 + )); } }