@@ -8,10 +8,8 @@ use bitflags::bitflags;
88use itertools:: chain;
99use num_enum:: { FromPrimitive , IntoPrimitive } ;
1010use std:: cmp:: Ordering ;
11- use std:: iter:: { FromIterator , Map } ;
11+ use std:: iter:: FromIterator ;
1212use std:: net:: IpAddr ;
13- use std:: slice:: Iter ;
14- use std:: vec:: IntoIter ;
1513
1614use crate :: error:: BgpValidationWarning ;
1715use crate :: models:: * ;
@@ -339,12 +337,41 @@ impl Attributes {
339337 }
340338 }
341339
340+ /// Count the total number of attributes (including well-known mandatory attributes)
341+ pub fn len ( & self ) -> usize {
342+ self . origin . iter ( ) . count ( ) + self . as_path . iter ( ) . count ( ) + self . next_hop . iter ( ) . count ( ) + self . inner . len ( )
343+ }
344+
345+ /// Check if there are no attributes
346+ pub fn is_empty ( & self ) -> bool {
347+ self . len ( ) == 0
348+ }
349+
350+ /// Get the first attribute if any exists
351+ pub fn first ( & self ) -> Option < & Attribute > {
352+ self . origin . as_ref ( )
353+ . or ( self . as_path . as_ref ( ) )
354+ . or ( self . next_hop . as_ref ( ) )
355+ . or ( self . inner . first ( ) )
356+ }
357+
342358 /// Get an iterator over the held [AttributeValue]s. If you also need attribute flags, consider
343359 /// using [Attributes::into_attributes_iter] instead.
344360 pub fn iter ( & self ) -> <& ' _ Self as IntoIterator >:: IntoIter {
345361 self . into_iter ( )
346362 }
347363
364+ /// Get an iterator over references to the held [Attribute]s. If you do not need attribute flags,
365+ /// consider using [Attributes::iter] instead.
366+ pub fn attributes_iter ( & self ) -> impl Iterator < Item = & Attribute > {
367+ chain ! (
368+ self . as_path. iter( ) ,
369+ self . origin. iter( ) ,
370+ self . next_hop. iter( ) ,
371+ self . inner. iter( ) ,
372+ )
373+ }
374+
348375 /// Get an iterator over the held [Attribute]s. If you do no not need attribute flags, consider
349376 /// using [Attributes::iter] instead.
350377 pub fn into_attributes_iter ( self ) -> impl Iterator < Item = Attribute > {
@@ -452,26 +479,35 @@ impl FromIterator<AttributeValue> for Attributes {
452479
453480impl IntoIterator for Attributes {
454481 type Item = AttributeValue ;
455- type IntoIter = Map < IntoIter < Attribute > , fn ( Attribute ) -> AttributeValue > ;
482+ type IntoIter = std :: vec :: IntoIter < AttributeValue > ;
456483
457484 fn into_iter ( self ) -> Self :: IntoIter {
458- self . inner . into_iter ( ) . map ( |x| x. value )
485+ chain ! (
486+ self . as_path. into_iter( ) ,
487+ self . origin. into_iter( ) ,
488+ self . next_hop. into_iter( ) ,
489+ self . inner. into_iter( )
490+ )
491+ . map ( |x| x. value )
492+ . collect :: < Vec < _ > > ( )
493+ . into_iter ( )
459494 }
460495}
461496
462497impl < ' a > IntoIterator for & ' a Attributes {
463498 type Item = & ' a AttributeValue ;
464- type IntoIter = Map < Iter < ' a , Attribute > , fn ( & Attribute ) -> & AttributeValue > ;
499+ type IntoIter = std :: vec :: IntoIter < & ' a AttributeValue > ;
465500
466501 fn into_iter ( self ) -> Self :: IntoIter {
467- let tmp : Vec < _ > = chain ! (
502+ chain ! (
468503 self . as_path. iter( ) ,
469504 self . origin. iter( ) ,
470505 self . next_hop. iter( ) ,
471506 self . inner. iter( )
472- ) . collect ( ) ;
473-
474- tmp. as_slice ( ) . into_iter ( ) . map ( |x| & x. value )
507+ )
508+ . map ( |x| & x. value )
509+ . collect :: < Vec < _ > > ( )
510+ . into_iter ( )
475511 }
476512}
477513
0 commit comments