Skip to content

Commit

Permalink
IArray: avoid heap allocation if there is only one element
Browse files Browse the repository at this point in the history
  • Loading branch information
cecton committed Oct 28, 2023
1 parent cba5148 commit 724db78
Showing 1 changed file with 45 additions and 1 deletion.
46 changes: 45 additions & 1 deletion src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ pub enum IArray<T: ImplicitClone + 'static> {
Static(&'static [T]),
/// A reference counted slice.
Rc(Rc<[T]>),
/// A single element.
Single([T; 1]),
}

// TODO add insta tests
Expand All @@ -21,6 +23,7 @@ impl<T: fmt::Debug + ImplicitClone + 'static> fmt::Debug for IArray<T> {
match self {
Self::Static(a) => a.fmt(f),
Self::Rc(a) => a.fmt(f),
Self::Single(x) => x.fmt(f),
}
}
}
Expand All @@ -30,6 +33,7 @@ impl<T: ImplicitClone + 'static> Clone for IArray<T> {
match self {
Self::Static(a) => Self::Static(a),
Self::Rc(a) => Self::Rc(a.clone()),
Self::Single(x) => Self::Single(x.clone()),
}
}
}
Expand Down Expand Up @@ -67,6 +71,18 @@ impl<T: ImplicitClone + 'static> From<Rc<[T]>> for IArray<T> {
}
}

impl<T: ImplicitClone + 'static> From<T> for IArray<T> {
fn from(x: T) -> IArray<T> {
IArray::Single([x])
}
}

impl<T: ImplicitClone + 'static> From<[T; 1]> for IArray<T> {
fn from(a: [T; 1]) -> IArray<T> {
IArray::Single(a)
}
}

impl<T: ImplicitClone + 'static> IArray<T> {
/// Returns an iterator over the slice.
///
Expand All @@ -87,6 +103,7 @@ impl<T: ImplicitClone + 'static> IArray<T> {
match self {
Self::Static(a) => a.iter().cloned(),
Self::Rc(a) => a.iter().cloned(),
Self::Single(a) => a.iter().cloned(),
}
}

Expand All @@ -105,6 +122,7 @@ impl<T: ImplicitClone + 'static> IArray<T> {
match self {
Self::Static(a) => a.len(),
Self::Rc(a) => a.len(),
Self::Single(_) => 1,
}
}

Expand All @@ -125,6 +143,7 @@ impl<T: ImplicitClone + 'static> IArray<T> {
match self {
Self::Static(a) => a.is_empty(),
Self::Rc(a) => a.is_empty(),
Self::Single(_) => false,
}
}

Expand All @@ -145,6 +164,7 @@ impl<T: ImplicitClone + 'static> IArray<T> {
match self {
Self::Static(a) => a,
Self::Rc(a) => a,
Self::Single(a) => a,
}
}

Expand All @@ -163,6 +183,8 @@ impl<T: ImplicitClone + 'static> IArray<T> {
match self {
Self::Static(a) => a.get(index).cloned(),
Self::Rc(a) => a.get(index).cloned(),
Self::Single(a) if index == 0 => Some(a[0].clone()),
Self::Single(_) => None,
}
}

Expand Down Expand Up @@ -194,7 +216,7 @@ impl<T: ImplicitClone + 'static> IArray<T> {
pub fn get_mut(&mut self) -> Option<&mut [T]> {
match self {
Self::Rc(ref mut rc) => Rc::get_mut(rc),
Self::Static(_) => None,
Self::Static(_) | Self::Single(_) => None,
}
}

Expand Down Expand Up @@ -238,6 +260,13 @@ impl<T: ImplicitClone + 'static> IArray<T> {
_ => unreachable!(),
}
}
Self::Single(slice) => {
*self = Self::Rc(slice.iter().cloned().collect());
match self {
Self::Rc(rc) => Rc::get_mut(rc).unwrap(),
_ => unreachable!(),
}
}
}
}
}
Expand All @@ -250,6 +279,8 @@ where
match self {
Self::Static(a) => a.eq(other),
Self::Rc(a) => a.eq(*other),
Self::Single(a) if N == 1 => a[0].eq(&other[0]),
Self::Single(_) => false,
}
}
}
Expand All @@ -262,6 +293,8 @@ where
match self {
Self::Static(a) => a.eq(other),
Self::Rc(a) => a.eq(other),
Self::Single(a) if N == 1 => a[0].eq(&other[0]),
Self::Single(_) => false,
}
}
}
Expand All @@ -274,6 +307,7 @@ where
match self {
Self::Static(a) => a.eq(&other),
Self::Rc(a) => a.eq(other),
Self::Single(a) => a.eq(other),
}
}
}
Expand All @@ -286,6 +320,7 @@ where
match self {
Self::Static(a) => a.eq(other),
Self::Rc(a) => a.eq(*other),
Self::Single(a) => a.eq(*other),
}
}
}
Expand Down Expand Up @@ -356,4 +391,13 @@ mod test_array {
const _ARRAY_F32: IArray<f32> = IArray::Static(&[]);
const _ARRAY_F64: IArray<f64> = IArray::Static(&[]);
}

#[test]
fn from() {
let _array: IArray<u32> = IArray::from(&[1, 2, 3][..]);
let _array: IArray<u32> = IArray::from(vec![1, 2, 3]);
let _array: IArray<u32> = IArray::from(Rc::from(vec![1, 2, 3]));
let _array: IArray<u32> = IArray::from(1);
let _array: IArray<u32> = IArray::from([1]);
}
}

0 comments on commit 724db78

Please sign in to comment.