diff --git a/Cargo.lock b/Cargo.lock index ce14063..a1cda61 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,14 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "aho-corasick" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" +dependencies = [ + "memchr", +] + [[package]] name = "autocfg" version = "1.0.1" @@ -69,6 +78,15 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "847ce131b72ffb13b6109a221da9ad97a64cbe48feb1028356b836b47b8f1748" +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "unicode-width", +] + [[package]] name = "getrandom" version = "0.1.15" @@ -293,10 +311,12 @@ name = "radius-rs" version = "0.1.0" dependencies = [ "chrono", + "getopts", "log", "md5", "num_enum", "rand", + "regex", "thiserror", "tokio", ] @@ -348,6 +368,24 @@ version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" +[[package]] +name = "regex" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local", +] + +[[package]] +name = "regex-syntax" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189" + [[package]] name = "scopeguard" version = "1.1.0" @@ -424,6 +462,15 @@ dependencies = [ "syn", ] +[[package]] +name = "thread_local" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" +dependencies = [ + "lazy_static", +] + [[package]] name = "time" version = "0.1.44" @@ -477,6 +524,12 @@ dependencies = [ "serde", ] +[[package]] +name = "unicode-width" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" + [[package]] name = "unicode-xid" version = "0.2.1" diff --git a/Cargo.toml b/Cargo.toml index d2c84c1..d4f380d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,3 +14,5 @@ num_enum = "0.5.1" tokio = { version = "0.3.4", features = ["full"] } log = "0.4.11" thiserror = "1.0" +regex = "1" +getopts = "0.2" diff --git a/src/bin/code_gen.rs b/src/bin/code_gen.rs new file mode 100644 index 0000000..142ae79 --- /dev/null +++ b/src/bin/code_gen.rs @@ -0,0 +1,121 @@ +use std::collections::HashMap; +use std::fs::File; +use std::io::BufRead; +use std::path::Path; +use std::{env, io, process}; + +use getopts::Options; +use regex::Regex; + +const ATTRIBUTE_KIND: &str = "ATTRIBUTE"; +const VALUE_KIND: &str = "VALUE"; + +#[derive(Debug)] +struct RadiusAttribute { + name: String, + identifier: u16, + typ: String, + is_encrypt: bool, +} + +#[derive(Debug)] +struct RadiusValue { + name: String, + identifier: u16, +} + +fn print_usage(program: &str, opts: &Options) { + let brief = format!("Usage: {} FILE [options]", program); + print!("{}", opts.usage(&brief)); + process::exit(0); +} + +fn read_lines

(filename: P) -> io::Result>> +where + P: AsRef, +{ + let file = File::open(filename)?; + Ok(io::BufReader::new(file).lines()) +} + +fn main() { + let args: Vec = env::args().collect(); + let program = args[0].clone(); + + let mut opts = Options::new(); + let matches = opts + .parse(&args[1..]) + .unwrap_or_else(|f| panic!(f.to_string())); + + let dict_file_path = matches.free[0].clone(); + let (radius_attributes, radius_attribute_to_values) = parse_dict_file(dict_file_path).unwrap(); + println!("{:?}", radius_attributes); + println!("{:?}", radius_attribute_to_values); +} + +type DictParsed = (Vec, HashMap>); + +fn parse_dict_file(dict_file_path: String) -> Result { + let line_filter_re = Regex::new(r"^(?:#.*|)$").unwrap(); + let tabs_re = Regex::new(r"\t+").unwrap(); + + let mut radius_attributes: Vec = Vec::new(); + let mut radius_attribute_to_values: HashMap> = HashMap::new(); + + let lines = read_lines(dict_file_path).unwrap(); + for line_result in lines { + let line = line_result.unwrap(); + + if line_filter_re.is_match(line.as_str()) { + continue; + } + + let items = tabs_re.split(line.as_str()).collect::>(); + + if items.len() < 4 { + return Err("the number of items is lacked in a line".to_owned()); + } + + let kind = items[0]; + match kind { + ATTRIBUTE_KIND => { + let type_descriptions = items[3].split(' ').collect::>(); + let typ = type_descriptions[0].to_string(); + let is_encrypt = if type_descriptions.len() >= 2 { + type_descriptions[1] == "encrypt=1" // FIXME: ad-hoc!!! + } else { + false + }; + + radius_attributes.push(RadiusAttribute { + name: items[1].to_string(), + identifier: items[2].parse().unwrap(), + typ, + is_encrypt, + }); + } + VALUE_KIND => { + let attribute_name = items[1].to_string(); + let name = items[2].to_string(); + + let radius_value = RadiusValue { + name, + identifier: items[3].parse().unwrap(), + }; + + match radius_attribute_to_values.get_mut(&attribute_name) { + None => { + radius_attribute_to_values + .insert(attribute_name.clone(), vec![radius_value]); + } + Some(vec) => { + vec.push(radius_value); + } + }; + } + _ => return Err(format!("unexpected kind has come => {}", kind)), + } + } + + Ok((radius_attributes, radius_attribute_to_values)) +}