Skip to content

Commit aebb7df

Browse files
authored
Merge pull request #29 from MikhailMS/multiple_dics
Support for multiple dictionaries
2 parents 3fb51c7 + e770561 commit aebb7df

File tree

2 files changed

+149
-20
lines changed

2 files changed

+149
-20
lines changed

dict_examples/empty_test_dictionary_dict

Whitespace-only changes.

src/protocol/dictionary.rs

Lines changed: 149 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -137,26 +137,19 @@ impl Dictionary {
137137
let mut attributes: Vec<DictionaryAttribute> = Vec::new();
138138
let mut values: Vec<DictionaryValue> = Vec::new();
139139
let mut vendors: Vec<DictionaryVendor> = Vec::new();
140-
let mut vendor_name: String = String::new();
141-
142-
let reader = io::BufReader::new(File::open(file_path).map_err(|error| RadiusError::MalformedDictionaryError { error })?);
143-
let lines = reader.lines()
144-
.filter_map(Result::ok)
145-
.filter(|line| !line.is_empty())
146-
.filter(|line| !line.contains(&COMMENT_PREFIX));
147-
148-
for line in lines {
149-
let parsed_line: Vec<&str> = line.split_whitespace().filter(|&item| !item.is_empty()).collect();
150-
match parsed_line[0] {
151-
"ATTRIBUTE" => parse_attribute(parsed_line, &vendor_name, &mut attributes),
152-
"VALUE" => parse_value(parsed_line, &vendor_name, &mut values),
153-
"VENDOR" => parse_vendor(parsed_line, &mut vendors),
154-
"BEGIN-VENDOR" => { vendor_name.insert_str(0, parsed_line[1]) },
155-
"END-VENDOR" => { vendor_name.clear() },
156-
_ => continue
157-
}
158-
};
159-
Ok(Dictionary { attributes, values, vendors })
140+
141+
match parse_file(file_path, &mut attributes, &mut values, &mut vendors) {
142+
Ok(()) => Ok(Dictionary { attributes, values, vendors }),
143+
Err(error) => Err(error)
144+
}
145+
}
146+
147+
/// Adds a dictionary file to existing Dictionary
148+
///
149+
/// Processes attributes, values and vendors from supplied dictionary file
150+
/// and adds them to existing attributes, values and vendors
151+
pub fn add_file(&mut self, file_path: &str) -> Result<(), RadiusError> {
152+
parse_file(file_path, &mut self.attributes, &mut self.values, &mut self.vendors)
160153
}
161154

162155
/// Returns parsed DictionaryAttributes
@@ -198,6 +191,30 @@ fn assign_attribute_type(code_type: &str) -> Option<SupportedAttributeTypes> {
198191
}
199192
}
200193

194+
fn parse_file(file_path: &str, attributes: &mut Vec<DictionaryAttribute>, values: &mut Vec<DictionaryValue>, vendors: &mut Vec<DictionaryVendor>) -> Result<(), RadiusError> {
195+
let mut vendor_name: String = String::new();
196+
197+
let reader = io::BufReader::new(File::open(file_path).map_err(|error| RadiusError::MalformedDictionaryError { error })?);
198+
let lines = reader.lines()
199+
.filter_map(Result::ok)
200+
.filter(|line| !line.is_empty())
201+
.filter(|line| !line.contains(&COMMENT_PREFIX));
202+
203+
for line in lines {
204+
let parsed_line: Vec<&str> = line.split_whitespace().filter(|&item| !item.is_empty()).collect();
205+
match parsed_line[0] {
206+
"ATTRIBUTE" => parse_attribute(parsed_line, &vendor_name, attributes),
207+
"VALUE" => parse_value(parsed_line, &vendor_name, values),
208+
"VENDOR" => parse_vendor(parsed_line, vendors),
209+
"BEGIN-VENDOR" => { vendor_name.insert_str(0, parsed_line[1]) },
210+
"END-VENDOR" => { vendor_name.clear() },
211+
_ => continue
212+
}
213+
};
214+
215+
Ok(())
216+
}
217+
201218
fn parse_attribute(parsed_line: Vec<&str>, vendor_name: &str, attributes: &mut Vec<DictionaryAttribute>) {
202219
if let Ok(code) = parsed_line[2].parse::<u8>() {
203220
attributes.push(DictionaryAttribute {
@@ -341,4 +358,116 @@ mod tests {
341358
let expected_dict = Dictionary { attributes, values, vendors };
342359
assert_eq!(dict, expected_dict)
343360
}
361+
362+
#[test]
363+
fn test_add_file() {
364+
let empty_dictionary_path = "./dict_examples/empty_test_dictionary_dict";
365+
let dictionary_path = "./dict_examples/test_dictionary_dict";
366+
367+
let mut dict = Dictionary::from_file(empty_dictionary_path).unwrap();
368+
dict.add_file(dictionary_path).unwrap();
369+
370+
let mut attributes: Vec<DictionaryAttribute> = Vec::new();
371+
attributes.push(DictionaryAttribute {
372+
name: "User-Name".to_string(),
373+
vendor_name: "".to_string(),
374+
code: 1,
375+
code_type: Some(SupportedAttributeTypes::AsciiString)
376+
});
377+
attributes.push(DictionaryAttribute {
378+
name: "NAS-IP-Address".to_string(),
379+
vendor_name: "".to_string(),
380+
code: 4,
381+
code_type: Some(SupportedAttributeTypes::IPv4Addr)
382+
});
383+
attributes.push(DictionaryAttribute {
384+
name: "NAS-Port-Id".to_string(),
385+
vendor_name: "".to_string(),
386+
code: 5,
387+
code_type: Some(SupportedAttributeTypes::Integer)
388+
});
389+
attributes.push(DictionaryAttribute {
390+
name: "Framed-Protocol".to_string(),
391+
vendor_name: "".to_string(),
392+
code: 7,
393+
code_type: Some(SupportedAttributeTypes::Integer)
394+
});
395+
attributes.push(DictionaryAttribute {
396+
name: "Chargeable-User-Identity".to_string(),
397+
vendor_name: "".to_string(),
398+
code: 89,
399+
code_type: Some(SupportedAttributeTypes::ByteString)
400+
});
401+
attributes.push(DictionaryAttribute {
402+
name: "Delegated-IPv6-Prefix".to_string(),
403+
vendor_name: "".to_string(),
404+
code: 123,
405+
code_type: Some(SupportedAttributeTypes::IPv6Prefix)
406+
});
407+
attributes.push(DictionaryAttribute {
408+
name: "MIP6-Feature-Vector".to_string(),
409+
vendor_name: "".to_string(),
410+
code: 124,
411+
code_type: Some(SupportedAttributeTypes::Integer64)
412+
});
413+
attributes.push(DictionaryAttribute {
414+
name: "Mobile-Node-Identifier".to_string(),
415+
vendor_name: "".to_string(),
416+
code: 145,
417+
code_type: Some(SupportedAttributeTypes::ByteString)
418+
});
419+
attributes.push(DictionaryAttribute {
420+
name: "PMIP6-Home-Interface-ID".to_string(),
421+
vendor_name: "".to_string(),
422+
code: 153,
423+
code_type: Some(SupportedAttributeTypes::InterfaceId)
424+
});
425+
attributes.push(DictionaryAttribute {
426+
name: "PMIP6-Home-IPv4-HoA".to_string(),
427+
vendor_name: "".to_string(),
428+
code: 155,
429+
code_type: Some(SupportedAttributeTypes::IPv4Prefix)
430+
});
431+
attributes.push(DictionaryAttribute {
432+
name: "Somevendor-Name".to_string(),
433+
vendor_name: "Somevendor".to_string(),
434+
code: 1,
435+
code_type: Some(SupportedAttributeTypes::AsciiString)
436+
});
437+
attributes.push(DictionaryAttribute {
438+
name: "Somevendor-Number".to_string(),
439+
vendor_name: "Somevendor".to_string(),
440+
code: 2,
441+
code_type: Some(SupportedAttributeTypes::Integer)
442+
});
443+
attributes.push(DictionaryAttribute {
444+
name: "Class".to_string(),
445+
vendor_name: "".to_string(),
446+
code: 25,
447+
code_type: Some(SupportedAttributeTypes::ByteString)
448+
});
449+
450+
let mut values: Vec<DictionaryValue> = Vec::new();
451+
values.push(DictionaryValue {
452+
attribute_name: "Framed-Protocol".to_string(),
453+
value_name: "PPP".to_string(),
454+
vendor_name: "".to_string(),
455+
value: "1".to_string()
456+
});
457+
values.push(DictionaryValue {
458+
attribute_name: "Somevendor-Number".to_string(),
459+
value_name: "Two".to_string(),
460+
vendor_name: "Somevendor".to_string(),
461+
value: "2".to_string()
462+
});
463+
464+
let mut vendors: Vec<DictionaryVendor> = Vec::new();
465+
vendors.push(DictionaryVendor {
466+
name: "Somevendor".to_string(),
467+
id: 10,
468+
});
469+
470+
let expected_dict = Dictionary { attributes, values, vendors };
471+
assert_eq!(dict, expected_dict)
472+
}
344473
}

0 commit comments

Comments
 (0)