1//! Contains types and traits for nonexhaustive enums.
2//!
3//! The most important type here is [NonExhaustive](./nonexhaustive/struct.NonExhaustive.html),
4//! which allows passing an enum which used the
5//! `#[derive(StableAbi)] #[sabi(kind(WithNonExhaustive(...)))]`
6//! attributes through ffi.
7//!
89#[doc(hidden)]
10pub mod doc_enums;
1112#[cfg(any(feature = "testing", feature = "nonexhaustive_examples"))]
13pub mod examples;
1415pub(crate) mod alt_c_functions;
16pub(crate) mod nonexhaustive;
17pub(crate) mod traits;
18pub(crate) mod vtable;
1920pub use self::{
21 nonexhaustive::{
22 NonExhaustive, NonExhaustiveFor, NonExhaustiveSharedOps, NonExhaustiveWI, NonExhaustiveWS,
23 UnwrapEnumError,
24 },
25 traits::{
26 DeserializeEnum, EnumInfo, GetEnumInfo, NonExhaustiveMarker, SerializeEnum,
27 ValidDiscriminant,
28 },
29 vtable::GetVTable,
30};
3132pub(crate) use self::traits::GetSerializeEnumProxy;
3334/////////////////////////////////////////////////////////////
3536/// Asserts that the size and alignment of an enum are valid for its default storage.
37#[track_caller]
38pub fn assert_correct_default_storage<E>()
39where
40E: GetEnumInfo,
41{
42 assert_correct_storage::<E, E::DefaultStorage>(AssertCsArgs {
43 enum_ty: std::any::type_name::<E>(),
44 storage_ty: std::any::type_name::<E::DefaultStorage>(),
45 })
46}
4748/// Arguments for [`assert_correct_storage`]
49pub struct AssertCsArgs {
50/// The stringified type name of the enum.
51pub enum_ty: &'static str,
52/// The stringified type name of the storage.
53pub storage_ty: &'static str,
54}
5556impl AssertCsArgs {
57/// Constant where both types are unknown.
58pub const UNKNOWN: Self = Self {
59 enum_ty: "<unknown>",
60 storage_ty: "<unknown>",
61 };
62}
6364/// Asserts that the size and alignment of an enum aree valid for this storage.
65///
66/// To make this function a `const fn`,
67/// the names of the `Enum` and `Storage` types must be passed separately.
68#[track_caller]
69pub const fn assert_correct_storage<Enum, Storage>(args: AssertCsArgs) {
70#[derive(Debug)]
71 #[allow(dead_code)]
72struct TypeAndStorageLayout {
73 enum_: &'static str,
74 enum_size: usize,
75 enum_alignment: usize,
76 storage_: &'static str,
77 storage_size: usize,
78 storage_alignment: usize,
79 }
8081#[track_caller]
82const fn inner(lay: TypeAndStorageLayout) {
83let msg = match (
84 lay.enum_alignment <= lay.storage_alignment,
85 lay.enum_size <= lay.storage_size,
86 ) {
87 (false, false) => {
88"The alignment and size of the storage is smaller than the contained type"
89}
90 (false, true) => "The alignment of the storage is lower than the contained type",
91 (true, false) => "The size of the storage is smaller than the contained type",
92 (true, true) => return,
93 };
9495const_panic::concat_panic!(
96"\n",
97 display: msg,
98":\n",
99"\tenum_: ",
100 lay.enum_,
101"\n",
102"\tenum_size: ",
103 lay.enum_size,
104"\n",
105"\tenum_alignment: ",
106 lay.enum_alignment,
107"\n",
108"\tstorage_: ",
109 lay.storage_,
110"\n",
111"\tstorage_size: ",
112 lay.storage_size,
113"\n",
114"\tstorage_alignment: ",
115 lay.storage_alignment,
116"\n",
117 )
118 }
119120 inner(TypeAndStorageLayout {
121 enum_: args.enum_ty,
122 enum_size: std::mem::size_of::<Enum>(),
123 enum_alignment: std::mem::align_of::<Enum>(),
124 storage_: args.storage_ty,
125 storage_size: std::mem::size_of::<Storage>(),
126 storage_alignment: std::mem::align_of::<Storage>(),
127 })
128}