@@ -127,29 +127,48 @@ pub struct Dictionary {
127
127
128
128
#[ allow( unused) ]
129
129
impl Dictionary {
130
+ fn from_lines ( lines : StringIterator ) -> Result < Dictionary , RadiusError > {
131
+ let mut attributes: Vec < DictionaryAttribute > = Vec :: new ( ) ;
132
+ let mut values: Vec < DictionaryValue > = Vec :: new ( ) ;
133
+ let mut vendors: Vec < DictionaryVendor > = Vec :: new ( ) ;
134
+
135
+ match parse_lines ( lines, & mut attributes, & mut values, & mut vendors) {
136
+ Ok ( ( ) ) => Ok ( Dictionary { attributes, values, vendors } ) ,
137
+ Err ( error) => Err ( error) ,
138
+ }
139
+ }
140
+
130
141
/// Creates Dictionary from a string
131
142
pub fn from_str ( dictionary_str : & str ) -> Result < Dictionary , RadiusError > {
132
- todo ! ( )
143
+ let lines = read_str ( dictionary_str) ;
144
+ Dictionary :: from_lines ( lines)
133
145
}
134
146
135
147
/// Creates Dictionary from a RADIUS dictionary file
136
148
pub fn from_file ( file_path : & str ) -> Result < Dictionary , RadiusError > {
137
- let mut attributes: Vec < DictionaryAttribute > = Vec :: new ( ) ;
138
- let mut values: Vec < DictionaryValue > = Vec :: new ( ) ;
139
- let mut vendors: Vec < DictionaryVendor > = Vec :: new ( ) ;
140
-
141
- match parse_file ( file_path, & mut attributes, & mut values, & mut vendors) {
142
- Ok ( ( ) ) => Ok ( Dictionary { attributes, values, vendors } ) ,
149
+ match read_file ( file_path) {
150
+ Ok ( lines) => Dictionary :: from_lines ( lines) ,
143
151
Err ( error) => Err ( error)
144
152
}
145
153
}
146
154
155
+ /// The add functions process attributes, values and vendors from a supplied dictionary file
156
+ /// and merge them into an existing set of attributes, values and vendors
157
+
158
+ /// Adds a dictionary string to existing Dictionary
159
+ pub fn add_str ( & mut self , dictionary_str : & str ) -> Result < ( ) , RadiusError > {
160
+ let lines = read_str ( dictionary_str) ;
161
+ parse_lines ( lines, & mut self . attributes , & mut self . values , & mut self . vendors )
162
+ }
163
+
147
164
/// 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
165
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 )
166
+ match read_file ( file_path) {
167
+ Ok ( lines) => parse_lines (
168
+ lines, & mut self . attributes , & mut self . values , & mut self . vendors
169
+ ) ,
170
+ Err ( error) => Err ( error)
171
+ }
153
172
}
154
173
155
174
/// Returns parsed DictionaryAttributes
@@ -191,14 +210,29 @@ fn assign_attribute_type(code_type: &str) -> Option<SupportedAttributeTypes> {
191
210
}
192
211
}
193
212
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 ( ) ;
213
+ type StringIterator = Box < dyn Iterator < Item = String > > ;
214
+
215
+ fn filter_lines < T : Iterator < Item = String > + ' static > ( lines : T ) -> StringIterator {
216
+ Box :: new (
217
+ lines
218
+ . filter ( |line| !line. is_empty ( ) )
219
+ . filter ( |line| !line. contains ( & COMMENT_PREFIX ) )
220
+ )
221
+ }
196
222
223
+ fn read_file ( file_path : & str ) -> Result < StringIterator , RadiusError > {
197
224
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 ) ) ;
225
+ Ok ( filter_lines ( reader. lines ( ) . filter_map ( Result :: ok) ) )
226
+ }
227
+
228
+ fn read_str ( dictionary_str : & str ) -> StringIterator {
229
+ let lines: Vec < String > = dictionary_str. to_string ( ) . lines ( )
230
+ . map ( |line| line. to_owned ( ) ) . collect ( ) ;
231
+ filter_lines ( lines. into_iter ( ) )
232
+ }
233
+
234
+ fn parse_lines ( lines : StringIterator , attributes : & mut Vec < DictionaryAttribute > , values : & mut Vec < DictionaryValue > , vendors : & mut Vec < DictionaryVendor > ) -> Result < ( ) , RadiusError > {
235
+ let mut vendor_name: String = String :: new ( ) ;
202
236
203
237
for line in lines {
204
238
let parsed_line: Vec < & str > = line. split_whitespace ( ) . filter ( |& item| !item. is_empty ( ) ) . collect ( ) ;
@@ -249,6 +283,116 @@ fn parse_vendor(parsed_line: Vec<&str>, vendors: &mut Vec<DictionaryVendor>) {
249
283
mod tests {
250
284
use super :: * ;
251
285
286
+ #[ test]
287
+ fn test_from_str ( ) {
288
+ let dictionary_str = include_str ! ( "../../dict_examples/test_dictionary_dict" ) ;
289
+
290
+ let dict = Dictionary :: from_str ( dictionary_str) . unwrap ( ) ;
291
+
292
+ let mut attributes: Vec < DictionaryAttribute > = Vec :: new ( ) ;
293
+ attributes. push ( DictionaryAttribute {
294
+ name : "User-Name" . to_string ( ) ,
295
+ vendor_name : "" . to_string ( ) ,
296
+ code : 1 ,
297
+ code_type : Some ( SupportedAttributeTypes :: AsciiString )
298
+ } ) ;
299
+ attributes. push ( DictionaryAttribute {
300
+ name : "NAS-IP-Address" . to_string ( ) ,
301
+ vendor_name : "" . to_string ( ) ,
302
+ code : 4 ,
303
+ code_type : Some ( SupportedAttributeTypes :: IPv4Addr )
304
+ } ) ;
305
+ attributes. push ( DictionaryAttribute {
306
+ name : "NAS-Port-Id" . to_string ( ) ,
307
+ vendor_name : "" . to_string ( ) ,
308
+ code : 5 ,
309
+ code_type : Some ( SupportedAttributeTypes :: Integer )
310
+ } ) ;
311
+ attributes. push ( DictionaryAttribute {
312
+ name : "Framed-Protocol" . to_string ( ) ,
313
+ vendor_name : "" . to_string ( ) ,
314
+ code : 7 ,
315
+ code_type : Some ( SupportedAttributeTypes :: Integer )
316
+ } ) ;
317
+ attributes. push ( DictionaryAttribute {
318
+ name : "Chargeable-User-Identity" . to_string ( ) ,
319
+ vendor_name : "" . to_string ( ) ,
320
+ code : 89 ,
321
+ code_type : Some ( SupportedAttributeTypes :: ByteString )
322
+ } ) ;
323
+ attributes. push ( DictionaryAttribute {
324
+ name : "Delegated-IPv6-Prefix" . to_string ( ) ,
325
+ vendor_name : "" . to_string ( ) ,
326
+ code : 123 ,
327
+ code_type : Some ( SupportedAttributeTypes :: IPv6Prefix )
328
+ } ) ;
329
+ attributes. push ( DictionaryAttribute {
330
+ name : "MIP6-Feature-Vector" . to_string ( ) ,
331
+ vendor_name : "" . to_string ( ) ,
332
+ code : 124 ,
333
+ code_type : Some ( SupportedAttributeTypes :: Integer64 )
334
+ } ) ;
335
+ attributes. push ( DictionaryAttribute {
336
+ name : "Mobile-Node-Identifier" . to_string ( ) ,
337
+ vendor_name : "" . to_string ( ) ,
338
+ code : 145 ,
339
+ code_type : Some ( SupportedAttributeTypes :: ByteString )
340
+ } ) ;
341
+ attributes. push ( DictionaryAttribute {
342
+ name : "PMIP6-Home-Interface-ID" . to_string ( ) ,
343
+ vendor_name : "" . to_string ( ) ,
344
+ code : 153 ,
345
+ code_type : Some ( SupportedAttributeTypes :: InterfaceId )
346
+ } ) ;
347
+ attributes. push ( DictionaryAttribute {
348
+ name : "PMIP6-Home-IPv4-HoA" . to_string ( ) ,
349
+ vendor_name : "" . to_string ( ) ,
350
+ code : 155 ,
351
+ code_type : Some ( SupportedAttributeTypes :: IPv4Prefix )
352
+ } ) ;
353
+ attributes. push ( DictionaryAttribute {
354
+ name : "Somevendor-Name" . to_string ( ) ,
355
+ vendor_name : "Somevendor" . to_string ( ) ,
356
+ code : 1 ,
357
+ code_type : Some ( SupportedAttributeTypes :: AsciiString )
358
+ } ) ;
359
+ attributes. push ( DictionaryAttribute {
360
+ name : "Somevendor-Number" . to_string ( ) ,
361
+ vendor_name : "Somevendor" . to_string ( ) ,
362
+ code : 2 ,
363
+ code_type : Some ( SupportedAttributeTypes :: Integer )
364
+ } ) ;
365
+ attributes. push ( DictionaryAttribute {
366
+ name : "Class" . to_string ( ) ,
367
+ vendor_name : "" . to_string ( ) ,
368
+ code : 25 ,
369
+ code_type : Some ( SupportedAttributeTypes :: ByteString )
370
+ } ) ;
371
+
372
+ let mut values: Vec < DictionaryValue > = Vec :: new ( ) ;
373
+ values. push ( DictionaryValue {
374
+ attribute_name : "Framed-Protocol" . to_string ( ) ,
375
+ value_name : "PPP" . to_string ( ) ,
376
+ vendor_name : "" . to_string ( ) ,
377
+ value : "1" . to_string ( )
378
+ } ) ;
379
+ values. push ( DictionaryValue {
380
+ attribute_name : "Somevendor-Number" . to_string ( ) ,
381
+ value_name : "Two" . to_string ( ) ,
382
+ vendor_name : "Somevendor" . to_string ( ) ,
383
+ value : "2" . to_string ( )
384
+ } ) ;
385
+
386
+ let mut vendors: Vec < DictionaryVendor > = Vec :: new ( ) ;
387
+ vendors. push ( DictionaryVendor {
388
+ name : "Somevendor" . to_string ( ) ,
389
+ id : 10 ,
390
+ } ) ;
391
+
392
+ let expected_dict = Dictionary { attributes, values, vendors } ;
393
+ assert_eq ! ( dict, expected_dict)
394
+ }
395
+
252
396
#[ test]
253
397
fn test_from_file ( ) {
254
398
let dictionary_path = "./dict_examples/test_dictionary_dict" ;
@@ -359,6 +503,118 @@ mod tests {
359
503
assert_eq ! ( dict, expected_dict)
360
504
}
361
505
506
+ #[ test]
507
+ fn test_add_str ( ) {
508
+ let empty_dictionary_str = include_str ! ( "../../dict_examples/empty_test_dictionary_dict" ) ;
509
+ let dictionary_str = include_str ! ( "../../dict_examples/test_dictionary_dict" ) ;
510
+
511
+ let mut dict = Dictionary :: from_str ( empty_dictionary_str) . unwrap ( ) ;
512
+ dict. add_str ( dictionary_str) . unwrap ( ) ;
513
+
514
+ let mut attributes: Vec < DictionaryAttribute > = Vec :: new ( ) ;
515
+ attributes. push ( DictionaryAttribute {
516
+ name : "User-Name" . to_string ( ) ,
517
+ vendor_name : "" . to_string ( ) ,
518
+ code : 1 ,
519
+ code_type : Some ( SupportedAttributeTypes :: AsciiString )
520
+ } ) ;
521
+ attributes. push ( DictionaryAttribute {
522
+ name : "NAS-IP-Address" . to_string ( ) ,
523
+ vendor_name : "" . to_string ( ) ,
524
+ code : 4 ,
525
+ code_type : Some ( SupportedAttributeTypes :: IPv4Addr )
526
+ } ) ;
527
+ attributes. push ( DictionaryAttribute {
528
+ name : "NAS-Port-Id" . to_string ( ) ,
529
+ vendor_name : "" . to_string ( ) ,
530
+ code : 5 ,
531
+ code_type : Some ( SupportedAttributeTypes :: Integer )
532
+ } ) ;
533
+ attributes. push ( DictionaryAttribute {
534
+ name : "Framed-Protocol" . to_string ( ) ,
535
+ vendor_name : "" . to_string ( ) ,
536
+ code : 7 ,
537
+ code_type : Some ( SupportedAttributeTypes :: Integer )
538
+ } ) ;
539
+ attributes. push ( DictionaryAttribute {
540
+ name : "Chargeable-User-Identity" . to_string ( ) ,
541
+ vendor_name : "" . to_string ( ) ,
542
+ code : 89 ,
543
+ code_type : Some ( SupportedAttributeTypes :: ByteString )
544
+ } ) ;
545
+ attributes. push ( DictionaryAttribute {
546
+ name : "Delegated-IPv6-Prefix" . to_string ( ) ,
547
+ vendor_name : "" . to_string ( ) ,
548
+ code : 123 ,
549
+ code_type : Some ( SupportedAttributeTypes :: IPv6Prefix )
550
+ } ) ;
551
+ attributes. push ( DictionaryAttribute {
552
+ name : "MIP6-Feature-Vector" . to_string ( ) ,
553
+ vendor_name : "" . to_string ( ) ,
554
+ code : 124 ,
555
+ code_type : Some ( SupportedAttributeTypes :: Integer64 )
556
+ } ) ;
557
+ attributes. push ( DictionaryAttribute {
558
+ name : "Mobile-Node-Identifier" . to_string ( ) ,
559
+ vendor_name : "" . to_string ( ) ,
560
+ code : 145 ,
561
+ code_type : Some ( SupportedAttributeTypes :: ByteString )
562
+ } ) ;
563
+ attributes. push ( DictionaryAttribute {
564
+ name : "PMIP6-Home-Interface-ID" . to_string ( ) ,
565
+ vendor_name : "" . to_string ( ) ,
566
+ code : 153 ,
567
+ code_type : Some ( SupportedAttributeTypes :: InterfaceId )
568
+ } ) ;
569
+ attributes. push ( DictionaryAttribute {
570
+ name : "PMIP6-Home-IPv4-HoA" . to_string ( ) ,
571
+ vendor_name : "" . to_string ( ) ,
572
+ code : 155 ,
573
+ code_type : Some ( SupportedAttributeTypes :: IPv4Prefix )
574
+ } ) ;
575
+ attributes. push ( DictionaryAttribute {
576
+ name : "Somevendor-Name" . to_string ( ) ,
577
+ vendor_name : "Somevendor" . to_string ( ) ,
578
+ code : 1 ,
579
+ code_type : Some ( SupportedAttributeTypes :: AsciiString )
580
+ } ) ;
581
+ attributes. push ( DictionaryAttribute {
582
+ name : "Somevendor-Number" . to_string ( ) ,
583
+ vendor_name : "Somevendor" . to_string ( ) ,
584
+ code : 2 ,
585
+ code_type : Some ( SupportedAttributeTypes :: Integer )
586
+ } ) ;
587
+ attributes. push ( DictionaryAttribute {
588
+ name : "Class" . to_string ( ) ,
589
+ vendor_name : "" . to_string ( ) ,
590
+ code : 25 ,
591
+ code_type : Some ( SupportedAttributeTypes :: ByteString )
592
+ } ) ;
593
+
594
+ let mut values: Vec < DictionaryValue > = Vec :: new ( ) ;
595
+ values. push ( DictionaryValue {
596
+ attribute_name : "Framed-Protocol" . to_string ( ) ,
597
+ value_name : "PPP" . to_string ( ) ,
598
+ vendor_name : "" . to_string ( ) ,
599
+ value : "1" . to_string ( )
600
+ } ) ;
601
+ values. push ( DictionaryValue {
602
+ attribute_name : "Somevendor-Number" . to_string ( ) ,
603
+ value_name : "Two" . to_string ( ) ,
604
+ vendor_name : "Somevendor" . to_string ( ) ,
605
+ value : "2" . to_string ( )
606
+ } ) ;
607
+
608
+ let mut vendors: Vec < DictionaryVendor > = Vec :: new ( ) ;
609
+ vendors. push ( DictionaryVendor {
610
+ name : "Somevendor" . to_string ( ) ,
611
+ id : 10 ,
612
+ } ) ;
613
+
614
+ let expected_dict = Dictionary { attributes, values, vendors } ;
615
+ assert_eq ! ( dict, expected_dict)
616
+ }
617
+
362
618
#[ test]
363
619
fn test_add_file ( ) {
364
620
let empty_dictionary_path = "./dict_examples/empty_test_dictionary_dict" ;
0 commit comments