|
25 | 25 | //! functionality that is missing from `vmstate_of!`.
|
26 | 26 |
|
27 | 27 | use core::{marker::PhantomData, mem, ptr::NonNull};
|
| 28 | +use std::os::raw::{c_int, c_void}; |
28 | 29 |
|
29 | 30 | pub use crate::bindings::{VMStateDescription, VMStateField};
|
30 |
| -use crate::{bindings::VMStateFlags, prelude::*, qom::Owned, zeroable::Zeroable}; |
| 31 | +use crate::{ |
| 32 | + bindings::VMStateFlags, callbacks::FnCall, prelude::*, qom::Owned, zeroable::Zeroable, |
| 33 | +}; |
31 | 34 |
|
32 | 35 | /// This macro is used to call a function with a generic argument bound
|
33 | 36 | /// to the type of a field. The function must take a
|
@@ -508,6 +511,53 @@ macro_rules! vmstate_fields {
|
508 | 511 | }}
|
509 | 512 | }
|
510 | 513 |
|
| 514 | +pub extern "C" fn rust_vms_test_field_exists<T, F: for<'a> FnCall<(&'a T, u8), bool>>( |
| 515 | + opaque: *mut c_void, |
| 516 | + version_id: c_int, |
| 517 | +) -> bool { |
| 518 | + let owner: &T = unsafe { &*(opaque.cast::<T>()) }; |
| 519 | + let version: u8 = version_id.try_into().unwrap(); |
| 520 | + // SAFETY: the opaque was passed as a reference to `T`. |
| 521 | + F::call((owner, version)) |
| 522 | +} |
| 523 | + |
| 524 | +pub type VMSFieldExistCb = unsafe extern "C" fn( |
| 525 | + opaque: *mut std::os::raw::c_void, |
| 526 | + version_id: std::os::raw::c_int, |
| 527 | +) -> bool; |
| 528 | + |
| 529 | +#[doc(alias = "VMSTATE_VALIDATE")] |
| 530 | +#[macro_export] |
| 531 | +macro_rules! vmstate_validate { |
| 532 | + ($struct_name:ty, $test_name:expr, $test_fn:expr $(,)?) => { |
| 533 | + $crate::bindings::VMStateField { |
| 534 | + name: ::std::ffi::CStr::as_ptr($test_name), |
| 535 | + field_exists: { |
| 536 | + const fn test_cb_builder__< |
| 537 | + T, |
| 538 | + F: for<'a> $crate::callbacks::FnCall<(&'a T, u8), bool>, |
| 539 | + >( |
| 540 | + _phantom: ::core::marker::PhantomData<F>, |
| 541 | + ) -> $crate::vmstate::VMSFieldExistCb { |
| 542 | + let _: () = F::ASSERT_IS_SOME; |
| 543 | + $crate::vmstate::rust_vms_test_field_exists::<T, F> |
| 544 | + } |
| 545 | + |
| 546 | + const fn phantom__<T>(_: &T) -> ::core::marker::PhantomData<T> { |
| 547 | + ::core::marker::PhantomData |
| 548 | + } |
| 549 | + Some(test_cb_builder__::<$struct_name, _>(phantom__(&$test_fn))) |
| 550 | + }, |
| 551 | + flags: $crate::bindings::VMStateFlags( |
| 552 | + $crate::bindings::VMStateFlags::VMS_MUST_EXIST.0 |
| 553 | + | $crate::bindings::VMStateFlags::VMS_ARRAY.0, |
| 554 | + ), |
| 555 | + num: 0, // 0 elements: no data, only run test_fn callback |
| 556 | + ..$crate::zeroable::Zeroable::ZERO |
| 557 | + } |
| 558 | + }; |
| 559 | +} |
| 560 | + |
511 | 561 | /// A transparent wrapper type for the `subsections` field of
|
512 | 562 | /// [`VMStateDescription`].
|
513 | 563 | ///
|
|
0 commit comments