diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2024-11-06 00:01:57 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2024-12-19 19:36:37 +0100 |
commit | ba3b81f3b668d3faa6cbdb39e123394f7bf637c7 (patch) | |
tree | 42d37373c9ad3d1004e2565e7b2e98647f3916d3 /rust/qemu-api/src/qom.rs | |
parent | f50cd85c8475c16374d0e138efda222ce4455f53 (diff) | |
download | qemu-ba3b81f3b668d3faa6cbdb39e123394f7bf637c7.zip qemu-ba3b81f3b668d3faa6cbdb39e123394f7bf637c7.tar.gz qemu-ba3b81f3b668d3faa6cbdb39e123394f7bf637c7.tar.bz2 |
rust: qom: add initial subset of methods on Object
Add an example of implementing instance methods and converting the
result back to a Rust type. In this case the returned types are a
string (actually a Cow<str>; but that's transparent as long as it derefs
to &str) and a QOM class.
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'rust/qemu-api/src/qom.rs')
-rw-r--r-- | rust/qemu-api/src/qom.rs | 56 |
1 files changed, 53 insertions, 3 deletions
diff --git a/rust/qemu-api/src/qom.rs b/rust/qemu-api/src/qom.rs index 74ea572..7d5fbef 100644 --- a/rust/qemu-api/src/qom.rs +++ b/rust/qemu-api/src/qom.rs @@ -5,8 +5,8 @@ //! Bindings to access QOM functionality from Rust. //! //! The QEMU Object Model (QOM) provides inheritance and dynamic typing for QEMU -//! devices. This module makes QOM's features available in Rust through two main -//! mechanisms: +//! devices. This module makes QOM's features available in Rust through three +//! main mechanisms: //! //! * Automatic creation and registration of `TypeInfo` for classes that are //! written in Rust, as well as mapping between Rust traits and QOM vtables. @@ -15,6 +15,11 @@ //! trait and methods such as [`upcast`](ObjectCast::upcast) and //! [`downcast`](ObjectCast::downcast). //! +//! * Automatic delegation of parent class methods to child classes. When a +//! trait uses [`IsA`] as a bound, its contents become available to all child +//! classes through blanket implementations. This works both for class methods +//! and for instance methods accessed through references or smart pointers. +//! //! # Structure of a class //! //! A leaf class only needs a struct holding instance state. The struct must @@ -37,6 +42,16 @@ //! `ClassInitImpl<DeviceClass>`. This fills the vtable in the class struct; //! the source for this is the `*Impl` trait; the associated consts and //! functions if needed are wrapped to map C types into Rust types. +//! +//! * a trait for instance methods, for example `DeviceMethods`. This trait is +//! automatically implemented for any reference or smart pointer to a device +//! instance. It calls into the vtable provides access across all subclasses +//! to methods defined for the class. +//! +//! * optionally, a trait for class methods, for example `DeviceClassMethods`. +//! This provides access to class-wide functionality that doesn't depend on +//! instance data. Like instance methods, these are automatically inherited by +//! child classes. use std::{ ffi::CStr, @@ -46,7 +61,7 @@ use std::{ pub use bindings::{Object, ObjectClass}; -use crate::bindings::{self, object_dynamic_cast, TypeInfo}; +use crate::bindings::{self, object_dynamic_cast, object_get_class, object_get_typename, TypeInfo}; /// Marker trait: `Self` can be statically upcasted to `P` (i.e. `P` is a direct /// or indirect parent of `Self`). @@ -532,3 +547,38 @@ unsafe impl ObjectType for Object { const TYPE_NAME: &'static CStr = unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_OBJECT) }; } + +/// Trait for methods exposed by the Object class. The methods can be +/// called on all objects that have the trait `IsA<Object>`. +/// +/// The trait should only be used through the blanket implementation, +/// which guarantees safety via `IsA` +pub trait ObjectMethods: ObjectDeref +where + Self::Target: IsA<Object>, +{ + /// Return the name of the type of `self` + fn typename(&self) -> std::borrow::Cow<'_, str> { + let obj = self.upcast::<Object>(); + // SAFETY: safety of this is the requirement for implementing IsA + // The result of the C API has static lifetime + unsafe { + let p = object_get_typename(obj.as_mut_ptr()); + CStr::from_ptr(p).to_string_lossy() + } + } + + fn get_class(&self) -> &'static <Self::Target as ObjectType>::Class { + let obj = self.upcast::<Object>(); + + // SAFETY: all objects can call object_get_class; the actual class + // type is guaranteed by the implementation of `ObjectType` and + // `ObjectImpl`. + let klass: &'static <Self::Target as ObjectType>::Class = + unsafe { &*object_get_class(obj.as_mut_ptr()).cast() }; + + klass + } +} + +impl<R: ObjectDeref> ObjectMethods for R where R::Target: IsA<Object> {} |