summaryrefslogtreecommitdiff
path: root/rust/macros/lib.rs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-12-12 16:59:00 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2022-12-12 16:59:00 -0800
commit96f42635684739cb563aa48d92d0d16b8dc9bda8 (patch)
tree661a6b0a72f70702401ac65c73a6f71bd12e83de /rust/macros/lib.rs
parenteb4511538191ac758faa0735fe06c5ce8202ae04 (diff)
parentb9ecf9b9ac5969d7b7ea786ce5c76e24246df2c5 (diff)
Merge tag 'rust-6.2' of https://github.com/Rust-for-Linux/linux
Pull rust updates from Miguel Ojeda: "The first set of changes after the merge, the major ones being: - String and formatting: new types 'CString', 'CStr', 'BStr' and 'Formatter'; new macros 'c_str!', 'b_str!' and 'fmt!'. - Errors: the rest of the error codes from 'errno-base.h', as well as some 'From' trait implementations for the 'Error' type. - Printing: the rest of the 'pr_*!' levels and the continuation one 'pr_cont!', as well as a new sample. - 'alloc' crate: new constructors 'try_with_capacity()' and 'try_with_capacity_in()' for 'RawVec' and 'Vec'. - Procedural macros: new macros '#[vtable]' and 'concat_idents!', as well as better ergonomics for 'module!' users. - Asserting: new macros 'static_assert!', 'build_error!' and 'build_assert!', as well as a new crate 'build_error' to support them. - Vocabulary types: new types 'Opaque' and 'Either'. - Debugging: new macro 'dbg!'" * tag 'rust-6.2' of https://github.com/Rust-for-Linux/linux: (28 commits) rust: types: add `Opaque` type rust: types: add `Either` type rust: build_assert: add `build_{error,assert}!` macros rust: add `build_error` crate rust: static_assert: add `static_assert!` macro rust: std_vendor: add `dbg!` macro based on `std`'s one rust: str: add `fmt!` macro rust: str: add `CString` type rust: str: add `Formatter` type rust: str: add `c_str!` macro rust: str: add `CStr` unit tests rust: str: implement several traits for `CStr` rust: str: add `CStr` type rust: str: add `b_str!` macro rust: str: add `BStr` type rust: alloc: add `Vec::try_with_capacity{,_in}()` constructors rust: alloc: add `RawVec::try_with_capacity_in()` constructor rust: prelude: add `error::code::*` constant items rust: error: add `From` implementations for `Error` rust: error: add codes from `errno-base.h` ...
Diffstat (limited to 'rust/macros/lib.rs')
-rw-r--r--rust/macros/lib.rs108
1 files changed, 102 insertions, 6 deletions
diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs
index 91764bfb1f89..c1d385e345b9 100644
--- a/rust/macros/lib.rs
+++ b/rust/macros/lib.rs
@@ -2,8 +2,10 @@
//! Crate for all kernel procedural macros.
+mod concat_idents;
mod helpers;
mod module;
+mod vtable;
use proc_macro::TokenStream;
@@ -23,20 +25,20 @@ use proc_macro::TokenStream;
///
/// module!{
/// type: MyModule,
-/// name: b"my_kernel_module",
-/// author: b"Rust for Linux Contributors",
-/// description: b"My very own kernel module!",
-/// license: b"GPL",
+/// name: "my_kernel_module",
+/// author: "Rust for Linux Contributors",
+/// description: "My very own kernel module!",
+/// license: "GPL",
/// params: {
/// my_i32: i32 {
/// default: 42,
/// permissions: 0o000,
-/// description: b"Example of i32",
+/// description: "Example of i32",
/// },
/// writeable_i32: i32 {
/// default: 42,
/// permissions: 0o644,
-/// description: b"Example of i32",
+/// description: "Example of i32",
/// },
/// },
/// }
@@ -70,3 +72,97 @@ use proc_macro::TokenStream;
pub fn module(ts: TokenStream) -> TokenStream {
module::module(ts)
}
+
+/// 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 is intended to close the gap. Traits can be declared and
+/// implemented with the `#[vtable]` attribute, and a `HAS_*` associated constant
+/// will be generated for each method in the trait, indicating if the implementor
+/// has overridden a method.
+///
+/// This attribute is not needed if all methods are required.
+///
+/// # Examples
+///
+/// ```ignore
+/// use kernel::prelude::*;
+///
+/// // Declares a `#[vtable]` trait
+/// #[vtable]
+/// pub trait Operations: Send + Sync + Sized {
+/// fn foo(&self) -> Result<()> {
+/// Err(EINVAL)
+/// }
+///
+/// fn bar(&self) -> Result<()> {
+/// Err(EINVAL)
+/// }
+/// }
+///
+/// struct Foo;
+///
+/// // Implements the `#[vtable]` trait
+/// #[vtable]
+/// impl Operations for Foo {
+/// fn foo(&self) -> Result<()> {
+/// # Err(EINVAL)
+/// // ...
+/// }
+/// }
+///
+/// assert_eq!(<Foo as Operations>::HAS_FOO, true);
+/// assert_eq!(<Foo as Operations>::HAS_BAR, false);
+/// ```
+#[proc_macro_attribute]
+pub fn vtable(attr: TokenStream, ts: TokenStream) -> TokenStream {
+ vtable::vtable(attr, ts)
+}
+
+/// Concatenate two identifiers.
+///
+/// This is useful in macros that need to declare or reference items with names
+/// starting with a fixed prefix and ending in a user specified name. The resulting
+/// identifier has the span of the second argument.
+///
+/// # Examples
+///
+/// ```ignore
+/// use kernel::macro::concat_idents;
+///
+/// macro_rules! pub_no_prefix {
+/// ($prefix:ident, $($newname:ident),+) => {
+/// $(pub(crate) const $newname: u32 = kernel::macros::concat_idents!($prefix, $newname);)+
+/// };
+/// }
+///
+/// pub_no_prefix!(
+/// binder_driver_return_protocol_,
+/// BR_OK,
+/// BR_ERROR,
+/// BR_TRANSACTION,
+/// BR_REPLY,
+/// BR_DEAD_REPLY,
+/// BR_TRANSACTION_COMPLETE,
+/// BR_INCREFS,
+/// BR_ACQUIRE,
+/// BR_RELEASE,
+/// BR_DECREFS,
+/// BR_NOOP,
+/// BR_SPAWN_LOOPER,
+/// BR_DEAD_BINDER,
+/// BR_CLEAR_DEATH_NOTIFICATION_DONE,
+/// BR_FAILED_REPLY
+/// );
+///
+/// assert_eq!(BR_OK, binder_driver_return_protocol_BR_OK);
+/// ```
+#[proc_macro]
+pub fn concat_idents(ts: TokenStream) -> TokenStream {
+ concat_idents::concat_idents(ts)
+}