devela/data/codec/bit/trait.rs
1// devela::data::codec::bit::trait
2//
3// TOC
4// - definition
5// - impls
6
7#[cfg(_bit··)]
8use super::Bitwise;
9use crate::MismatchedBounds;
10#[cfg(doc)]
11use crate::MismatchedBounds::{DataOverflow, IndexOutOfBounds, MismatchedIndices};
12
13/// Provides bitwise operations on `T`.
14///
15/// See also [`Bitwise`] for the equivalent const wrapper.
16pub trait BitOps
17where
18 Self: Sized,
19{
20 /// The inner type for the bit representation.
21 type Inner;
22
23 /* new mask */
24
25 /// Returns a bitmask of ones from the `[start..=end]` range.
26 ///
27 /// Sets the rest of the bits to 0.
28 ///
29 /// # Panics
30 /// Panics in debug if `start >= Self::BITS` || `end >= Self::BITS` || `start > end`.
31 #[doc = include_str!("./benches/mask_range.md")]
32 #[must_use]
33 fn bit_mask_range(start: u32, end: u32) -> Self;
34
35 /// Returns a bitmask of ones from the `[start..=end]` checked range.
36 ///
37 /// Sets the rest of the bits to 0.
38 ///
39 /// # Errors
40 /// Returns [`IndexOutOfBounds`] if `start >= Self::BITS` || `end >= Self::BITS`
41 /// and [`MismatchedIndices`] if `start > end`.
42 #[doc = include_str!("./benches/mask_checked_range.md")]
43 fn bit_mask_checked_range(start: u32, end: u32) -> Result<Self, MismatchedBounds>;
44
45 /* get */
46
47 /// Gets the bits in `self` from the `[start..=end]` range.
48 ///
49 /// Sets the rest of the bits to 0.
50 /// # Panics
51 /// Panics in debug if `start >= Self::BITS` || `end >= Self::BITS` || `start > end`.
52 #[must_use]
53 fn bit_get_range(self, start: u32, end: u32) -> Self;
54
55 /// Gets the bits in `self` from the `[start..=end]` checked range.
56 ///
57 /// Sets the rest of the bits to 0.
58 /// # Errors
59 /// Returns [`IndexOutOfBounds`] if `start >= Self::BITS` || `end >= Self::BITS`
60 /// and [`MismatchedIndices`] if `start > end`.
61 fn bit_get_checked_range(self, start: u32, end: u32) -> Result<Self, MismatchedBounds>;
62
63 /* get value */
64
65 /// Gets the rightwards shifted bits in `self` from the `[start..=end]` range.
66 ///
67 /// Sets the rest of the bits to 0.
68 ///
69 /// The bits in the specified range are shifted rightwards so that the least
70 /// significant bit (LSB) aligns with the units place, forming the integer value.
71 /// # Panics
72 /// Panics in debug if `start >= Self::BITS` || `end >= Self::BITS` || `start > end`.
73 #[must_use]
74 fn bit_get_value_range(self, start: u32, end: u32) -> Self;
75
76 /// Gets the rightwards shifted bits in `self` from the `[start..=end]` checked range.
77 ///
78 /// Sets the rest of the bits to 0.
79 ///
80 /// The bits in the specified range are shifted rightwards so that the least
81 /// significant bit (LSB) aligns with the units place, forming the integer value.
82 /// # Errors
83 /// Returns [`IndexOutOfBounds`] if `start >= Self::BITS` || `end >= Self::BITS`
84 /// and [`MismatchedIndices`] if `start > end`.
85 fn bit_get_value_checked_range(self, start: u32, end: u32) -> Result<Self, MismatchedBounds>;
86
87 /* set */
88
89 /// Sets the bits in `self` to 1 from the `[start..=end]` range.
90 ///
91 /// Leaves the rest of the bits untouched.
92 /// # Panics
93 /// Panics in debug if `start >= Self::BITS` || `end >= Self::BITS` || `start > end`.
94 #[must_use]
95 fn bit_set_range(self, start: u32, end: u32) -> Self;
96
97 /// Sets the bits in `self` to 1 from the `[start..=end]` checked range.
98 ///
99 /// Leaves the rest of the bits untouched.
100 /// # Errors
101 /// Returns [`IndexOutOfBounds`] if `start >= Self::BITS` || `end >= Self::BITS`
102 /// and [`MismatchedIndices`] if `start > end`.
103 fn bit_set_checked_range(self, start: u32, end: u32) -> Result<Self, MismatchedBounds>;
104
105 /* set value */
106
107 /// Sets the given `value` into the bits from the `[start..=end]` range.
108 ///
109 /// Leaves the rest of the bits unchanged.
110 ///
111 /// The value is first masked to fit the size of the range, and then
112 /// it is inserted into the specified bit range of `self`, replacing
113 /// the existing bits in that range. The rest of the bits in `self` remain unchanged.
114 /// # Panics
115 /// Panics if `start >= BITS || end >= BITS || start > end`.
116 fn bit_set_value_range(self, value: Self::Inner, start: u32, end: u32) -> Self;
117
118 /// Sets the given `value` into the bits from the `[start..=end]` checked range.
119 ///
120 /// Leaves the rest of the bits unchanged.
121 /// # Errors
122 /// Returns [`IndexOutOfBounds`] if `start >= BITS || end >= BITS`
123 /// and [`MismatchedIndices`] if `start > end`.
124 fn bit_set_value_checked_range(
125 self,
126 value: Self::Inner,
127 start: u32,
128 end: u32,
129 ) -> Result<Self, MismatchedBounds>;
130
131 /// Sets the given checked `value` into the bits from the `[start..=end]` checked range.
132 ///
133 /// Leaves the rest of the bits unchanged.
134 /// # Errors
135 /// Returns [`IndexOutOfBounds`] if `start >= BITS || end >= BITS`,
136 /// [`MismatchedIndices`] if `start > end` and
137 /// [`DataOverflow`] if `value` does not fit within the specified bit range.
138 fn bit_set_checked_value_checked_range(
139 self,
140 value: Self::Inner,
141 start: u32,
142 end: u32,
143 ) -> Result<Self, MismatchedBounds>;
144
145 /* unset */
146
147 /// Unsets the bits in `self` to 0 from the `[start..=end]` range.
148 ///
149 /// Leaves the rest of the bits untouched.
150 /// # Panics
151 /// Panics in debug if `start >= Self::BITS` || `end >= Self::BITS` || `start > end`.
152 #[must_use]
153 fn bit_unset_range(self, start: u32, end: u32) -> Self;
154
155 /// Unsets the bits in `self` to 0 from the `[start..=end]` checked range.
156 ///
157 /// Leaves the rest of the bits untouched.
158 /// # Errors
159 /// Returns [`IndexOutOfBounds`] if `start >= Self::BITS` || `end >= Self::BITS`
160 /// and [`MismatchedIndices`] if `start > end`.
161 fn bit_unset_checked_range(self, start: u32, end: u32) -> Result<Self, MismatchedBounds>;
162
163 /* flip */
164
165 /// Flips the bits in `self` from the `[start..=end]` range.
166 ///
167 /// Leaves the rest of the bits untouched.
168 /// # Panics
169 /// Panics in debug if `start >= Self::BITS` || `end >= Self::BITS` || `start > end`.
170 #[must_use]
171 fn bit_flip_range(self, start: u32, end: u32) -> Self;
172
173 /// Flips the bits in `self` from the `[start..=end]` checked range.
174 ///
175 /// Leaves the rest of the bits untouched.
176 /// # Errors
177 /// Returns [`IndexOutOfBounds`] if `start >= Self::BITS` || `end >= Self::BITS`
178 /// and [`MismatchedIndices`] if `start > end`.
179 fn bit_flip_checked_range(self, start: u32, end: u32) -> Result<Self, MismatchedBounds>;
180
181 /* reverse */
182
183 /// Reverses the order of the bits in `self` from the `[start..=end]` range.
184 ///
185 /// Leaves the rest of the bits untouched.
186 /// # Panics
187 /// Panics in debug if `start >= Self::BITS` || `end >= Self::BITS` || `start > end`.
188 #[must_use]
189 fn bit_reverse_range(self, start: u32, end: u32) -> Self;
190
191 /// Reverses the order of the bits in `self` from the `[start..=end]` checked range.
192 ///
193 /// Leaves the rest of the bits untouched.
194 /// # Errors
195 /// Returns [`IndexOutOfBounds`] if `start >= Self::BITS` || `end >= Self::BITS`
196 /// and [`MismatchedIndices`] if `start > end`.
197 fn bit_reverse_checked_range(self, start: u32, end: u32) -> Result<Self, MismatchedBounds>;
198
199 /* count */
200
201 /// Counts the number of 1s in `bits` from the `[start..=end]` range.
202 /// # Panics
203 /// Panics in debug if `start >= Self::BITS` || `end >= Self::BITS` || `start > end`.
204 #[must_use]
205 fn bit_count_ones_range(self, start: u32, end: u32) -> u32;
206
207 /// Counts the number of 1s in `bits` from the `[start..=end]` checked range.
208 /// # Errors
209 /// Returns [`IndexOutOfBounds`] if `start >= Self::BITS` || `end >= Self::BITS`
210 /// and [`MismatchedIndices`] if `start > end`.
211 fn bit_count_ones_checked_range(self, start: u32, end: u32) -> Result<u32, MismatchedBounds>;
212
213 /// Counts the number of 0s in `bits` from the `[start..=end]` range.
214 /// # Panics
215 /// Panics in debug if `start >= Self::BITS` || `end >= Self::BITS` || `start > end`.
216 #[must_use]
217 fn bit_count_zeros_range(self, start: u32, end: u32) -> u32;
218
219 /// Counts the number of 0s in `bits` from the `[start..=end]` checked range.
220 /// # Errors
221 /// Returns [`IndexOutOfBounds`] if `start >= Self::BITS` || `end >= Self::BITS`
222 /// and [`MismatchedIndices`] if `start > end`.
223 fn bit_count_zeros_checked_range(self, start: u32, end: u32) -> Result<u32, MismatchedBounds>;
224
225 /* find first */
226
227 /// Finds the index of the first 1 in `bits` from the `[start..=end]` range.
228 ///
229 /// Returns `None` if there are no bits set.
230 ///
231 /// The index is relative to the entire sequence of `bits`, not to the given `start`.
232 /// # Panics
233 /// Panics in debug if `start >= Self::BITS` || `end >= Self::BITS` || `start > end`.
234 #[must_use]
235 fn bit_find_first_one_range(self, start: u32, end: u32) -> Option<u32>;
236
237 /// Finds the index of the first 1 in `bits` from the `[start..=end]` checked range.
238 ///
239 /// Returns `None` if there are no bits set.
240 ///
241 /// The index is relative to the entire sequence of `bits`, not to the given `start`.
242 /// # Errors
243 /// Returns [`IndexOutOfBounds`] if `start >= Self::BITS` || `end >= Self::BITS`
244 /// and [`MismatchedIndices`] if `start > end`.
245 fn bit_find_first_one_checked_range(
246 self,
247 start: u32,
248 end: u32,
249 ) -> Result<Option<u32>, MismatchedBounds>;
250
251 /// Finds the index of the first 0 in `bits` from the `[start..=end]` range.
252 ///
253 /// Returns `None` if there are no bits unset.
254 ///
255 /// The index is relative to the entire sequence of `bits`, not to the given `start`.
256 /// # Panics
257 /// Panics in debug if `start >= Self::BITS` || `end >= Self::BITS` || `start > end`.
258 #[must_use]
259 fn bit_find_first_zero_range(self, start: u32, end: u32) -> Option<u32>;
260
261 /// Finds the index of the first 0 in `bits` from the `[start..=end]` checked range.
262 ///
263 /// Returns `None` if there are no bits unset.
264 ///
265 /// The index is relative to the entire sequence of `bits`, not to the given `start`.
266 /// # Errors
267 /// Returns [`IndexOutOfBounds`] if `start >= Self::BITS` || `end >= Self::BITS`
268 /// and [`MismatchedIndices`] if `start > end`.
269 fn bit_find_first_zero_checked_range(
270 self,
271 start: u32,
272 end: u32,
273 ) -> Result<Option<u32>, MismatchedBounds>;
274
275 /* find last */
276
277 /// Finds the index of the last 1 in `bits` from the `[start..=end]` range.
278 ///
279 /// Returns `None` if there are no bits set.
280 ///
281 /// The index is relative to the entire sequence of `bits`, not to the given `start`.
282 /// # Panics
283 /// Panics in debug if `start >= Self::BITS` || `end >= Self::BITS` || `start > end`.
284 #[must_use]
285 fn bit_find_last_one_range(self, start: u32, end: u32) -> Option<u32>;
286
287 /// Finds the index of the last 1 in `bits` from the `[start..=end]` checked range.
288 ///
289 /// Returns `None` if there are no bits set.
290 ///
291 /// The index is relative to the entire sequence of `bits`, not to the given `start`.
292 /// # Errors
293 /// Returns [`IndexOutOfBounds`] if `start >= Self::BITS` || `end >= Self::BITS`
294 /// and [`MismatchedIndices`] if `start > end`.
295 fn bit_find_last_one_checked_range(
296 self,
297 start: u32,
298 end: u32,
299 ) -> Result<Option<u32>, MismatchedBounds>;
300
301 /// Finds the index of the last 0 in `bits` from the `[start..=end]` range.
302 ///
303 /// Returns `None` if there are no bits unset.
304 ///
305 /// The index is relative to the entire sequence of `bits`, not to the given `start`.
306 /// # Panics
307 /// Panics in debug if `start >= Self::BITS` || `end >= Self::BITS` || `start > end`.
308 #[must_use]
309 fn bit_find_last_zero_range(self, start: u32, end: u32) -> Option<u32>;
310
311 /// Finds the index of the last 0 in `bits` from the `[start..=end]` checked range.
312 ///
313 /// Returns `None` if there are no bits unset.
314 ///
315 /// The index is relative to the entire sequence of `bits`, not to the given `start`.
316 /// # Errors
317 /// Returns [`IndexOutOfBounds`] if `start >= Self::BITS` || `end >= Self::BITS`
318 /// and [`MismatchedIndices`] if `start > end`.
319 fn bit_find_last_zero_checked_range(
320 self,
321 start: u32,
322 end: u32,
323 ) -> Result<Option<u32>, MismatchedBounds>;
324}
325
326macro_rules! impl_bit_ops {
327 () => {
328 impl_bit_ops![
329 i8:"_bit_i8", i16:"_bit_i16", i32:"_bit_i32",
330 i64:"_bit_i64", i128:"_bit_i128", isize:"_bit_isize",
331 u8:"_bit_u8", u16:"_bit_u16", u32:"_bit_u32",
332 u64:"_bit_u64", u128:"_bit_u128", usize:"_bit_usize"
333 ];
334 };
335
336 // `$t`: the type to implement the trait for.
337 // $cap: the capability feature that enables the given implementation. E.g "_bit_u8".
338 ($($t:ty : $cap:literal),+) => { $( impl_bit_ops![@$t:$cap]; )+ };
339 (@$t:ty : $cap:literal) => {
340 #[cfg(feature = $cap )]
341 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = $cap)))]
342 impl BitOps for $t {
343 type Inner = $t;
344
345 // new mask
346 fn bit_mask_range(start: u32, end: u32) -> Self {
347 Bitwise::<$t>::mask_range(start, end).0
348 }
349 fn bit_mask_checked_range(start: u32, end: u32) -> Result<Self, MismatchedBounds> {
350 Ok(Bitwise::<$t>::mask_checked_range(start, end)?.0)
351 }
352 // get
353 fn bit_get_range(self, start: u32, end: u32) -> Self {
354 Bitwise(self).get_range(start, end).0
355 }
356 fn bit_get_checked_range(self, start: u32, end: u32) -> Result<Self, MismatchedBounds> {
357 Ok(Bitwise(self).get_checked_range(start, end)?.0)
358 }
359 // get value
360 fn bit_get_value_range(self, start: u32, end: u32) -> Self {
361 Bitwise(self).get_value_range(start, end).0
362 }
363 fn bit_get_value_checked_range(self, start: u32, end: u32)
364 -> Result<Self, MismatchedBounds> {
365 Ok(Bitwise(self).get_value_checked_range(start, end)?.0)
366 }
367 // set
368 fn bit_set_range(self, start: u32, end: u32) -> Self {
369 Bitwise(self).set_range(start, end).0
370 }
371 fn bit_set_checked_range(self, start: u32, end: u32) -> Result<Self, MismatchedBounds> {
372 Ok(Bitwise(self).set_checked_range(start, end)?.0)
373 }
374 // set value
375 fn bit_set_value_range(self, value: Self::Inner, start: u32, end: u32) -> Self {
376 Bitwise(self).set_value_range(value, start, end).0
377 }
378 fn bit_set_value_checked_range(self, value: Self::Inner, start: u32, end: u32)
379 -> Result<Self, MismatchedBounds> {
380 Ok(Bitwise(self).set_value_checked_range(value, start, end)?.0)
381 }
382 fn bit_set_checked_value_checked_range(self, value: Self::Inner, start: u32, end: u32)
383 -> Result<Self, MismatchedBounds> {
384 Ok(Bitwise(self).set_checked_value_checked_range(value, start, end)?.0)
385 }
386 // unset
387 fn bit_unset_range(self, start: u32, end: u32) -> Self {
388 Bitwise(self).unset_range(start, end).0
389 }
390 fn bit_unset_checked_range(self, start: u32, end: u32)
391 -> Result<Self, MismatchedBounds> {
392 Ok(Bitwise(self).unset_checked_range(start, end)?.0)
393 }
394 // flip
395 fn bit_flip_range(self, start: u32, end: u32) -> Self {
396 Bitwise(self).flip_range(start, end).0
397 }
398 fn bit_flip_checked_range(self, start: u32, end: u32)
399 -> Result<Self, MismatchedBounds> {
400 Ok(Bitwise(self).flip_checked_range(start, end)?.0)
401 }
402 // reverse
403 fn bit_reverse_range(self, start: u32, end: u32) -> Self {
404 Bitwise(self).reverse_range(start, end).0
405 }
406 fn bit_reverse_checked_range(self, start: u32, end: u32)
407 -> Result<Self, MismatchedBounds> {
408 Ok(Bitwise(self).reverse_checked_range(start, end)?.0)
409 }
410 // count
411 fn bit_count_ones_range(self, start: u32, end: u32) -> u32 {
412 Bitwise(self).count_ones_range(start, end)
413 }
414 fn bit_count_ones_checked_range(self, start: u32, end: u32)
415 -> Result<u32, MismatchedBounds> {
416 Bitwise(self).count_ones_checked_range(start, end)
417 }
418 fn bit_count_zeros_range(self, start: u32, end: u32) -> u32 {
419 Bitwise(self).count_zeros_range(start, end)
420 }
421 fn bit_count_zeros_checked_range(self, start: u32, end: u32)
422 -> Result<u32, MismatchedBounds> {
423 Bitwise(self).count_zeros_checked_range(start, end)
424 }
425 // find first
426 fn bit_find_first_one_range(self, start: u32, end: u32) -> Option<u32> {
427 Bitwise(self).find_first_one_range(start, end)
428 }
429 fn bit_find_first_one_checked_range(self, start: u32, end: u32)
430 -> Result<Option<u32>, MismatchedBounds> {
431 Bitwise(self).find_first_one_checked_range(start, end)
432 }
433 fn bit_find_first_zero_range(self, start: u32, end: u32) -> Option<u32> {
434 Bitwise(self).find_first_zero_range(start, end)
435 }
436 fn bit_find_first_zero_checked_range(self, start: u32, end: u32)
437 -> Result<Option<u32>, MismatchedBounds> {
438 Bitwise(self).find_first_zero_checked_range(start, end)
439 }
440 // find last
441 fn bit_find_last_one_range(self, start: u32, end: u32) -> Option<u32> {
442 Bitwise(self).find_last_one_range(start, end)
443 }
444 fn bit_find_last_one_checked_range(self, start: u32, end: u32)
445 -> Result<Option<u32>, MismatchedBounds> {
446 Bitwise(self).find_last_one_checked_range(start, end)
447 }
448 fn bit_find_last_zero_range(self, start: u32, end: u32) -> Option<u32> {
449 Bitwise(self).find_last_zero_range(start, end)
450 }
451 fn bit_find_last_zero_checked_range(self, start: u32, end: u32)
452 -> Result<Option<u32>, MismatchedBounds> {
453 Bitwise(self).find_last_zero_checked_range(start, end)
454 }
455 }
456 };
457}
458impl_bit_ops![];