• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use std::collections::BTreeMap;
2 use std::fs::File;
3 use std::io::{BufRead, BufReader, Result, Write};
4 use std::path::Path;
5 
6 /// Temporary structure, created when reading a file containing OID declarations
7 #[derive(Debug)]
8 pub 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
22 pub 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 ///
load_file<P: AsRef<Path>>(path: P) -> Result<LoadedMap>34 pub 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
generate_file<P: AsRef<Path>>(map: &LoadedMap, dest_path: P) -> Result<()>66 pub 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, "impl<'a> OidRegistry<'a> {{")?;
78     for (k, v) in map {
79         writeln!(out_file, r#"    #[cfg(feature = "{}")]"#, k)?;
80         writeln!(out_file, r#"    #[cfg_attr(docsrs, doc(cfg(feature = "{}")))]"#, k)?;
81         writeln!(
82             out_file,
83             r#"    #[doc = "Load all known OIDs for feature `{}` in the registry."]"#,
84             k
85         )?;
86         writeln!(out_file, "    pub fn with_{}(mut self) -> Self {{", k)?;
87         for item in v {
88             writeln!(
89                 out_file,
90                 r#"        self.insert(oid!({}), OidEntry::new("{}", "{}"));"#,
91                 item.oid, item.sn, item.description
92             )?;
93         }
94         writeln!(out_file, "        self")?;
95         writeln!(out_file, "    }}")?;
96         writeln!(out_file)?;
97     }
98     writeln!(out_file, "}}")?;
99     Ok(())
100 }
101