@@ -343,6 +343,32 @@ impl NetworkState {
343343 Ok ( ( ) )
344344 }
345345
346+ pub fn add_access_point ( & mut self , ap : AccessPoint ) -> Result < ( ) , NetworkStateError > {
347+ if let Some ( position) = self
348+ . access_points
349+ . iter ( )
350+ . position ( |a| a. hw_address == ap. hw_address )
351+ {
352+ self . access_points . remove ( position) ;
353+ }
354+ self . access_points . push ( ap) ;
355+
356+ Ok ( ( ) )
357+ }
358+
359+ pub fn remove_access_point ( & mut self , hw_address : & str ) -> Result < ( ) , NetworkStateError > {
360+ let Some ( position) = self
361+ . access_points
362+ . iter ( )
363+ . position ( |a| a. hw_address == hw_address)
364+ else {
365+ return Err ( NetworkStateError :: UnknownAccessPoint ( hw_address. to_string ( ) ) ) ;
366+ } ;
367+
368+ self . access_points . remove ( position) ;
369+ Ok ( ( ) )
370+ }
371+
346372 /// Sets a controller's ports.
347373 ///
348374 /// If the connection is not a controller, returns an error.
@@ -460,6 +486,57 @@ mod tests {
460486 assert ! ( matches!( error, NetworkStateError :: UnknownConnection ( _) ) ) ;
461487 }
462488
489+ #[ test]
490+ fn test_remove_device ( ) {
491+ let mut state = NetworkState :: default ( ) ;
492+ let device = Device {
493+ name : "eth0" . to_string ( ) ,
494+ ..Default :: default ( )
495+ } ;
496+ state. add_device ( device) . unwrap ( ) ;
497+ state. remove_device ( "eth0" ) . unwrap ( ) ;
498+ assert ! ( state. get_device( "eth0" ) . is_none( ) ) ;
499+ }
500+
501+ #[ test]
502+ fn test_add_access_point ( ) {
503+ let mut state = NetworkState :: default ( ) ;
504+ let ap = AccessPoint {
505+ hw_address : "AA:BB:CC:DD:EE:FF" . to_string ( ) ,
506+ ssid : SSID ( b"test" . to_vec ( ) ) ,
507+ ..Default :: default ( )
508+ } ;
509+ state. add_access_point ( ap. clone ( ) ) . unwrap ( ) ;
510+ assert_eq ! ( state. access_points. len( ) , 1 ) ;
511+ assert_eq ! ( state. access_points[ 0 ] . hw_address, "AA:BB:CC:DD:EE:FF" ) ;
512+
513+ // Adding same AP should replace it (in our implementation we remove and push)
514+ let mut ap2 = ap. clone ( ) ;
515+ ap2. strength = 80 ;
516+ state. add_access_point ( ap2) . unwrap ( ) ;
517+ assert_eq ! ( state. access_points. len( ) , 1 ) ;
518+ assert_eq ! ( state. access_points[ 0 ] . strength, 80 ) ;
519+ }
520+
521+ #[ test]
522+ fn test_remove_access_point ( ) {
523+ let mut state = NetworkState :: default ( ) ;
524+ let ap = AccessPoint {
525+ hw_address : "AA:BB:CC:DD:EE:FF" . to_string ( ) ,
526+ ..Default :: default ( )
527+ } ;
528+ state. add_access_point ( ap) . unwrap ( ) ;
529+ state. remove_access_point ( "AA:BB:CC:DD:EE:FF" ) . unwrap ( ) ;
530+ assert_eq ! ( state. access_points. len( ) , 0 ) ;
531+ }
532+
533+ #[ test]
534+ fn test_remove_unknown_access_point ( ) {
535+ let mut state = NetworkState :: default ( ) ;
536+ let error = state. remove_access_point ( "unknown" ) . unwrap_err ( ) ;
537+ assert ! ( matches!( error, NetworkStateError :: UnknownAccessPoint ( _) ) ) ;
538+ }
539+
463540 #[ test]
464541 fn test_is_loopback ( ) {
465542 let conn = Connection :: new ( "eth0" . to_string ( ) , DeviceType :: Ethernet ) ;
@@ -1740,6 +1817,10 @@ pub enum NetworkChange {
17401817 id : String ,
17411818 state : ConnectionState ,
17421819 } ,
1820+ /// A new access point has been added.
1821+ AccessPointAdded ( AccessPoint ) ,
1822+ /// An access point has been removed.
1823+ AccessPointRemoved ( String ) ,
17431824}
17441825
17451826#[ derive( Default , Debug , PartialEq , Clone , Deserialize , Serialize , utoipa:: ToSchema ) ]
0 commit comments