oid_registry/
load.rs

1use std::collections::BTreeMap;
2use std::fs::File;
3use std::io::{BufRead, BufReader, Result, Write};
4use std::path::Path;
5
6/// Temporary structure, created when reading a file containing OID declarations
7#[derive(Debug)]
8pub struct LoadedEntry {
9    /// Name of the global constant for this entry.
10    ///
11    /// If `name` is "", then no global constant is defined
12    pub name: String,
13    /// Textual representation of OID (ex: 2.5.4.3)
14    pub oid: String,
15    /// A short name to describe OID. Should be unique (no check is done)
16    pub sn: String,
17    /// A description for this entry
18    pub description: String,
19}
20
21/// Temporary structure, created when reading a file containing OID declarations
22pub type LoadedMap = BTreeMap<String, Vec<LoadedEntry>>;
23
24/// Load a file to an OID description map
25///
26/// format of the file: tab-separated values
27/// <pre>
28/// feature   name   oid   short_name   description (until end of line)
29/// </pre>
30///
31/// `name` is used to declare a global constant when creating output file (see `generate_file`).
32/// If `name` is "" then no constant will be written
33///
34pub fn load_file<P: AsRef<Path>>(path: P) -> Result<LoadedMap> {
35    let mut map = BTreeMap::new();
36
37    let file = File::open(path)?;
38    for line in BufReader::new(file).lines() {
39        let line = line?;
40        if line.is_empty() || line.starts_with('#') {
41            continue;
42        }
43        // split by tabs
44        let mut iter = line.splitn(5, '\t');
45        let feature = iter.next().expect("invalid oid_db format: missing feature").replace('-', "_");
46        let name = iter.next().expect("invalid oid_db format: missing name").to_string();
47        let oid = iter.next().expect("invalid oid_db format: missing OID").to_string();
48        let sn = iter.next().expect("invalid oid_db format: missing short name").to_string();
49        let description = iter.next().expect("invalid oid_db format: missing description").to_string();
50
51        let entry = LoadedEntry {
52            name,
53            oid,
54            sn,
55            description,
56        };
57
58        let v = map.entry(feature.to_string()).or_insert_with(Vec::new);
59
60        v.push(entry);
61    }
62    Ok(map)
63}
64
65/// Generate a file containing a `with_<feat>` method for OidRegistry
66pub fn generate_file<P: AsRef<Path>>(map: &LoadedMap, dest_path: P) -> Result<()> {
67    let mut out_file = File::create(&dest_path)?;
68    for feat_entries in map.values() {
69        for v in feat_entries {
70            if v.name != "\"\"" {
71                writeln!(out_file, "/// {}", v.oid)?;
72                writeln!(out_file, "pub const {}: Oid<'static> = oid!({});", v.name, v.oid)?;
73            }
74        }
75    }
76    writeln!(out_file)?;
77    writeln!(out_file, r#"#[cfg(feature = "registry")]"#)?;
78    writeln!(out_file, r#"#[cfg_attr(docsrs, doc(cfg(feature = "registry")))]"#)?;
79    writeln!(out_file, "impl<'a> OidRegistry<'a> {{")?;
80    for (k, v) in map {
81        writeln!(out_file, r#"    #[cfg(feature = "{}")]"#, k)?;
82        writeln!(out_file, r#"    #[cfg_attr(docsrs, doc(cfg(feature = "{}")))]"#, k)?;
83        writeln!(
84            out_file,
85            r#"    #[doc = "Load all known OIDs for feature `{}` in the registry."]"#,
86            k
87        )?;
88        writeln!(out_file, "    pub fn with_{}(mut self) -> Self {{", k)?;
89        for item in v {
90            writeln!(
91                out_file,
92                r#"        self.insert(oid!({}), OidEntry::new("{}", "{}"));"#,
93                item.oid, item.sn, item.description
94            )?;
95        }
96        writeln!(out_file, "        self")?;
97        writeln!(out_file, "    }}")?;
98        writeln!(out_file)?;
99    }
100    writeln!(out_file, "}}")?;
101    Ok(())
102}