#[vtable]
Expand description
Declares or implements a vtable trait.
Linux’s use of pure vtables is very close to Rust traits, but they differ
in how unimplemented functions are represented. In Rust, traits can provide
default implementation for all non-required methods (and the default
implementation could just return Error::EINVAL
); Linux typically use C
NULL
pointers to represent these functions.
This attribute closes that gap. A trait can be annotated with the
#[vtable]
attribute. Implementers of the trait will then also have to
annotate the trait with #[vtable]
. This attribute generates a HAS_*
associated constant bool for each method in the trait that is set to true if
the implementer has overridden the associated method.
For a trait method to be optional, it must have a default implementation.
This is also the case for traits annotated with #[vtable]
, but in this
case the default implementation will never be executed. The reason for this
is that the functions will be called through function pointers installed in
C side vtables. When an optional method is not implemented on a #[vtable]
trait, a NULL entry is installed in the vtable. Thus the default
implementation is never called. Since these traits are not designed to be
used on the Rust side, it should not be possible to call the default
implementation. This is done to ensure that we call the vtable methods
through the C vtable, and not through the Rust vtable. Therefore, the
default implementation should call kernel::build_error
, which prevents
calls to this function at compile time:
kernel::build_error(VTABLE_DEFAULT_ERROR)
Note that you might need to import kernel::error::VTABLE_DEFAULT_ERROR
.
This macro should not be used when all functions are required.
Examples
use kernel::error::VTABLE_DEFAULT_ERROR;
use kernel::prelude::*;
// Declares a `#[vtable]` trait
#[vtable]
pub trait Operations: Send + Sync + Sized {
fn foo(&self) -> Result<()> {
kernel::build_error(VTABLE_DEFAULT_ERROR)
}
fn bar(&self) -> Result<()> {
kernel::build_error(VTABLE_DEFAULT_ERROR)
}
}
struct Foo;
// Implements the `#[vtable]` trait
#[vtable]
impl Operations for Foo {
fn foo(&self) -> Result<()> {
// ...
}
}
assert_eq!(<Foo as Operations>::HAS_FOO, true);
assert_eq!(<Foo as Operations>::HAS_BAR, false);