abi_stable/type_layout/
small_types.rs

1use super::*;
2
3use crate::const_utils::{min_u16, min_u8};
4
5use std::ops::{Range, RangeInclusive};
6
7////////////////////////////////////////////////////////////////////////////////
8
9/// The start and length of a slice into `TLFunctions`.
10#[repr(transparent)]
11#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, StableAbi)]
12pub struct StartLen {
13    bits: u32,
14}
15
16/// The internal representation of `StartLen`.
17pub type StartLenRepr = u32;
18
19impl StartLen {
20    /// Constructs a range.
21    #[inline]
22    pub const fn new(start: u16, len: u16) -> Self {
23        Self {
24            bits: (start as u32) | ((len as u32) << 16),
25        }
26    }
27
28    /// Gets the start of the range.
29    #[inline]
30    pub const fn start(self) -> u16 {
31        self.bits as u16
32    }
33    /// Gets the length of the range.
34    #[inline]
35    pub const fn len(self) -> u16 {
36        (self.bits >> 16) as u16
37    }
38
39    /// Whether the range is empty.
40    pub const fn is_empty(self) -> bool {
41        self.len() == 0
42    }
43
44    /// Gets the start of the range as a usize.
45    #[inline]
46    pub const fn start_usize(self) -> usize {
47        (self.bits & 0xffff) as usize
48    }
49    #[inline]
50    /// Gets the length of the range as a usize.
51    pub const fn len_usize(self) -> usize {
52        (self.bits >> 16) as usize
53    }
54    /// Gets the exclusive end of the range as a usize.
55    #[inline]
56    pub const fn end_usize(self) -> usize {
57        self.start_usize() + self.len_usize()
58    }
59
60    /// Converts this range to a `std::ops::Range`.
61    #[inline]
62    pub const fn to_range(self) -> Range<usize> {
63        self.start_usize()..self.end_usize()
64    }
65
66    /// Constructs this `StartLen` from its internal representation.
67    #[inline]
68    pub const fn from_u32(n: StartLenRepr) -> Self {
69        Self { bits: n }
70    }
71
72    /// An empty range.
73    pub const EMPTY: Self = Self::new(0, 0);
74
75    abi_stable_shared::declare_start_len_bit_methods! {}
76}
77
78/// Used to convert the arguments passed to the `tl_genparams` macro to a `StartLen`.
79pub struct StartLenConverter<T>(pub T);
80
81#[allow(clippy::wrong_self_convention)]
82impl StartLenConverter<()> {
83    /// Constructs an empty `StartLen`.
84    pub const fn to_start_len(self) -> StartLen {
85        StartLen::EMPTY
86    }
87}
88
89#[allow(clippy::wrong_self_convention)]
90impl StartLenConverter<usize> {
91    /// Constructs a `StartLen` from `0` to `self.0` exclusive.
92    pub const fn to_start_len(self) -> StartLen {
93        StartLen::new(self.0 as u16, 1)
94    }
95}
96
97#[allow(clippy::wrong_self_convention)]
98impl StartLenConverter<Range<usize>> {
99    /// Constructs a `StartLen` from the `Range`.
100    pub const fn to_start_len(self) -> StartLen {
101        let start = self.0.start as u16;
102        let len = (self.0.end - self.0.start) as u16;
103        StartLen::new(start, len)
104    }
105}
106
107#[allow(clippy::wrong_self_convention)]
108impl StartLenConverter<RangeInclusive<usize>> {
109    /// Constructs a `StartLen` from the `RangeInclusive`.
110    pub const fn to_start_len(self) -> StartLen {
111        let start = *self.0.start();
112        let end = *self.0.end() + 1;
113        StartLen::new(start as u16, (end - start) as u16)
114    }
115}
116
117#[allow(clippy::wrong_self_convention)]
118impl StartLenConverter<StartLen> {
119    /// Unwraps this back into a `StartLen`.
120    pub const fn to_start_len(self) -> StartLen {
121        self.0
122    }
123}
124
125/////////////////////////////////////////////////////////////////////////////////////////////
126
127/// An optional u16 which represents None as `u16::max_value()`
128#[repr(transparent)]
129#[derive(Copy, Clone, PartialEq, Eq, Ord, PartialOrd, StableAbi)]
130pub struct OptionU16(u16);
131
132impl OptionU16 {
133    /// Equivalent to Option::None
134    #[allow(non_upper_case_globals)]
135    pub const None: Self = OptionU16(!0);
136
137    const MAX_VAL: u16 = !0 - 1;
138
139    /// Constructs the equivalent of `Some(value)`,
140    /// which saturates the `u16::max_value()` value down to `u16::max_value()-1`
141    pub const fn some(value: u16) -> Self {
142        OptionU16(min_u16(value, Self::MAX_VAL))
143    }
144
145    /// Const equivalent of `OptionU16 == OptionU16`
146    pub const fn eq(self, other: Self) -> bool {
147        self.0 == other.0
148    }
149
150    /// Const equivalent of `OptionU16 != OptionU16`
151    pub const fn ne(self, other: Self) -> bool {
152        self.0 != other.0
153    }
154
155    /// Whether this is the Some variant.
156    pub const fn is_some(self) -> bool {
157        self.ne(Self::None)
158    }
159    /// Whether this is the None variant.
160    pub const fn is_none(self) -> bool {
161        self.eq(Self::None)
162    }
163
164    /// Converts this to an `Option<u16>`.
165    pub const fn to_option(self) -> Option<u16> {
166        if self.is_some() {
167            Some(self.0)
168        } else {
169            None
170        }
171    }
172}
173
174impl Debug for OptionU16 {
175    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
176        Debug::fmt(&self.to_option(), f)
177    }
178}
179
180impl Display for OptionU16 {
181    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
182        if self.is_some() {
183            Display::fmt("None", f)
184        } else {
185            Display::fmt(&self.0, f)
186        }
187    }
188}
189
190/////////////////////////////////////////////////////////////////////////////////////////////
191
192/// An optional u8 which represents None as `u8::max_value()`
193#[repr(transparent)]
194#[derive(Copy, Clone, PartialEq, Eq, Ord, PartialOrd, StableAbi)]
195pub struct OptionU8(u8);
196
197impl OptionU8 {
198    /// Equivalent to Option::None
199    #[allow(non_upper_case_globals)]
200    pub const None: Self = OptionU8(!0);
201
202    const MAX_VAL: u8 = !0 - 1;
203
204    /// Constructs the equivalent of `Some(value)`,
205    /// which saturates the `u8::max_value()` value down to `u8::max_value()-1`
206    pub const fn some(value: u8) -> Self {
207        OptionU8(min_u8(value, Self::MAX_VAL))
208    }
209
210    /// Const equivalent of `OptionU8 == OptionU8`
211    pub const fn eq(self, other: Self) -> bool {
212        self.0 == other.0
213    }
214
215    /// Const equivalent of `OptionU8 != OptionU8`
216    pub const fn ne(self, other: Self) -> bool {
217        self.0 != other.0
218    }
219
220    /// Whether this is the Some variant.
221    pub const fn is_some(self) -> bool {
222        self.ne(Self::None)
223    }
224    /// Whether this is the None variant.
225    pub const fn is_none(self) -> bool {
226        self.eq(Self::None)
227    }
228
229    /// Converts this to an `Option<u8>`.
230    pub const fn to_option(self) -> Option<u8> {
231        if self.is_some() {
232            Some(self.0)
233        } else {
234            None
235        }
236    }
237}
238
239impl Debug for OptionU8 {
240    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
241        Debug::fmt(&self.to_option(), f)
242    }
243}
244
245impl Display for OptionU8 {
246    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
247        if self.is_some() {
248            Display::fmt("None", f)
249        } else {
250            Display::fmt(&self.0, f)
251        }
252    }
253}