qemu/rust/qemu-api/tests/tests.rs
Paolo Bonzini 6dd818fbbb rust: qom: put class_init together from multiple ClassInitImpl<>
Parameterize the implementation of ClassInitImpl so that it is
possible to call up the chain of implementations, one superclass at
a time starting at ClassInitImpl<Self::Class>.

In order to avoid having to implement (for example)
ClassInitImpl<PL011Class>, also remove the dummy PL011Class and
PL011LuminaryClass structs and specify the same ObjectType::Class as
the superclass.  In the future this default behavior can be handled by
a procedural macro, by looking at the first field in the struct.

Note that the new trait is safe: the calls are started by
rust_class_init<>(), which is not public and can convert the class
pointer to a Rust reference.

Since CLASS_BASE_INIT applies to the type that is being defined,
and only to it, move it to ObjectImpl.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2024-12-19 19:36:37 +01:00

63 lines
1.7 KiB
Rust

// Copyright 2024, Linaro Limited
// Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
// SPDX-License-Identifier: GPL-2.0-or-later
use std::ffi::CStr;
use qemu_api::{
bindings::*, c_str, declare_properties, define_property, definitions::ObjectImpl,
device_class::DeviceImpl, impl_device_class, prelude::*, zeroable::Zeroable,
};
#[test]
fn test_device_decl_macros() {
// Test that macros can compile.
pub static VMSTATE: VMStateDescription = VMStateDescription {
name: c_str!("name").as_ptr(),
unmigratable: true,
..Zeroable::ZERO
};
#[derive(qemu_api_macros::offsets)]
#[repr(C)]
#[derive(qemu_api_macros::Object)]
pub struct DummyState {
pub _parent: DeviceState,
pub migrate_clock: bool,
}
declare_properties! {
DUMMY_PROPERTIES,
define_property!(
c_str!("migrate-clk"),
DummyState,
migrate_clock,
unsafe { &qdev_prop_bool },
bool
),
}
unsafe impl ObjectType for DummyState {
type Class = <DeviceState as ObjectType>::Class;
const TYPE_NAME: &'static CStr = c_str!("dummy");
}
impl ObjectImpl for DummyState {
type ParentType = DeviceState;
const ABSTRACT: bool = false;
}
impl DeviceImpl for DummyState {
fn properties() -> &'static [Property] {
&DUMMY_PROPERTIES
}
fn vmsd() -> Option<&'static VMStateDescription> {
Some(&VMSTATE)
}
}
unsafe {
module_call_init(module_init_type::MODULE_INIT_QOM);
object_unref(object_new(DummyState::TYPE_NAME.as_ptr()).cast());
}
}