This adds two related parts of the Rust bindings:

- QAPI code generator that creates Rust structs from the JSON
  description.  The structs are *not* ABI compatible with the
  C ones, instead they use native Rust data types.

- QObject bindings and (de)serialization support, which can be used to
  convert QObjects to and from QAPI structs.

Unfortunately Rust code is not able to use visitors, other than by
creating an intermediate QObject.  This is because of the different
architecture of serde vs. QAPI visitors, and because visitor's
dual-purpose functions, where the same function is used by both input and
output visitors, rely heavily on the structs using the same representation
as the visitor arguments (for example NUL-terminated strings).

The serde format implementation was co-authored by me and Marc-André.
Marc-André did all the bug fixing and integration testing.

As an example of how this would be used, the marshaling functions for
QMP commands would look like this:

fn qmp_marshal_query_stats(args: *mut QDict,
    retp: *mut *mut QObject, errp: *mut *mut Error)
{
    let qobj = unsafe { QObject::cloned_from_raw(args.cast()) };

    let result = from_qobject::<StatsFilter>(qobj)
         .map_err(anyhow::Error::from)
         .and_then(qmp_query_stats)
         .and_then(|ret| 
to_qobject::<Vec<StatsResult>>(ret).map_err(anyhow::Error::from));

    match qmp_marshal_query_stats_rs(qobj) {
        Ok(ret) => unsafe { *retp = ret.into_raw(); },
        Err(e) => unsafe { crate::Error::from(e).propagate(errp) },
    }
}

Despite the long v1->v2, the changes are mostly cosmetic; there are a few
small differences in the detection of types to be wrapped with Box<>,
because Vec<> is now considered to break cycles.

Available at branch rust-next of https://gitlab.com/bonzini/qemu (which
is now almost empty other than this series, yay).

Paolo

v1->v2, Rust:
- adjust comments in C code (include/qobject/qobject.h)
- improve or fix documentation in rust/util/src/qobject/mod.rs
- introduce a qobject! macro that is equivalent to QOBJECT()
- remark when functions are converted from C inlines
- rename from_int/from_uint/from_double macros
- fix incorrect "native: true" on serde and serde_core overrides
- rebase

qapi-gen:
- rewrite QAPISchemaIfCond.rsgen() to avoid messy typing
- new patches 10-11 to extend existing qapigen code
- rewritten rs_type() to avoid going through a C type first
- removed renaming of QAPICBackend
- reused C functions for case conversions
- clean up rs_name, move it to common.py (needed for rs_type() changes)
- Vec<> can break cycles and avoid boxing of structs
- restrict squashing of consecutive newlines to Rust code
- add copyright blurb
- annotate that using a separate qapi-gen backend is temporary
- drop #[derive(common::TryInto)] from enums

Marc-André Lureau (7):
  rust/qobject: add Display/Debug
  scripts/qapi: add QAPISchemaIfCond.rsgen()
  scripts/qapi: generate high-level Rust bindings
  scripts/rustc_args: add --no-strict-cfg
  rust/util: build QAPI types
  scripts/qapi: add serde attributes
  rust/tests: QAPI integration tests

Paolo Bonzini (9):
  rust/qobject: add basic bindings
  subprojects: add serde
  rust/qobject: add Serialize implementation
  rust/qobject: add Serializer (to_qobject) implementation
  rust/qobject: add Deserialize implementation
  rust/qobject: add Deserializer (from_qobject) implementation
  rust/qobject: add from/to JSON bindings for QObject
  scripts/qapi: add QAPISchemaType.is_predefined
  scripts/qapi: pull c_name from camel_to_upper to caller

 docs/devel/rust.rst                           |   1 +
 meson.build                                   |   4 +-
 include/qobject/qobject.h                     |   5 +-
 rust/util/wrapper.h                           |   8 +
 qapi/meson.build                              |   9 +
 rust/Cargo.lock                               |   2 +
 rust/Cargo.toml                               |   2 +
 rust/meson.build                              |   4 +
 rust/tests/meson.build                        |  21 +-
 rust/tests/tests/integration.rs               |   2 +
 rust/tests/tests/qapi.rs                      | 444 +++++++++++++
 rust/util/Cargo.toml                          |   2 +
 rust/util/meson.build                         |  30 +-
 rust/util/src/lib.rs                          |   4 +
 rust/util/src/qobject/deserialize.rs          | 134 ++++
 rust/util/src/qobject/deserializer.rs         | 371 +++++++++++
 rust/util/src/qobject/error.rs                |  58 ++
 rust/util/src/qobject/mod.rs                  | 383 ++++++++++++
 rust/util/src/qobject/serialize.rs            |  59 ++
 rust/util/src/qobject/serializer.rs           | 585 ++++++++++++++++++
 scripts/archive-source.sh                     |   3 +
 scripts/make-release                          |   2 +-
 scripts/qapi/backend.py                       |  25 +
 scripts/qapi/common.py                        |  66 +-
 scripts/qapi/rs.py                            |  61 ++
 scripts/qapi/rs_types.py                      | 394 ++++++++++++
 scripts/qapi/schema.py                        |  74 ++-
 scripts/rust/rustc_args.py                    |  16 +-
 subprojects/.gitignore                        |   3 +
 .../packagefiles/serde-1-rs/meson.build       |  36 ++
 .../packagefiles/serde-1.0.226-include.patch  |  16 +
 .../packagefiles/serde_core-1-rs/meson.build  |  25 +
 .../serde_core-1.0.226-include.patch          |  15 +
 .../serde_derive-1-rs/meson.build             |  35 ++
 .../serde_derive-1.0.226-include.patch        |  11 +
 subprojects/serde-1-rs.wrap                   |  11 +
 subprojects/serde_core-1-rs.wrap              |  11 +
 subprojects/serde_derive-1-rs.wrap            |  11 +
 38 files changed, 2910 insertions(+), 33 deletions(-)
 create mode 100644 rust/tests/tests/integration.rs
 create mode 100644 rust/tests/tests/qapi.rs
 create mode 100644 rust/util/src/qobject/deserialize.rs
 create mode 100644 rust/util/src/qobject/deserializer.rs
 create mode 100644 rust/util/src/qobject/error.rs
 create mode 100644 rust/util/src/qobject/mod.rs
 create mode 100644 rust/util/src/qobject/serialize.rs
 create mode 100644 rust/util/src/qobject/serializer.rs
 create mode 100644 scripts/qapi/rs.py
 create mode 100644 scripts/qapi/rs_types.py
 create mode 100644 subprojects/packagefiles/serde-1-rs/meson.build
 create mode 100644 subprojects/packagefiles/serde-1.0.226-include.patch
 create mode 100644 subprojects/packagefiles/serde_core-1-rs/meson.build
 create mode 100644 subprojects/packagefiles/serde_core-1.0.226-include.patch
 create mode 100644 subprojects/packagefiles/serde_derive-1-rs/meson.build
 create mode 100644 subprojects/packagefiles/serde_derive-1.0.226-include.patch
 create mode 100644 subprojects/serde-1-rs.wrap
 create mode 100644 subprojects/serde_core-1-rs.wrap
 create mode 100644 subprojects/serde_derive-1-rs.wrap

-- 
2.52.0


Reply via email to