mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-07-27 04:13:53 -06:00
rust: qom: introduce ParentInit
This is a smart pointer for MaybeUninit; it can be upcasted to the already-initialized parent classes, or dereferenced to a MaybeUninit for the class that is being initialized. Reviewed-by: Zhao Liu <zhao1.liu@intel.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
eb64a0c6ae
commit
a441222583
1 changed files with 95 additions and 1 deletions
|
@ -95,7 +95,7 @@
|
|||
use std::{
|
||||
ffi::{c_void, CStr},
|
||||
fmt,
|
||||
mem::ManuallyDrop,
|
||||
mem::{ManuallyDrop, MaybeUninit},
|
||||
ops::{Deref, DerefMut},
|
||||
ptr::NonNull,
|
||||
};
|
||||
|
@ -206,6 +206,100 @@ impl<T: fmt::Display + ObjectType> fmt::Display for ParentField<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// This struct knows that the superclasses of the object have already been
|
||||
/// initialized.
|
||||
pub struct ParentInit<'a, T>(&'a mut MaybeUninit<T>);
|
||||
|
||||
impl<'a, T> ParentInit<'a, T> {
|
||||
#[inline]
|
||||
pub fn with(obj: &'a mut MaybeUninit<T>, f: impl FnOnce(ParentInit<'a, T>)) {
|
||||
let parent_init = ParentInit(obj);
|
||||
f(parent_init)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ObjectType> ParentInit<'_, T> {
|
||||
/// Return the receiver as a mutable raw pointer to Object.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Fields beyond `Object` could be uninitialized and it's your
|
||||
/// responsibility to avoid that they're used when the pointer is
|
||||
/// dereferenced, either directly or through a cast.
|
||||
pub fn as_object_mut_ptr(&self) -> *mut bindings::Object {
|
||||
self.as_object_ptr().cast_mut()
|
||||
}
|
||||
|
||||
/// Return the receiver as a mutable raw pointer to Object.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Fields beyond `Object` could be uninitialized and it's your
|
||||
/// responsibility to avoid that they're used when the pointer is
|
||||
/// dereferenced, either directly or through a cast.
|
||||
pub fn as_object_ptr(&self) -> *const bindings::Object {
|
||||
self.0.as_ptr().cast()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ObjectImpl> ParentInit<'a, T> {
|
||||
/// Convert from a derived type to one of its parent types, which
|
||||
/// have already been initialized.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Structurally this is always a safe operation; the [`IsA`] trait
|
||||
/// provides static verification trait that `Self` dereferences to `U` or
|
||||
/// a child of `U`, and only parent types of `T` are allowed.
|
||||
///
|
||||
/// However, while the fields of the resulting reference are initialized,
|
||||
/// calls might use uninitialized fields of the subclass. It is your
|
||||
/// responsibility to avoid this.
|
||||
pub unsafe fn upcast<U: ObjectType>(&self) -> &'a U
|
||||
where
|
||||
T::ParentType: IsA<U>,
|
||||
{
|
||||
// SAFETY: soundness is declared via IsA<U>, which is an unsafe trait;
|
||||
// the parent has been initialized before `instance_init `is called
|
||||
unsafe { &*(self.0.as_ptr().cast::<U>()) }
|
||||
}
|
||||
|
||||
/// Convert from a derived type to one of its parent types, which
|
||||
/// have already been initialized.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Structurally this is always a safe operation; the [`IsA`] trait
|
||||
/// provides static verification trait that `Self` dereferences to `U` or
|
||||
/// a child of `U`, and only parent types of `T` are allowed.
|
||||
///
|
||||
/// However, while the fields of the resulting reference are initialized,
|
||||
/// calls might use uninitialized fields of the subclass. It is your
|
||||
/// responsibility to avoid this.
|
||||
pub unsafe fn upcast_mut<U: ObjectType>(&mut self) -> &'a mut U
|
||||
where
|
||||
T::ParentType: IsA<U>,
|
||||
{
|
||||
// SAFETY: soundness is declared via IsA<U>, which is an unsafe trait;
|
||||
// the parent has been initialized before `instance_init `is called
|
||||
unsafe { &mut *(self.0.as_mut_ptr().cast::<U>()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for ParentInit<'_, T> {
|
||||
type Target = MaybeUninit<T>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DerefMut for ParentInit<'_, T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn rust_instance_init<T: ObjectImpl>(obj: *mut bindings::Object) {
|
||||
let mut state = NonNull::new(obj).unwrap().cast::<T>();
|
||||
// SAFETY: obj is an instance of T, since rust_instance_init<T>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue