rust: move class_init to an extension trait

Prepare for having ObjectClass, DeviceClass and SysbusDeviceClass
defined outside the hwcore and qom crates.  It then becomes
impossible to add a method to them.

Extracted from a patch by Marc-André Lureau.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini
2026-01-14 09:46:01 +01:00
parent e079272604
commit f9bbbde1ed
5 changed files with 32 additions and 15 deletions

View File

@@ -1,6 +1,8 @@
//! Essential types and traits intended for blanket imports.
pub use crate::qdev::Clock;
pub use crate::qdev::DeviceClassExt;
pub use crate::qdev::DeviceState;
pub use crate::qdev::DeviceImpl;
pub use crate::qdev::DeviceMethods;
@@ -8,6 +10,7 @@ pub use crate::qdev::ResettablePhasesImpl;
pub use crate::qdev::ResetType;
pub use crate::sysbus::SysBusDevice;
pub use crate::sysbus::SysBusDeviceClassExt;
pub use crate::sysbus::SysBusDeviceImpl;
pub use crate::sysbus::SysBusDeviceMethods;

View File

@@ -15,9 +15,9 @@ use migration::{impl_vmstate_c_struct, VMStateDescription};
use qom::{prelude::*, ObjectClass};
use util::{Error, Result};
pub use crate::bindings::{ClockEvent, DeviceClass, Property, ResetType};
pub use crate::bindings::{ClockEvent, ResetType};
use crate::{
bindings::{self, qdev_init_gpio_in, qdev_init_gpio_out, ResettableClass},
bindings::{self, qdev_init_gpio_in, qdev_init_gpio_out, DeviceClass, Property},
irq::InterruptSource,
};
@@ -206,6 +206,9 @@ unsafe extern "C" fn rust_realize_fn<T: DeviceImpl>(
}
}
#[repr(transparent)]
pub struct ResettableClass(bindings::ResettableClass);
unsafe impl InterfaceType for ResettableClass {
const TYPE_NAME: &'static CStr =
unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_RESETTABLE_INTERFACE) };
@@ -214,23 +217,25 @@ unsafe impl InterfaceType for ResettableClass {
impl ResettableClass {
/// Fill in the virtual methods of `ResettableClass` based on the
/// definitions in the `ResettablePhasesImpl` trait.
pub fn class_init<T: ResettablePhasesImpl>(&mut self) {
fn class_init<T: ResettablePhasesImpl>(&mut self) {
if <T as ResettablePhasesImpl>::ENTER.is_some() {
self.phases.enter = Some(rust_resettable_enter_fn::<T>);
self.0.phases.enter = Some(rust_resettable_enter_fn::<T>);
}
if <T as ResettablePhasesImpl>::HOLD.is_some() {
self.phases.hold = Some(rust_resettable_hold_fn::<T>);
self.0.phases.hold = Some(rust_resettable_hold_fn::<T>);
}
if <T as ResettablePhasesImpl>::EXIT.is_some() {
self.phases.exit = Some(rust_resettable_exit_fn::<T>);
self.0.phases.exit = Some(rust_resettable_exit_fn::<T>);
}
}
}
impl DeviceClass {
/// Fill in the virtual methods of `DeviceClass` based on the definitions in
/// the `DeviceImpl` trait.
pub fn class_init<T: DeviceImpl>(&mut self) {
pub trait DeviceClassExt {
fn class_init<T: DeviceImpl>(&mut self);
}
impl DeviceClassExt for DeviceClass {
fn class_init<T: DeviceImpl>(&mut self) {
if <T as DeviceImpl>::REALIZE.is_some() {
self.realize = Some(rust_realize_fn::<T>);
}

View File

@@ -15,7 +15,7 @@ use util::{Error, Result};
use crate::{
bindings,
irq::{IRQState, InterruptSource},
qdev::{DeviceImpl, DeviceState},
qdev::{DeviceClassExt, DeviceImpl, DeviceState},
};
/// A safe wrapper around [`bindings::SysBusDevice`].
@@ -37,10 +37,14 @@ qom_isa!(SysBusDevice: DeviceState, Object);
// TODO: add virtual methods
pub trait SysBusDeviceImpl: DeviceImpl + IsA<SysBusDevice> {}
impl SysBusDeviceClass {
pub trait SysBusDeviceClassExt {
fn class_init<T: SysBusDeviceImpl>(&mut self);
}
impl SysBusDeviceClassExt for SysBusDeviceClass {
/// Fill in the virtual methods of `SysBusDeviceClass` based on the
/// definitions in the `SysBusDeviceImpl` trait.
pub fn class_init<T: SysBusDeviceImpl>(self: &mut SysBusDeviceClass) {
fn class_init<T: SysBusDeviceImpl>(&mut self) {
self.parent_class.class_init::<T>();
}
}

View File

@@ -4,6 +4,7 @@ pub use crate::qom::InterfaceType;
pub use crate::qom::IsA;
pub use crate::qom::Object;
pub use crate::qom::ObjectCast;
pub use crate::qom::ObjectClassExt;
pub use crate::qom::ObjectClassMethods;
pub use crate::qom::ObjectDeref;
pub use crate::qom::ObjectImpl;

View File

@@ -729,10 +729,14 @@ unsafe extern "C" fn rust_unparent_fn<T: ObjectImpl>(dev: *mut bindings::Object)
T::UNPARENT.unwrap()(unsafe { state.as_ref() });
}
impl ObjectClass {
pub trait ObjectClassExt {
fn class_init<T: ObjectImpl>(&mut self);
}
impl ObjectClassExt for ObjectClass {
/// Fill in the virtual methods of `ObjectClass` based on the definitions in
/// the `ObjectImpl` trait.
pub fn class_init<T: ObjectImpl>(&mut self) {
fn class_init<T: ObjectImpl>(&mut self) {
if <T as ObjectImpl>::UNPARENT.is_some() {
self.unparent = Some(rust_unparent_fn::<T>);
}