Skip to content

Commit 2778c54

Browse files
committed
Add generic alias
1 parent 219b405 commit 2778c54

File tree

2 files changed

+81
-52
lines changed

2 files changed

+81
-52
lines changed

src/collections/array_set.rs

Lines changed: 46 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,17 @@
1-
use core::{cmp::Ordering, mem::size_of, ops::Deref, ptr::copy};
1+
use core::{
2+
cmp::Ordering,
3+
mem::size_of,
4+
ops::{AddAssign, Deref, SubAssign},
5+
ptr::copy,
6+
};
27

38
use crate::{
49
error::{Result, TranslationError},
510
from_bytes::{FromBytes, FromBytesMut},
611
transmute::{cast_slice_unchecked, cast_slice_unchecked_mut, Transmute},
12+
types::{ToUsize, Unit},
713
};
814

9-
pub trait Prefix: Transmute {
10-
fn as_usize(&self) -> usize;
11-
12-
fn decrement(&mut self);
13-
14-
fn increment(&mut self);
15-
}
16-
17-
// Convenience macro to implement the `Prefix` trait for common numeric types.
18-
macro_rules! impl_prefix {
19-
( $($type:ty),* ) => {
20-
$(
21-
impl Prefix for $type {
22-
#[inline(always)]
23-
fn as_usize(&self) -> usize {
24-
*self as usize
25-
}
26-
27-
#[inline(always)]
28-
fn decrement(&mut self) {
29-
*self -= 1;
30-
}
31-
32-
#[inline(always)]
33-
fn increment(&mut self) {
34-
*self += 1;
35-
}
36-
}
37-
)*
38-
};
39-
}
40-
41-
// Implement the `Transmute` trait for common numeric types.
42-
impl_prefix!(u8, u16, u32, u64, u128, usize);
43-
4415
/// A set-like type that stores elements in a sorted array.
4516
///
4617
/// It requires that the elements implement the `Ord` trait. It is a logic error
@@ -54,7 +25,7 @@ impl_prefix!(u8, u16, u32, u64, u128, usize);
5425
/// aborts, memory leaks, and non-termination.
5526
pub struct ArraySet<'a, P, V>
5627
where
57-
P: Prefix,
28+
P: AddAssign<P> + SubAssign<P> + ToUsize + Transmute + Unit,
5829
V: Clone + Copy + Default + PartialOrd + Transmute,
5930
{
6031
/// Number of elements in the array
@@ -71,7 +42,7 @@ macro_rules! readonly_impl {
7142
( $name:tt ) => {
7243
impl<'a, P, V> $name<'a, P, V>
7344
where
74-
P: Prefix,
45+
P: AddAssign<P> + SubAssign<P> + ToUsize + Transmute + Unit,
7546
V: Clone + Copy + Default + Ord + PartialOrd + Transmute,
7647
{
7748
/// Returns true if the set contains a value.
@@ -107,7 +78,7 @@ macro_rules! readonly_impl {
10778

10879
#[inline(always)]
10980
pub fn len(&self) -> usize {
110-
self.length.as_usize()
81+
self.length.to_usize()
11182
}
11283

11384
/// Returns the index of the value in the array.
@@ -127,7 +98,7 @@ macro_rules! readonly_impl {
12798
}
12899

129100
let mut start = 0;
130-
let mut end = self.length.as_usize() - 1;
101+
let mut end = self.length.to_usize() - 1;
131102

132103
while start <= end {
133104
let middle = start + (end.saturating_sub(start) / 2);
@@ -158,7 +129,7 @@ macro_rules! readonly_impl {
158129

159130
impl<'a, P, V> Deref for $name<'a, P, V>
160131
where
161-
P: Prefix,
132+
P: AddAssign<P> + SubAssign<P> + ToUsize + Transmute + Unit,
162133
V: Clone + Copy + Default + Ord + PartialOrd + Transmute,
163134
{
164135
type Target = [V];
@@ -173,7 +144,7 @@ macro_rules! readonly_impl {
173144
/// A mutable set-like type that stores elements in a sorted array.
174145
pub struct ArraySetMut<'a, P, V>
175146
where
176-
P: Prefix,
147+
P: AddAssign<P> + SubAssign<P> + ToUsize + Transmute + Unit,
177148
V: Default + Copy + Clone + Ord + Transmute,
178149
{
179150
/// Number of elements in the array
@@ -187,7 +158,7 @@ where
187158

188159
impl<P, V> ArraySetMut<'_, P, V>
189160
where
190-
P: Prefix,
161+
P: AddAssign<P> + SubAssign<P> + ToUsize + Transmute + Unit,
191162
V: Default + Copy + Clone + Ord + Transmute,
192163
{
193164
/// Returns a mutable reference to the value in the set, if any, that is equal to the
@@ -232,7 +203,7 @@ where
232203
}
233204
// insert the new value
234205
self.values[index] = value;
235-
self.length.increment();
206+
*self.length += P::UNIT;
236207
return true;
237208
}
238209

@@ -271,7 +242,7 @@ where
271242
copy(src_ptr, dest_ptr, self.values.len() - (index + 1));
272243
}
273244
}
274-
self.length.decrement();
245+
*self.length -= P::UNIT;
275246
return Some(value);
276247
}
277248

@@ -281,7 +252,7 @@ where
281252

282253
unsafe impl<'a, P, V> FromBytes<'a> for ArraySet<'a, P, V>
283254
where
284-
P: Prefix,
255+
P: AddAssign<P> + SubAssign<P> + ToUsize + Transmute + Unit,
285256
V: Default + Copy + Clone + Ord + Transmute,
286257
{
287258
/// Loads a sorted array from its byte representation.
@@ -315,7 +286,7 @@ where
315286

316287
unsafe impl<'a, P, V> FromBytesMut<'a> for ArraySetMut<'a, P, V>
317288
where
318-
P: Prefix,
289+
P: AddAssign<P> + SubAssign<P> + ToUsize + Transmute + Unit,
319290
V: Default + Copy + Clone + Ord + Transmute,
320291
{
321292
/// Loads a sorted array from its byte representation.
@@ -350,6 +321,30 @@ where
350321
readonly_impl!(ArraySet);
351322
readonly_impl!(ArraySetMut);
352323

324+
/// Type alias for an `ArraySet` with `u8` as length type.
325+
pub type U8ArraySet<'a, V> = ArraySet<'a, u8, V>;
326+
327+
/// Type alias for an `ArraySet` with `u16` as length type.
328+
pub type U16ArraySet<'a, V> = ArraySet<'a, u16, V>;
329+
330+
/// Type alias for an `ArraySet` with `u32` as length type.
331+
pub type U32ArraySet<'a, V> = ArraySet<'a, u32, V>;
332+
333+
/// Type alias for an `ArraySet` with `u64` as length type.
334+
pub type U64ArraySet<'a, V> = ArraySet<'a, u64, V>;
335+
336+
/// Type alias for an `ArraySetMut` with `u8` as length type.
337+
pub type U8ArraySetMut<'a, V> = ArraySetMut<'a, u8, V>;
338+
339+
/// Type alias for an `ArraySetMut` with `u16` as length type.
340+
pub type U16ArraySetMut<'a, V> = ArraySetMut<'a, u16, V>;
341+
342+
/// Type alias for an `ArraySetMut` with `u32` as length type.
343+
pub type U32ArraySetMut<'a, V> = ArraySetMut<'a, u32, V>;
344+
345+
/// Type alias for an `ArraySetMut` with `u64` as length type.
346+
pub type U64ArraySetMut<'a, V> = ArraySetMut<'a, u64, V>;
347+
353348
#[cfg(test)]
354349
mod tests {
355350
use core::slice::from_raw_parts_mut;
@@ -361,15 +356,15 @@ mod tests {
361356
let mut array = [0u64; size_of::<u64>() * 3];
362357
// Ensure that `bytes` has 8-byte alignment.
363358
let bytes = unsafe { from_raw_parts_mut(array.as_mut_ptr() as *mut u8, 18) };
364-
let mut set = unsafe { ArraySetMut::<u64, u8>::from_bytes_unchecked_mut(bytes) };
359+
let mut set = unsafe { U64ArraySetMut::<u8>::from_bytes_unchecked_mut(bytes) };
365360

366361
set.insert(10);
367362
set.insert(1);
368363
set.insert(2);
369364
set.insert(7);
370365
set.insert(4);
371366

372-
let set = unsafe { ArraySet::<u64, u8>::from_bytes_unchecked(bytes) };
367+
let set = unsafe { U64ArraySet::<u8>::from_bytes_unchecked(bytes) };
373368
assert_eq!(set.len(), 5);
374369
assert_eq!(&*set, &[1, 2, 4, 7, 10]);
375370

@@ -379,7 +374,7 @@ mod tests {
379374
#[test]
380375
fn test_remove() {
381376
let mut bytes = [0; size_of::<u8>() + 10 * size_of::<u8>()];
382-
let mut set = unsafe { ArraySetMut::<u8, u8>::from_bytes_unchecked_mut(&mut bytes) };
377+
let mut set = unsafe { U8ArraySetMut::<u8>::from_bytes_unchecked_mut(&mut bytes) };
383378

384379
set.insert(1);
385380
set.insert(10);
@@ -409,7 +404,7 @@ mod tests {
409404
#[test]
410405
fn test_get() {
411406
let mut bytes = [0; size_of::<u8>() + 10 * size_of::<u8>()];
412-
let mut set = unsafe { ArraySetMut::<u8, u8>::from_bytes_unchecked_mut(&mut bytes) };
407+
let mut set = unsafe { U8ArraySetMut::<u8>::from_bytes_unchecked_mut(&mut bytes) };
413408

414409
set.insert(1);
415410
set.insert(10);

src/types/mod.rs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ pub use str::Str;
99
use crate::{nullable::Nullable, transmute::Transmute};
1010

1111
// Implement `Transmute` and `Nullable` for unsigned integer
12-
// assay types.
12+
// array types.
1313
macro_rules! transmute_unsigned_array_type {
1414
( $type:tt ) => {
1515
unsafe impl<const N: usize> Transmute for [$type; N] {}
@@ -25,6 +25,40 @@ transmute_unsigned_array_type!(u16);
2525
transmute_unsigned_array_type!(u32);
2626
transmute_unsigned_array_type!(u64);
2727

28+
/// A trait for converting a value to `usize`.
29+
///
30+
/// This trait is implemented for primitive integer types,
31+
/// which can be used as generic parameters where a numeric
32+
/// value is needed to represent sizes or counts.
33+
pub trait ToUsize {
34+
fn to_usize(&self) -> usize;
35+
}
36+
37+
/// A trait representing a unit value for a type.
38+
pub trait Unit {
39+
const UNIT: Self;
40+
}
41+
42+
// Implement `ToUsize` and `Unit` for unsigned integer types.
43+
macro_rules! as_usize_and_unit_for_unsigned_type {
44+
( $type:tt ) => {
45+
impl ToUsize for $type {
46+
fn to_usize(&self) -> usize {
47+
*self as usize
48+
}
49+
}
50+
51+
impl Unit for $type {
52+
const UNIT: Self = 1;
53+
}
54+
};
55+
}
56+
57+
as_usize_and_unit_for_unsigned_type!(u8);
58+
as_usize_and_unit_for_unsigned_type!(u16);
59+
as_usize_and_unit_for_unsigned_type!(u32);
60+
as_usize_and_unit_for_unsigned_type!(u64);
61+
2862
#[cfg(test)]
2963
mod tests {
3064
use core::slice::from_raw_parts;

0 commit comments

Comments
 (0)