@@ -355,10 +355,9 @@ 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
+ // get_slices() ensures that if no error happens, the cumulative length of all slices
359
+ // equal `len`.
360
+ self . get_slices ( base, len) . all ( |r| r. is_ok ( ) )
362
361
}
363
362
364
363
/// Returns the address plus the offset if it is present within the memory of the guest.
@@ -376,6 +375,10 @@ pub trait GuestMemory {
376
375
/// - the error code returned by the callback 'f'
377
376
/// - the size of the already handled data when encountering the first hole
378
377
/// - the size of the already handled data when the whole range has been handled
378
+ #[ deprecated(
379
+ since = "0.17.0" ,
380
+ note = "supplemented by external iterator `get_slices()`"
381
+ ) ]
379
382
fn try_access < F > ( & self , count : usize , addr : GuestAddress , mut f : F ) -> Result < usize >
380
383
where
381
384
F : FnMut ( usize , usize , MemoryRegionAddress , & Self :: R ) -> Result < usize > ,
@@ -533,6 +536,17 @@ impl<'a, M: GuestMemory + ?Sized> GuestMemorySliceIterator<'a, M> {
533
536
)
534
537
} ) )
535
538
}
539
+
540
+ /// Adapts this [`GuestMemorySliceIterator`] to return `None` (e.g. gracefully terminate)
541
+ /// when it encounters an error after successfully producing at least one slice.
542
+ /// Return an error if requesting the first slice returns an error.
543
+ pub fn stop_on_error ( self ) -> Result < impl Iterator < Item = VolatileSlice < ' a , MS < ' a , M > > > > {
544
+ let mut peek = self . peekable ( ) ;
545
+ if let Some ( err) = peek. next_if ( Result :: is_err) {
546
+ return Err ( err. unwrap_err ( ) ) ;
547
+ }
548
+ Ok ( peek. filter_map ( Result :: ok) )
549
+ }
536
550
}
537
551
538
552
impl < ' a , M : GuestMemory + ?Sized > Iterator for GuestMemorySliceIterator < ' a , M > {
@@ -562,23 +576,15 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
562
576
type E = Error ;
563
577
564
578
fn write ( & self , buf : & [ u8 ] , addr : GuestAddress ) -> Result < usize > {
565
- self . try_access (
566
- buf. len ( ) ,
567
- addr,
568
- |offset, count, caddr, region| -> Result < usize > {
569
- region. write ( & buf[ offset..( offset + count) ] , caddr)
570
- } ,
571
- )
579
+ self . get_slices ( addr, buf. len ( ) )
580
+ . stop_on_error ( ) ?
581
+ . try_fold ( 0 , |acc, slice| Ok ( acc + slice. write ( & buf[ acc..] , 0 ) ?) )
572
582
}
573
583
574
584
fn read ( & self , buf : & mut [ u8 ] , addr : GuestAddress ) -> Result < usize > {
575
- self . try_access (
576
- buf. len ( ) ,
577
- addr,
578
- |offset, count, caddr, region| -> Result < usize > {
579
- region. read ( & mut buf[ offset..( offset + count) ] , caddr)
580
- } ,
581
- )
585
+ self . get_slices ( addr, buf. len ( ) )
586
+ . stop_on_error ( ) ?
587
+ . try_fold ( 0 , |acc, slice| Ok ( acc + slice. read ( & mut buf[ acc..] , 0 ) ?) )
582
588
}
583
589
584
590
/// # Examples
@@ -642,9 +648,11 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
642
648
where
643
649
F : ReadVolatile ,
644
650
{
645
- self . try_access ( count, addr, |_, len, caddr, region| -> Result < usize > {
646
- region. read_volatile_from ( caddr, src, len)
647
- } )
651
+ self . get_slices ( addr, count)
652
+ . stop_on_error ( ) ?
653
+ . try_fold ( 0 , |acc, slice| {
654
+ Ok ( acc + slice. read_volatile_from ( 0 , src, slice. len ( ) ) ?)
655
+ } )
648
656
}
649
657
650
658
fn read_exact_volatile_from < F > (
@@ -670,11 +678,14 @@ impl<T: GuestMemory + ?Sized> Bytes<GuestAddress> for T {
670
678
where
671
679
F : WriteVolatile ,
672
680
{
673
- self . try_access ( count, addr, |_, len, caddr, region| -> Result < usize > {
674
- // For a non-RAM region, reading could have side effects, so we
675
- // must use write_all().
676
- region. write_all_volatile_to ( caddr, dst, len) . map ( |( ) | len)
677
- } )
681
+ self . get_slices ( addr, count)
682
+ . stop_on_error ( ) ?
683
+ . try_fold ( 0 , |acc, slice| {
684
+ // For a non-RAM region, reading could have side effects, so we
685
+ // must use write_all().
686
+ slice. write_all_volatile_to ( 0 , dst, slice. len ( ) ) ?;
687
+ Ok ( acc + slice. len ( ) )
688
+ } )
678
689
}
679
690
680
691
fn write_all_volatile_to < F > ( & self , addr : GuestAddress , dst : & mut F , count : usize ) -> Result < ( ) >
0 commit comments