@@ -355,10 +355,10 @@ pub trait GuestMemory {
355
355
356
356
/// Check whether the range [base, base + len) is valid.
357
357
fn check_range ( & self , base : GuestAddress , len : usize ) -> bool {
358
- match self . try_access ( len , base, |_ , count , _ , _| -> Result < usize > { Ok ( count ) } ) {
359
- Ok ( count ) => count == len,
360
- _ => false ,
361
- }
358
+ self . get_slices ( base, len )
359
+ . map ( |r| r . map ( |slice| slice . len ( ) ) . unwrap_or ( 0 ) )
360
+ . sum :: < usize > ( )
361
+ == len
362
362
}
363
363
364
364
/// Returns the address plus the offset if it is present within the memory of the guest.
@@ -376,6 +376,10 @@ pub trait GuestMemory {
376
376
/// - the error code returned by the callback 'f'
377
377
/// - the size of the already handled data when encountering the first hole
378
378
/// - the size of the already handled data when the whole range has been handled
379
+ #[ deprecated(
380
+ since = "0.17.0" ,
381
+ note = "supplemented by external iterator `get_slices()`"
382
+ ) ]
379
383
fn try_access < F > ( & self , count : usize , addr : GuestAddress , mut f : F ) -> Result < usize >
380
384
where
381
385
F : FnMut ( usize , usize , MemoryRegionAddress , & Self :: R ) -> Result < usize > ,
@@ -527,6 +531,14 @@ impl<'a, M: GuestMemory + ?Sized> GuestMemorySliceIterator<'a, M> {
527
531
528
532
Some ( region. get_slice ( start, len as usize ) )
529
533
}
534
+
535
+ /// Adapts this [`GuestMemorySliceIterator`] to return `None` (e.g. gracefully terminate)
536
+ /// instead of `Err(Error::InvalidGuestAddress)` when iteration hits an invalid [`GuestAddress`].
537
+ pub fn partial ( self ) -> impl Iterator < Item = Result < VolatileSlice < ' a , MS < ' a , M > > > > {
538
+ self . enumerate ( )
539
+ . filter ( |( i, r) | !( * i > 0 && matches ! ( r, Err ( Error :: InvalidGuestAddress ( _) ) ) ) )
540
+ . map ( |( _, r) | r)
541
+ }
530
542
}
531
543
532
544
impl < ' a , M : GuestMemory + ?Sized > Iterator for GuestMemorySliceIterator < ' a , M > {
@@ -556,23 +568,15 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
556
568
type E = Error ;
557
569
558
570
fn write ( & self , buf : & [ u8 ] , addr : GuestAddress ) -> Result < usize > {
559
- self . try_access (
560
- buf. len ( ) ,
561
- addr,
562
- |offset, count, caddr, region| -> Result < usize > {
563
- region. write ( & buf[ offset..( offset + count) ] , caddr)
564
- } ,
565
- )
571
+ self . get_slices ( addr, buf. len ( ) )
572
+ . partial ( )
573
+ . try_fold ( 0 , |acc, slice| Ok ( acc + slice?. write ( & buf[ acc..] , 0 ) ?) )
566
574
}
567
575
568
576
fn read ( & self , buf : & mut [ u8 ] , addr : GuestAddress ) -> Result < usize > {
569
- self . try_access (
570
- buf. len ( ) ,
571
- addr,
572
- |offset, count, caddr, region| -> Result < usize > {
573
- region. read ( & mut buf[ offset..( offset + count) ] , caddr)
574
- } ,
575
- )
577
+ self . get_slices ( addr, buf. len ( ) )
578
+ . partial ( )
579
+ . try_fold ( 0 , |acc, slice| Ok ( acc + slice?. read ( & mut buf[ acc..] , 0 ) ?) )
576
580
}
577
581
578
582
/// # Examples
@@ -636,9 +640,12 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
636
640
where
637
641
F : ReadVolatile ,
638
642
{
639
- self . try_access ( count, addr, |_, len, caddr, region| -> Result < usize > {
640
- region. read_volatile_from ( caddr, src, len)
641
- } )
643
+ self . get_slices ( addr, count)
644
+ . partial ( )
645
+ . try_fold ( 0 , |acc, r| {
646
+ let slice = r?;
647
+ Ok ( acc + slice. read_volatile_from ( 0 , src, slice. len ( ) ) ?)
648
+ } )
642
649
}
643
650
644
651
fn read_exact_volatile_from < F > (
@@ -664,11 +671,15 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
664
671
where
665
672
F : WriteVolatile ,
666
673
{
667
- self . try_access ( count, addr, |_, len, caddr, region| -> Result < usize > {
668
- // For a non-RAM region, reading could have side effects, so we
669
- // must use write_all().
670
- region. write_all_volatile_to ( caddr, dst, len) . map ( |( ) | len)
671
- } )
674
+ self . get_slices ( addr, count)
675
+ . partial ( )
676
+ . try_fold ( 0 , |acc, r| {
677
+ let slice = r?;
678
+ // For a non-RAM region, reading could have side effects, so we
679
+ // must use write_all().
680
+ slice. write_all_volatile_to ( 0 , dst, slice. len ( ) ) ?;
681
+ Ok ( acc + slice. len ( ) )
682
+ } )
672
683
}
673
684
674
685
fn write_all_volatile_to < F > ( & self , addr : GuestAddress , dst : & mut F , count : usize ) -> Result < ( ) >
0 commit comments