xref: /openbmc/qemu/rust/qemu-api/src/zeroable.rs (revision 2537f8309885013c4b04ae7b2888591ba0cb6ca7)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 use std::ptr;
4 
5 /// Encapsulates the requirement that
6 /// `MaybeUninit::<Self>::zeroed().assume_init()` does not cause undefined
7 /// behavior.  This trait in principle could be implemented as just:
8 ///
9 /// ```
10 /// pub unsafe trait Zeroable: Default {
11 ///     const ZERO: Self = unsafe { ::core::mem::MaybeUninit::<Self>::zeroed().assume_init() };
12 /// }
13 /// ```
14 ///
15 /// The need for a manual implementation is only because `zeroed()` cannot
16 /// be used as a `const fn` prior to Rust 1.75.0. Once we can assume a new
17 /// enough version of the compiler, we could provide a `#[derive(Zeroable)]`
18 /// macro to check at compile-time that all struct fields are Zeroable, and
19 /// use the above blanket implementation of the `ZERO` constant.
20 ///
21 /// # Safety
22 ///
23 /// Because the implementation of `ZERO` is manual, it does not make
24 /// any assumption on the safety of `zeroed()`.  However, other users of the
25 /// trait could use it that way.  Do not add this trait to a type unless
26 /// all-zeroes is a valid value for the type.  In particular, remember that
27 /// raw pointers can be zero, but references and `NonNull<T>` cannot
28 pub unsafe trait Zeroable: Default {
29     const ZERO: Self;
30 }
31 
32 unsafe impl Zeroable for crate::bindings::Property__bindgen_ty_1 {
33     const ZERO: Self = Self { i: 0 };
34 }
35 
36 unsafe impl Zeroable for crate::bindings::Property {
37     const ZERO: Self = Self {
38         name: ptr::null(),
39         info: ptr::null(),
40         offset: 0,
41         bitnr: 0,
42         bitmask: 0,
43         set_default: false,
44         defval: Zeroable::ZERO,
45         arrayoffset: 0,
46         arrayinfo: ptr::null(),
47         arrayfieldsize: 0,
48         link_type: ptr::null(),
49     };
50 }
51 
52 // bindgen does not derive Default here
53 #[allow(clippy::derivable_impls)]
54 impl Default for crate::bindings::VMStateFlags {
55     fn default() -> Self {
56         Self(0)
57     }
58 }
59 
60 unsafe impl Zeroable for crate::bindings::VMStateFlags {
61     const ZERO: Self = Self(0);
62 }
63 
64 unsafe impl Zeroable for crate::bindings::VMStateField {
65     const ZERO: Self = Self {
66         name: ptr::null(),
67         err_hint: ptr::null(),
68         offset: 0,
69         size: 0,
70         start: 0,
71         num: 0,
72         num_offset: 0,
73         size_offset: 0,
74         info: ptr::null(),
75         flags: Zeroable::ZERO,
76         vmsd: ptr::null(),
77         version_id: 0,
78         struct_version_id: 0,
79         field_exists: None,
80     };
81 }
82 
83 unsafe impl Zeroable for crate::bindings::VMStateDescription {
84     const ZERO: Self = Self {
85         name: ptr::null(),
86         unmigratable: false,
87         early_setup: false,
88         version_id: 0,
89         minimum_version_id: 0,
90         priority: crate::bindings::MigrationPriority::MIG_PRI_DEFAULT,
91         pre_load: None,
92         post_load: None,
93         pre_save: None,
94         post_save: None,
95         needed: None,
96         dev_unplug_pending: None,
97         fields: ptr::null(),
98         subsections: ptr::null(),
99     };
100 }
101 
102 unsafe impl Zeroable for crate::bindings::MemoryRegionOps__bindgen_ty_1 {
103     const ZERO: Self = Self {
104         min_access_size: 0,
105         max_access_size: 0,
106         unaligned: false,
107         accepts: None,
108     };
109 }
110 
111 unsafe impl Zeroable for crate::bindings::MemoryRegionOps__bindgen_ty_2 {
112     const ZERO: Self = Self {
113         min_access_size: 0,
114         max_access_size: 0,
115         unaligned: false,
116     };
117 }
118