use std::collections::BTreeMap; use std::fs::File; use std::io::{BufRead, BufReader, Result, Write}; use std::path::Path; /// Temporary structure, created when reading a file containing OID declarations #[derive(Debug)] pub struct LoadedEntry { /// Name of the global constant for this entry. /// /// If `name` is "", then no global constant is defined pub name: String, /// Textual representation of OID (ex: 2.5.4.3) pub oid: String, /// A short name to describe OID. Should be unique (no check is done) pub sn: String, /// A description for this entry pub description: String, } /// Temporary structure, created when reading a file containing OID declarations pub type LoadedMap = BTreeMap>; /// Load a file to an OID description map /// /// format of the file: tab-separated values ///
/// feature   name   oid   short_name   description (until end of line)
/// 
/// /// `name` is used to declare a global constant when creating output file (see `generate_file`). /// If `name` is "" then no constant will be written /// pub fn load_file>(path: P) -> Result { let mut map = BTreeMap::new(); let file = File::open(path)?; for line in BufReader::new(file).lines() { let line = line?; if line.is_empty() || line.starts_with('#') { continue; } // split by tabs let mut iter = line.splitn(5, '\t'); let feature = iter.next().expect("invalid oid_db format: missing feature").replace("-", "_"); let name = iter.next().expect("invalid oid_db format: missing name").to_string(); let oid = iter.next().expect("invalid oid_db format: missing OID").to_string(); let sn = iter.next().expect("invalid oid_db format: missing short name").to_string(); let description = iter.next().expect("invalid oid_db format: missing description").to_string(); let entry = LoadedEntry { name, oid, sn, description, }; let v = map.entry(feature.to_string()).or_insert_with(Vec::new); v.push(entry); } Ok(map) } /// Generate a file containing a `with_` method for OidRegistry pub fn generate_file>(map: &LoadedMap, dest_path: P) -> Result<()> { let mut out_file = File::create(&dest_path)?; for feat_entries in map.values() { for v in feat_entries { if v.name != "\"\"" { writeln!(out_file, "/// {}", v.oid)?; writeln!(out_file, "pub const {}: Oid<'static> = oid!({});", v.name, v.oid)?; } } } writeln!(out_file)?; writeln!(out_file, "impl<'a> OidRegistry<'a> {{")?; for (k, v) in map { writeln!(out_file, r#" #[cfg(feature = "{}")]"#, k)?; writeln!(out_file, r#" #[cfg_attr(docsrs, doc(cfg(feature = "{}")))]"#, k)?; writeln!( out_file, r#" #[doc = "Load all known OIDs for feature `{}` in the registry."]"#, k )?; writeln!(out_file, " pub fn with_{}(mut self) -> Self {{", k)?; for item in v { writeln!( out_file, r#" self.insert(oid!({}), OidEntry::new("{}", "{}"));"#, item.oid, item.sn, item.description )?; } writeln!(out_file, " self")?; writeln!(out_file, " }}")?; writeln!(out_file)?; } writeln!(out_file, "}}")?; Ok(()) }