@@ -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:: * ;
@@ -187,13 +185,19 @@ impl FromIterator<Attribute> for WellKnownMandatoryAndOtherAttributes {
187185 }
188186}
189187
188+ impl From < Vec < Attribute > > for WellKnownMandatoryAndOtherAttributes {
189+ fn from ( attributes : Vec < Attribute > ) -> Self {
190+ attributes. into_iter ( ) . collect ( )
191+ }
192+ }
193+
190194impl Attributes {
191195 pub fn has_attr ( & self , ty : AttrType ) -> bool {
192196 match ty {
193197 AttrType :: ORIGIN => self . origin . is_some ( ) ,
194198 AttrType :: AS_PATH => self . as_path . is_some ( ) ,
195199 AttrType :: NEXT_HOP => self . next_hop . is_some ( ) ,
196- _ => self . inner . iter ( ) . any ( |x| x. value . attr_type ( ) == ty)
200+ _ => self . inner . iter ( ) . any ( |x| x. value . attr_type ( ) == ty) ,
197201 }
198202 }
199203
@@ -202,10 +206,11 @@ impl Attributes {
202206 AttrType :: ORIGIN => self . origin . clone ( ) ,
203207 AttrType :: AS_PATH => self . as_path . clone ( ) ,
204208 AttrType :: NEXT_HOP => self . next_hop . clone ( ) ,
205- _ => self . inner
206- . iter ( )
207- . find ( |x| x. value . attr_type ( ) == ty)
208- . cloned ( )
209+ _ => self
210+ . inner
211+ . iter ( )
212+ . find ( |x| x. value . attr_type ( ) == ty)
213+ . cloned ( ) ,
209214 }
210215 }
211216
@@ -236,7 +241,8 @@ impl Attributes {
236241 /// Get the `ORIGIN` attribute. In the event that this attribute is not present,
237242 /// [Origin::INCOMPLETE] will be returned instead.
238243 pub fn origin ( & self ) -> Origin {
239- self . origin . as_ref ( )
244+ self . origin
245+ . as_ref ( )
240246 . and_then ( |x| match & x. value {
241247 AttributeValue :: Origin ( x) => Some ( * x) ,
242248 _ => None ,
@@ -257,12 +263,10 @@ impl Attributes {
257263 /// **Note**: Even when this attribute is not present, the next hop address may still be
258264 /// attainable from the `MP_REACH_NLRI` attribute.
259265 pub fn next_hop ( & self ) -> Option < IpAddr > {
260- self . next_hop
261- . as_ref ( )
262- . and_then ( |x| match & x. value {
263- AttributeValue :: NextHop ( x) => Some ( * x) ,
264- _ => None ,
265- } )
266+ self . next_hop . as_ref ( ) . and_then ( |x| match & x. value {
267+ AttributeValue :: NextHop ( x) => Some ( * x) ,
268+ _ => None ,
269+ } )
266270 }
267271
268272 pub fn multi_exit_discriminator ( & self ) -> Option < u32 > {
@@ -310,12 +314,10 @@ impl Attributes {
310314
311315 // These implementations are horribly inefficient, but they were super easy to write and use
312316 pub fn as_path ( & self ) -> Option < & AsPath > {
313- self . as_path
314- . as_ref ( )
315- . and_then ( |x| match & x. value {
316- AttributeValue :: AsPath { path, .. } => Some ( path) ,
317- _ => None ,
318- } )
317+ self . as_path . as_ref ( ) . and_then ( |x| match & x. value {
318+ AttributeValue :: AsPath { path, .. } => Some ( path) ,
319+ _ => None ,
320+ } )
319321 }
320322
321323 pub fn get_reachable_nlri ( & self ) -> Option < & Nlri > {
@@ -339,12 +341,45 @@ impl Attributes {
339341 }
340342 }
341343
344+ /// Count the total number of attributes (including well-known mandatory attributes)
345+ pub fn len ( & self ) -> usize {
346+ self . origin . iter ( ) . count ( )
347+ + self . as_path . iter ( ) . count ( )
348+ + self . next_hop . iter ( ) . count ( )
349+ + self . inner . len ( )
350+ }
351+
352+ /// Check if there are no attributes
353+ pub fn is_empty ( & self ) -> bool {
354+ self . len ( ) == 0
355+ }
356+
357+ /// Get the first attribute if any exists
358+ pub fn first ( & self ) -> Option < & Attribute > {
359+ self . origin
360+ . as_ref ( )
361+ . or ( self . as_path . as_ref ( ) )
362+ . or ( self . next_hop . as_ref ( ) )
363+ . or ( self . inner . first ( ) )
364+ }
365+
342366 /// Get an iterator over the held [AttributeValue]s. If you also need attribute flags, consider
343367 /// using [Attributes::into_attributes_iter] instead.
344368 pub fn iter ( & self ) -> <& ' _ Self as IntoIterator >:: IntoIter {
345369 self . into_iter ( )
346370 }
347371
372+ /// Get an iterator over references to the held [Attribute]s. If you do not need attribute flags,
373+ /// consider using [Attributes::iter] instead.
374+ pub fn attributes_iter ( & self ) -> impl Iterator < Item = & Attribute > {
375+ chain ! (
376+ self . as_path. iter( ) ,
377+ self . origin. iter( ) ,
378+ self . next_hop. iter( ) ,
379+ self . inner. iter( ) ,
380+ )
381+ }
382+
348383 /// Get an iterator over the held [Attribute]s. If you do no not need attribute flags, consider
349384 /// using [Attributes::iter] instead.
350385 pub fn into_attributes_iter ( self ) -> impl Iterator < Item = Attribute > {
@@ -431,14 +466,13 @@ impl Extend<AttributeValue> for Attributes {
431466
432467impl FromIterator < AttributeValue > for Attributes {
433468 fn from_iter < T : IntoIterator < Item = AttributeValue > > ( iter : T ) -> Self {
434- let attrs = WellKnownMandatoryAndOtherAttributes :: from_iter (
435- iter
436- . into_iter ( )
437- . map ( |value| Attribute {
469+ let attrs =
470+ WellKnownMandatoryAndOtherAttributes :: from_iter ( iter. into_iter ( ) . map ( |value| {
471+ Attribute {
438472 value,
439473 flag : AttrFlags :: empty ( ) ,
440- } )
441- ) ;
474+ }
475+ } ) ) ;
442476
443477 Attributes {
444478 origin : attrs. origin ,
@@ -452,26 +486,35 @@ impl FromIterator<AttributeValue> for Attributes {
452486
453487impl IntoIterator for Attributes {
454488 type Item = AttributeValue ;
455- type IntoIter = Map < IntoIter < Attribute > , fn ( Attribute ) -> AttributeValue > ;
489+ type IntoIter = std :: vec :: IntoIter < AttributeValue > ;
456490
457491 fn into_iter ( self ) -> Self :: IntoIter {
458- self . inner . into_iter ( ) . map ( |x| x. value )
492+ chain ! (
493+ self . as_path. into_iter( ) ,
494+ self . origin. into_iter( ) ,
495+ self . next_hop. into_iter( ) ,
496+ self . inner. into_iter( )
497+ )
498+ . map ( |x| x. value )
499+ . collect :: < Vec < _ > > ( )
500+ . into_iter ( )
459501 }
460502}
461503
462504impl < ' a > IntoIterator for & ' a Attributes {
463505 type Item = & ' a AttributeValue ;
464- type IntoIter = Map < Iter < ' a , Attribute > , fn ( & Attribute ) -> & AttributeValue > ;
506+ type IntoIter = std :: vec :: IntoIter < & ' a AttributeValue > ;
465507
466508 fn into_iter ( self ) -> Self :: IntoIter {
467- let tmp : Vec < _ > = chain ! (
509+ chain ! (
468510 self . as_path. iter( ) ,
469511 self . origin. iter( ) ,
470512 self . next_hop. iter( ) ,
471513 self . inner. iter( )
472- ) . collect ( ) ;
473-
474- tmp. as_slice ( ) . into_iter ( ) . map ( |x| & x. value )
514+ )
515+ . map ( |x| & x. value )
516+ . collect :: < Vec < _ > > ( )
517+ . into_iter ( )
475518 }
476519}
477520
@@ -494,8 +537,14 @@ mod serde_impl {
494537 where
495538 D : Deserializer < ' de > ,
496539 {
540+ let attributes = <Vec < Attribute > >:: deserialize ( deserializer) ?;
541+ let well_known_and_others = WellKnownMandatoryAndOtherAttributes :: from ( attributes) ;
542+
497543 Ok ( Attributes {
498- inner : <Vec < Attribute > >:: deserialize ( deserializer) ?,
544+ inner : well_known_and_others. inner ,
545+ origin : well_known_and_others. origin ,
546+ as_path : well_known_and_others. as_path ,
547+ next_hop : well_known_and_others. next_hop ,
499548 validation_warnings : Vec :: new ( ) ,
500549 } )
501550 }
0 commit comments