reimplement RocList and RocStr

This commit is contained in:
Tom Dohrmann 2022-02-23 14:49:10 +01:00
parent 16e568be76
commit 788c8a6af2
19 changed files with 680 additions and 792 deletions

100
roc_std/src/rc.rs Normal file
View file

@ -0,0 +1,100 @@
/// A type which uses reference counting for it's heap allocated memory.
///
/// Note that if a type doesn't allocate any heap memory (eg. `i32`), the
/// `increment` and `decrement` methods don't need to do anything.
///
/// # Safety
///
/// It must be safe to memcpy this type to a new location after the reference count has been increased.
pub unsafe trait ReferenceCount {
/// Increment the reference count.
fn increment(&self);
/// Decrement the reference count.
///
/// # Safety
///
/// The caller must ensure that `ptr` points to a value with a non-zero
/// reference count.
unsafe fn decrement(ptr: *const Self);
}
macro_rules! impl_reference_count_for_primitive {
($ty:ty) => {
unsafe impl ReferenceCount for $ty {
fn increment(&self) {
// Do nothing.
}
unsafe fn decrement(_ptr: *const Self) {
// Do nothing.
}
}
};
}
impl_reference_count_for_primitive!(bool);
impl_reference_count_for_primitive!(char);
impl_reference_count_for_primitive!(u8);
impl_reference_count_for_primitive!(i8);
impl_reference_count_for_primitive!(u16);
impl_reference_count_for_primitive!(i16);
impl_reference_count_for_primitive!(u32);
impl_reference_count_for_primitive!(i32);
impl_reference_count_for_primitive!(u64);
impl_reference_count_for_primitive!(i64);
impl_reference_count_for_primitive!(u128);
impl_reference_count_for_primitive!(i128);
impl_reference_count_for_primitive!(f32);
impl_reference_count_for_primitive!(f64);
macro_rules! impl_reference_count_for_tuple {
($($ty:ident: $field:tt,)*) => {
unsafe impl<$($ty),*> ReferenceCount for ($($ty,)*)
where
$($ty: ReferenceCount,)*
{
fn increment(&self) {
$(self.$field.increment();)*
}
#[allow(unused_variables, clippy::unused_unit)]
unsafe fn decrement(ptr: *const Self) {
let ptrs = {
let this = &*ptr;
($(core::ptr::addr_of!(this.$field),)*)
};
$($ty::decrement(ptrs.$field);)*
}
}
};
}
impl_reference_count_for_tuple!();
impl_reference_count_for_tuple!(A: 0,);
impl_reference_count_for_tuple!(A: 0, B: 1,);
impl_reference_count_for_tuple!(A: 0, B: 1, C: 2,);
impl_reference_count_for_tuple!(A: 0, B: 1, C: 2, D: 3,);
impl_reference_count_for_tuple!(A: 0, B: 1, C: 2, D: 3, E: 4,);
impl_reference_count_for_tuple!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5,);
impl_reference_count_for_tuple!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6,);
impl_reference_count_for_tuple!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7,);
impl_reference_count_for_tuple!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7, I: 8,);
impl_reference_count_for_tuple!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7, I: 8, J: 9,);
impl_reference_count_for_tuple!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7, I: 8, J: 9, K: 10,);
impl_reference_count_for_tuple!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7, I: 8, J: 9, K: 10, L: 11,);
unsafe impl<T, const N: usize> ReferenceCount for [T; N]
where
T: ReferenceCount,
{
fn increment(&self) {
self.iter().for_each(T::increment)
}
unsafe fn decrement(ptr: *const Self) {
for i in 0..N {
T::decrement(ptr.cast::<T>().add(i));
}
}
}