mem_macros/
lib.rs

1#![no_std]
2//! `align_of` and `size_of` as a macro, to avoid turbofish notation
3
4#[doc(hidden)]
5pub extern crate core as __core;
6
7#[macro_export]
8/// Returns the [ABI]-required minimum alignment of a type.
9///
10/// Every reference to a value of the type `T` must be a multiple of this number.
11///
12/// This is the alignment used for struct fields. It may be smaller than the preferred alignment.
13///
14/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface
15///
16/// # Examples
17///
18/// ```
19/// #[macro_use]
20/// extern crate mem_macros;
21///
22/// # fn main() {
23/// assert_eq!(4, align_of!(i32));
24/// # }
25/// ```
26macro_rules! align_of {
27    ($t:ty) => {
28        $crate::__core::mem::align_of::<$t>()
29    };
30}
31
32/// Returns the size of a type in bytes.
33///
34/// More specifically, this is the offset in bytes between successive elements
35/// in an array with that item type including alignment padding. Thus, for any
36/// type `T` and length `n`, `[T; n]` has a size of `n * size_of!(T)`.
37///
38/// In general, the size of a type is not stable across compilations, but
39/// specific types such as primitives are.
40///
41/// The following table gives the size for primitives.
42///
43/// Type | size_of!(Type)
44/// ---- | ---------------
45/// () | 0
46/// bool | 1
47/// u8 | 1
48/// u16 | 2
49/// u32 | 4
50/// u64 | 8
51/// i8 | 1
52/// i16 | 2
53/// i32 | 4
54/// i64 | 8
55/// f32 | 4
56/// f64 | 8
57/// char | 4
58///
59/// Furthermore, `usize` and `isize` have the same size.
60///
61/// The types `*const T`, `&T`, `Box<T>`, `Option<&T>`, and `Option<Box<T>>` all have
62/// the same size. If `T` is Sized, all of those types have the same size as `usize`.
63///
64/// The mutability of a pointer does not change its size. As such, `&T` and `&mut T`
65/// have the same size. Likewise for `*const T` and `*mut T`.
66///
67/// # Size of `#[repr(C)]` items
68///
69/// The `C` representation for items has a defined layout. With this layout,
70/// the size of items is also stable as long as all fields have a stable size.
71///
72/// ## Size of Structs
73///
74/// For `structs`, the size is determined by the following algorithm.
75///
76/// For each field in the struct ordered by declaration order:
77///
78/// 1. Add the size of the field.
79/// 2. Round up the current size to the nearest multiple of the next field's [alignment].
80///
81/// Finally, round the size of the struct to the nearest multiple of its [alignment].
82///
83/// Unlike `C`, zero sized structs are not rounded up to one byte in size.
84///
85/// ## Size of Enums
86///
87/// Enums that carry no data other than the descriminant have the same size as C enums
88/// on the platform they are compiled for.
89///
90/// ## Size of Unions
91///
92/// The size of a union is the size of its largest field.
93///
94/// Unlike `C`, zero sized unions are not rounded up to one byte in size.
95///
96/// # Examples
97///
98/// ```
99/// #[macro_use]
100/// extern crate mem_macros;
101///
102/// # fn main() {
103/// // Some primitives
104/// assert_eq!(4, size_of!(i32));
105/// assert_eq!(8, size_of!(f64));
106/// assert_eq!(0, size_of!(()));
107///
108/// // Some arrays
109/// assert_eq!(8, size_of!([i32; 2]));
110/// assert_eq!(12, size_of!([i32; 3]));
111/// assert_eq!(0, size_of!([i32; 0]));
112///
113///
114/// // Pointer size equality
115/// assert_eq!(size_of!(&i32), size_of!(*const i32));
116/// assert_eq!(size_of!(&i32), size_of!(Box<i32>));
117/// assert_eq!(size_of!(&i32), size_of!(Option<&i32>));
118/// assert_eq!(size_of!(Box<i32>), size_of!(Option<Box<i32>>));
119/// # }
120/// ```
121///
122/// Using `#[repr(C)]`.
123///
124/// ```
125/// #[macro_use]
126/// extern crate mem_macros;
127///
128/// # fn main() {
129/// #[repr(C)]
130/// struct FieldStruct {
131///     first: u8,
132///     second: u16,
133///     third: u8
134/// }
135///
136/// // The size of the first field is 1, so add 1 to the size. Size is 1.
137/// // The alignment of the second field is 2, so add 1 to the size for padding. Size is 2.
138/// // The size of the second field is 2, so add 2 to the size. Size is 4.
139/// // The alignment of the third field is 1, so add 0 to the size for padding. Size is 4.
140/// // The size of the third field is 1, so add 1 to the size. Size is 5.
141/// // Finally, the alignment of the struct is 2, so add 1 to the size for padding. Size is 6.
142/// assert_eq!(6, size_of!(FieldStruct));
143///
144/// #[repr(C)]
145/// struct TupleStruct(u8, u16, u8);
146///
147/// // Tuple structs follow the same rules.
148/// assert_eq!(6, size_of!(TupleStruct));
149///
150/// // Note that reordering the fields can lower the size. We can remove both padding bytes
151/// // by putting `third` before `second`.
152/// #[repr(C)]
153/// struct FieldStructOptimized {
154///     first: u8,
155///     third: u8,
156///     second: u16
157/// }
158///
159/// assert_eq!(4, size_of!(FieldStructOptimized));
160///
161/// // Union size is the size of the largest field.
162/// #[repr(C)]
163/// union ExampleUnion {
164///     smaller: u8,
165///     larger: u16
166/// }
167///
168/// assert_eq!(2, size_of!(ExampleUnion));
169/// # }
170/// ```
171#[macro_export]
172macro_rules! size_of {
173    ($t:ty) => {
174        $crate::__core::mem::size_of::<$t>()
175    };
176}