repr_c_impl/
util.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2use crate::builder::common::default_aligned_alignment;
3use crate::layout::Annotation;
4use crate::result::{err, ErrorType, Result};
5use crate::target::Target;
6
7/// The number of bits in a byte.
8pub const BITS_PER_BYTE: u64 = 8;
9
10pub(crate) trait MinAssign<T> {
11    fn assign_min(&mut self, other: T);
12}
13
14impl MinAssign<u64> for u64 {
15    fn assign_min(&mut self, other: u64) {
16        *self = (*self).min(other);
17    }
18}
19
20impl MinAssign<Option<u64>> for u64 {
21    fn assign_min(&mut self, other: Option<u64>) {
22        *self = (*self).min2(other)
23    }
24}
25
26pub(crate) trait MaxAssign<T> {
27    fn assign_max(&mut self, other: T);
28}
29
30impl MaxAssign<Option<u64>> for Option<u64> {
31    fn assign_max(&mut self, other: Option<u64>) {
32        *self = (*self).max2(other);
33    }
34}
35
36impl MaxAssign<u64> for Option<u64> {
37    fn assign_max(&mut self, other: u64) {
38        *self = Some((*self).max2(other));
39    }
40}
41
42impl MaxAssign<Option<u64>> for u64 {
43    fn assign_max(&mut self, other: Option<u64>) {
44        *self = (*self).max2(other);
45    }
46}
47
48impl MaxAssign<u64> for u64 {
49    fn assign_max(&mut self, other: u64) {
50        *self = (*self).max(other);
51    }
52}
53
54pub(crate) trait MinExt<T> {
55    type Output;
56
57    fn min2(self, other: T) -> Self::Output;
58}
59
60impl MinExt<Option<u64>> for Option<u64> {
61    type Output = Option<u64>;
62
63    fn min2(self, other: Option<u64>) -> Option<u64> {
64        match (self, other) {
65            (Some(a), Some(b)) => Some(a.min(b)),
66            (None, _) => other,
67            _ => self,
68        }
69    }
70}
71
72impl MinExt<Option<u64>> for u64 {
73    type Output = u64;
74
75    fn min2(self, other: Option<u64>) -> u64 {
76        match other {
77            Some(b) => self.min(b),
78            _ => self,
79        }
80    }
81}
82
83impl MinExt<u64> for Option<u64> {
84    type Output = u64;
85
86    fn min2(self, other: u64) -> u64 {
87        match self {
88            Some(b) => other.min(b),
89            _ => other,
90        }
91    }
92}
93
94pub(crate) trait MaxExt<T> {
95    type Output;
96
97    fn max2(self, other: T) -> Self::Output;
98}
99
100impl MaxExt<Option<u64>> for Option<u64> {
101    type Output = Option<u64>;
102
103    fn max2(self, other: Option<u64>) -> Option<u64> {
104        match (self, other) {
105            (Some(a), Some(b)) => Some(a.max(b)),
106            (None, _) => other,
107            _ => self,
108        }
109    }
110}
111
112impl MaxExt<Option<u64>> for u64 {
113    type Output = u64;
114
115    fn max2(self, other: Option<u64>) -> u64 {
116        match other {
117            Some(b) => self.max(b),
118            _ => self,
119        }
120    }
121}
122
123impl MaxExt<u64> for Option<u64> {
124    type Output = u64;
125
126    fn max2(self, other: u64) -> u64 {
127        match self {
128            Some(b) => other.max(b),
129            _ => other,
130        }
131    }
132}
133
134pub(crate) fn align_to(n: u64, m: u64) -> Result<u64> {
135    assert!(m.is_power_of_two());
136    let mask = m - 1;
137    match n.checked_add(mask) {
138        Some(n) => Ok(n & !mask),
139        _ => Err(err(ErrorType::SizeOverflow)),
140    }
141}
142
143pub(crate) fn is_attr_packed(a: &[Annotation]) -> bool {
144    a.iter().any(|a| matches!(a, Annotation::AttrPacked))
145}
146
147pub(crate) fn annotation_alignment(target: Target, annotations: &[Annotation]) -> Option<u64> {
148    let mut max = None;
149    for a in annotations {
150        if let Annotation::Align(n) = a {
151            max.assign_max(n.unwrap_or_else(|| default_aligned_alignment(target)));
152        }
153    }
154    max
155}
156
157pub(crate) fn pragma_pack_value(a: &[Annotation]) -> Option<u64> {
158    for a in a {
159        if let Annotation::PragmaPack(n) = a {
160            return Some(*n);
161        }
162    }
163    None
164}
165
166pub(crate) fn size_mul(a: u64, b: u64) -> Result<u64> {
167    match a.checked_mul(b) {
168        Some(v) => Ok(v),
169        None => Err(err(ErrorType::SizeOverflow)),
170    }
171}
172
173pub(crate) fn size_add(a: u64, b: u64) -> Result<u64> {
174    match a.checked_add(b) {
175        Some(v) => Ok(v),
176        None => Err(err(ErrorType::SizeOverflow)),
177    }
178}