diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a6a4870..9171fc6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog ## [Unreleased] +### Added + +- [[192]](https://github.com/rust-vmm/vm-memory/pull/192): Add new method + as_any() to GuestAddressSpace + ## [v0.8.0] ### Fixed diff --git a/src/atomic.rs b/src/atomic.rs index bb5693b4..36b087d0 100644 --- a/src/atomic.rs +++ b/src/atomic.rs @@ -12,6 +12,7 @@ extern crate arc_swap; use arc_swap::{ArcSwap, Guard}; +use std::any::Any; use std::ops::Deref; use std::sync::{Arc, LockResult, Mutex, MutexGuard, PoisonError}; @@ -75,13 +76,17 @@ impl GuestMemoryAtomic { } } -impl GuestAddressSpace for GuestMemoryAtomic { - type T = GuestMemoryLoadGuard; +impl GuestAddressSpace for GuestMemoryAtomic { type M = M; + type T = GuestMemoryLoadGuard; fn memory(&self) -> Self::T { GuestMemoryLoadGuard { guard: self.load() } } + + fn as_any(&self) -> &dyn Any { + self + } } /// A guard that provides temporary access to a `GuestMemoryAtomic`. This @@ -148,6 +153,23 @@ mod tests { type GuestRegionMmap = crate::GuestRegionMmap<()>; type GuestMemoryMmapAtomic = GuestMemoryAtomic; + #[test] + fn test_as_any() { + let region_size = 0x400; + let regions = vec![ + (GuestAddress(0x0), region_size), + (GuestAddress(0x1000), region_size), + ]; + let gmm = GuestMemoryMmap::from_ranges(®ions).unwrap(); + let gm = GuestMemoryMmapAtomic::new(gmm); + + assert!(gm + .as_any() + .downcast_ref::() + .is_some()); + assert!(gm.as_any().downcast_ref::().is_none()); + } + #[test] fn test_atomic_memory() { let region_size = 0x400; diff --git a/src/guest_memory.rs b/src/guest_memory.rs index 6bbd02f1..f0e24c19 100644 --- a/src/guest_memory.rs +++ b/src/guest_memory.rs @@ -41,6 +41,7 @@ //! via pointers, references, or slices returned by methods of `GuestMemory`,`GuestMemoryRegion`, //! `VolatileSlice`, `VolatileRef`, or `VolatileArrayRef`. +use std::any::Any; use std::convert::From; use std::fmt::{self, Display}; use std::fs::File; @@ -400,33 +401,48 @@ pub trait GuestAddressSpace { /// to access memory through this address space. The object provides /// a consistent snapshot of the memory map. fn memory(&self) -> Self::T; + + /// Cast `self` to a dynamic trait object of `std::any::Any`. + fn as_any(&self) -> &dyn Any; } -impl GuestAddressSpace for &M { +impl GuestAddressSpace for &M { type M = M; type T = Self; fn memory(&self) -> Self { self } + + fn as_any(&self) -> &dyn Any { + *self + } } -impl GuestAddressSpace for Rc { +impl GuestAddressSpace for Rc { type M = M; type T = Self; fn memory(&self) -> Self { self.clone() } + + fn as_any(&self) -> &dyn Any { + self + } } -impl GuestAddressSpace for Arc { +impl GuestAddressSpace for Arc { type M = M; type T = Self; fn memory(&self) -> Self { self.clone() } + + fn as_any(&self) -> &dyn Any { + self + } } /// Lifetime generic associated iterators. The actual iterator type is defined through associated @@ -1256,4 +1272,14 @@ mod tests { let r = mem.find_region(addr).unwrap(); assert_eq!(r.is_hugetlbfs(), None); } + + #[cfg(feature = "backend-mmap")] + #[test] + fn test_as_any() { + let addr = GuestAddress(0x1000); + let mem = &GuestMemoryMmap::from_ranges(&[(addr, 0x1000)]).unwrap(); + + assert!(mem.as_any().downcast_ref::().is_some()); + assert!(mem.as_any().downcast_ref::().is_none()); + } }