@@ -394,6 +394,25 @@ impl<M: GuestMemory> GuestAddressSpace for Arc<M> {
394
394
}
395
395
}
396
396
397
+ /// Lifetime generic associated iterators. The actual iterator type is defined through associated
398
+ /// item `Iter`, for example:
399
+ ///
400
+ /// ```ignore
401
+ /// impl<'a> GuestMemoryIterator<'a, MyGuestRegion> for MyGuestMemory {
402
+ /// type Iter = MyGuestMemoryIter<'a>;
403
+ /// }
404
+ ///
405
+ /// pub struct MyGuestMemoryIter<`a>( /* ... */ );
406
+ /// impl<'a> Iterator for MyGuestMemoryIter<'a> {
407
+ /// type Item = &'a MyGuestRegion;
408
+ /// /* ... */
409
+ /// }
410
+ /// ```
411
+ pub trait GuestMemoryIterator < ' a , R : ' a > {
412
+ /// Type of the `iter` method's return value.
413
+ type Iter : Iterator < Item = & ' a R > ;
414
+ }
415
+
397
416
/// `GuestMemory` represents a container for an *immutable* collection of
398
417
/// `GuestMemoryRegion` objects. `GuestMemory` provides the `Bytes<GuestAddress>`
399
418
/// trait to hide the details of accessing guest memory by physical address.
@@ -407,6 +426,9 @@ pub trait GuestMemory {
407
426
/// Type of objects hosted by the address space.
408
427
type R : GuestMemoryRegion ;
409
428
429
+ /// Lifetime generic associated iterators. Usually this is just `Self`.
430
+ type I : for < ' a > GuestMemoryIterator < ' a , Self :: R > ;
431
+
410
432
/// Returns the number of regions in the collection.
411
433
fn num_regions ( & self ) -> usize ;
412
434
@@ -418,14 +440,55 @@ pub trait GuestMemory {
418
440
/// It only walks children of current region and does not step into sub regions.
419
441
fn with_regions < F , E > ( & self , cb : F ) -> std:: result:: Result < ( ) , E >
420
442
where
421
- F : Fn ( usize , & Self :: R ) -> std:: result:: Result < ( ) , E > ;
443
+ F : Fn ( usize , & Self :: R ) -> std:: result:: Result < ( ) , E > ,
444
+ {
445
+ for ( index, region) in self . iter ( ) . enumerate ( ) {
446
+ cb ( index, region) ?;
447
+ }
448
+ Ok ( ( ) )
449
+ }
422
450
423
451
/// Perform the specified action on each region mutably.
424
452
///
425
453
/// It only walks children of current region and does not step into sub regions.
426
- fn with_regions_mut < F , E > ( & self , cb : F ) -> std:: result:: Result < ( ) , E >
454
+ fn with_regions_mut < F , E > ( & self , mut cb : F ) -> std:: result:: Result < ( ) , E >
427
455
where
428
- F : FnMut ( usize , & Self :: R ) -> std:: result:: Result < ( ) , E > ;
456
+ F : FnMut ( usize , & Self :: R ) -> std:: result:: Result < ( ) , E > ,
457
+ {
458
+ for ( index, region) in self . iter ( ) . enumerate ( ) {
459
+ cb ( index, region) ?;
460
+ }
461
+ Ok ( ( ) )
462
+ }
463
+
464
+ /// Gets an iterator over the entries in the collection.
465
+ ///
466
+ /// # Examples
467
+ ///
468
+ /// * Compute the total size of all memory mappings in KB by iterating over the memory regions
469
+ /// and dividing their sizes to 1024, then summing up the values in an accumulator.
470
+ ///
471
+ /// ```
472
+ /// # #[cfg(feature = "backend-mmap")]
473
+ /// # use vm_memory::{GuestAddress, GuestMemory, GuestMemoryRegion, GuestMemoryMmap};
474
+ ///
475
+ /// # #[cfg(feature = "backend-mmap")]
476
+ /// # fn test_map_fold() -> Result<(), ()> {
477
+ /// let start_addr1 = GuestAddress(0x0);
478
+ /// let start_addr2 = GuestAddress(0x400);
479
+ /// let mem = GuestMemoryMmap::from_ranges(&vec![(start_addr1, 1024), (start_addr2, 2048)])
480
+ /// .unwrap();
481
+ /// let total_size = mem.iter()
482
+ /// .map(|region| region.len() / 1024)
483
+ /// .fold(0, |acc, size| acc + size);
484
+ /// println!("Total memory size = {} KB", total_size);
485
+ /// Ok(())
486
+ /// # }
487
+ ///
488
+ /// # #[cfg(feature = "backend-mmap")]
489
+ /// # test_map_fold();
490
+ /// ```
491
+ fn iter ( & self ) -> <Self :: I as GuestMemoryIterator < Self :: R > >:: Iter ;
429
492
430
493
/// Applies two functions, specified as callbacks, on the inner memory regions.
431
494
///
@@ -468,7 +531,10 @@ pub trait GuestMemory {
468
531
fn map_and_fold < F , G , T > ( & self , init : T , mapf : F , foldf : G ) -> T
469
532
where
470
533
F : Fn ( ( usize , & Self :: R ) ) -> T ,
471
- G : Fn ( T , T ) -> T ;
534
+ G : Fn ( T , T ) -> T ,
535
+ {
536
+ self . iter ( ) . enumerate ( ) . map ( mapf) . fold ( init, foldf)
537
+ }
472
538
473
539
/// Returns the maximum (inclusive) address managed by the
474
540
/// [`GuestMemory`](trait.GuestMemory.html).
@@ -491,11 +557,9 @@ pub trait GuestMemory {
491
557
/// # test_last_addr();
492
558
/// ```
493
559
fn last_addr ( & self ) -> GuestAddress {
494
- self . map_and_fold (
495
- GuestAddress ( 0 ) ,
496
- |( _, region) | region. last_addr ( ) ,
497
- std:: cmp:: max,
498
- )
560
+ self . iter ( )
561
+ . map ( GuestMemoryRegion :: last_addr)
562
+ . fold ( GuestAddress ( 0 ) , std:: cmp:: max)
499
563
}
500
564
501
565
/// Tries to convert an absolute address to a relative address within the corresponding region.
0 commit comments