On Thu, Jun 11, 2026 at 5:56 PM Zhao Liu <[email protected]> wrote: > > On Tue, May 26, 2026 at 07:56:14PM +0200, Paolo Bonzini wrote: > > Date: Tue, 26 May 2026 19:56:14 +0200 > > From: Paolo Bonzini <[email protected]> > > Subject: [PATCH v3 15/19] scripts/qapi: generate high-level Rust bindings > > X-Mailer: git-send-email 2.54.0 > > > > From: Marc-André Lureau <[email protected]> > > > > Generate high-level native Rust declarations for the QAPI types. > > > > - char* is mapped to String, scalars to there corresponding Rust types > > > > - enums use #[repr(u32)] and can be transmuted to their C counterparts > > > > - has_foo/foo members are mapped to Option<T> > > > > - lists are represented as Vec<T> > > > > - structures map fields 1:1 to Rust > > > > - alternate are represented as Rust enum, each variant being a 1-element > > tuple > > > > - unions are represented in a similar way as in C: a struct S with a "u" > > member (since S may have extra 'base' fields). The discriminant > > isn't a member of S, since Rust enum already include it, but it can be > > recovered with "mystruct.u.into()" > > > > Anything that includes a recursive struct puts it in a Box. Lists are > > not considered recursive, because Vec breaks the recursion (it's possible > > to construct an object containing an empty Vec of its own type). > > > > Given the experimental nature of Rust, and the incompleteness of the > > backend (it lacks commands and events), QAPIRsBackend is not modular > > and is not built together with the C and trace-event files. It can > > be used by specifying "-B qapi.backend.QAPIRsBackend" on the qapi-gen > > command line. > > > > Signed-off-by: Marc-André Lureau <[email protected]> > > Link: > > https://lore.kernel.org/r/[email protected] > > [Paolo: rewrite conversion of leaf types] > > Signed-off-by: Paolo Bonzini <[email protected]> > > --- > > meson.build | 4 +- > > scripts/qapi/backend.py | 25 +++ > > scripts/qapi/common.py | 49 ++++++ > > scripts/qapi/rs.py | 50 ++++++ > > scripts/qapi/rs_types.py | 372 +++++++++++++++++++++++++++++++++++++++ > > scripts/qapi/schema.py | 59 +++++-- > > 6 files changed, 540 insertions(+), 19 deletions(-) > > create mode 100644 scripts/qapi/rs.py > > create mode 100644 scripts/qapi/rs_types.py > > [snip] > > > +def rs_name(name: str) -> str: > > + """ > > + Map @name to a valid, possibly raw Rust identifier. > > + """ > > + name = re.sub(r'[^A-Za-z0-9_]', '_', name) > > + if name[0].isnumeric(): > > + name = '_' + name > > + # based from the list: > > + # https://doc.rust-lang.org/reference/keywords.html > > + if name in ('Self', 'abstract', 'as', 'async', > ^^^^ > > + 'await', 'become', 'box', 'break', > > + 'const', 'continue', 'crate', 'do', > ^^^^^ > > + 'dyn', 'else', 'enum', 'extern', > > + 'false', 'final', 'fn', 'for', > > + 'if', 'impl', 'in', 'let', > > + 'loop', 'macro', 'match', 'mod', > > + 'move', 'mut', 'override', 'priv', > > + 'pub', 'ref', 'return', 'self', > ^^^^ > > + 'static', 'struct', 'super', 'trait', > ^^^^^ > > + 'true', 'try', 'type', 'typeof', > > + 'union', 'unsafe', 'unsized', 'use', > > + 'virtual', 'where', 'while', 'yield'): > > + name = 'r#' + name > > EMM, r#self, r#Self, r#crate and r#super are "RESERVED_RAW_IDENTIFIER", > and "It is an error to use the RESERVED_RAW_IDENTIFIER token". [*] > > [*]: > https://doc.rust-lang.org/reference/identifiers.html#grammar-RESERVED_RAW_IDENTIFIER > > We can't use 'q_' prefix for these special case, or what about > name + '_'?
This is what bindgen does also: https://github.com/rust-lang/rust-bindgen/blob/2048231f45c87cd65d7891f55090aac81cc0d66b/bindgen-tests/tests/headers/keywords.h becomes: https://github.com/rust-lang/rust-bindgen/blob/2048231f45c87cd65d7891f55090aac81cc0d66b/bindgen-tests/tests/expectations/tests/keywords.rs > > e.g., > > if name in ('self', 'Self', 'crate', 'super'): > name = name + '_' > elif name in (...) > name = 'r#' + name > > > + > > + return name > > + > > [snip] > > > @@ -502,6 +515,9 @@ def is_implicit(self) -> bool: > > def c_type(self) -> str: > > return c_name(self.name) + POINTER_SUFFIX > > > > + def rs_type(self) -> str: > > Only a nit, it's better to check _checked before accessing element_type > (just refer Markus' suggestion in v2) > > assert self._checked > > > + return 'Vec<%s>' % self.element_type.rs_type() > > + > > Regards, > Zhao > > -- Manos Pitsidianakis Emulation and Virtualization Engineer at Linaro Ltd
