From 8fcdf9674b99f0fcde78d52d0f14da2491271ed2 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Tue, 6 May 2014 21:16:58 -0700 Subject: [PATCH] Remove transmute_mut calls in types::array There are transmute calls inside of match blocks that I don't think should be necessary but I can't figure out how to get rid of them right now. --- src/types/array.rs | 129 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 111 insertions(+), 18 deletions(-) diff --git a/src/types/array.rs b/src/types/array.rs index 14fe14c2..c80157d1 100644 --- a/src/types/array.rs +++ b/src/types/array.rs @@ -40,9 +40,7 @@ pub trait MutableArray : Array { /// # Failure /// /// Fails if the array is one-dimensional or the index is out of bounds. - fn slice_mut<'a>(&'a mut self, idx: int) -> MutArraySlice<'a, T> { - MutArraySlice { slice: self.slice(idx) } - } + fn slice_mut<'a>(&'a mut self, idx: int) -> MutArraySlice<'a, T>; /// Retrieves a mutable reference to a value in this array. /// @@ -50,13 +48,11 @@ pub trait MutableArray : Array { /// # Failure /// /// Fails if the array is multi-dimensional or the index is out of bounds. - fn get_mut<'a>(&'a mut self, idx: int) -> &'a mut T { - unsafe { cast::transmute_mut(self.get(idx)) } - } + fn get_mut<'a>(&'a mut self, idx: int) -> &'a mut T; } #[doc(hidden)] -trait InternalArray : Array { +trait InternalArray: Array { fn shift_idx(&self, idx: int) -> uint { let shifted_idx = idx - self.dimension_info()[0].lower_bound; assert!(shifted_idx >= 0 && @@ -68,6 +64,11 @@ trait InternalArray : Array { fn raw_get<'a>(&'a self, idx: uint, size: uint) -> &'a T; } +#[doc(hidden)] +trait InternalMutableArray: MutableArray { + fn raw_get_mut<'a>(&'a mut self, idx: uint, size: uint) -> &'a mut T; +} + /// A multi-dimensional array #[deriving(Eq, Clone)] pub struct ArrayBase { @@ -159,7 +160,7 @@ impl Array for ArrayBase { "Attempted to slice a one-dimensional array"); ArraySlice { parent: BaseParent(self), - idx: self.shift_idx(idx) + idx: self.shift_idx(idx), } } @@ -170,7 +171,23 @@ impl Array for ArrayBase { } } -impl MutableArray for ArrayBase {} +impl MutableArray for ArrayBase { + fn slice_mut<'a>(&'a mut self, idx: int) -> MutArraySlice<'a, T> { + assert!(self.info.len() != 1, + "Attempted to slice_mut into a one-dimensional array"); + MutArraySlice { + idx: self.shift_idx(idx), + parent: MutBaseParent(self), + } + } + + fn get_mut<'a>(&'a mut self, idx: int) -> &'a mut T { + assert!(self.info.len() == 1, + "Attempted to get_mut from a multi-dimensional array"); + let idx = self.shift_idx(idx); + self.raw_get_mut(idx, 1) + } +} impl InternalArray for ArrayBase { fn raw_get<'a>(&'a self, idx: uint, _size: uint) -> &'a T { @@ -178,8 +195,15 @@ impl InternalArray for ArrayBase { } } +impl InternalMutableArray for ArrayBase { + fn raw_get_mut<'a>(&'a mut self, idx: uint, _size: uint) -> &'a mut T { + self.data.get_mut(idx) + } +} + enum ArrayParent<'parent, T> { - SliceParent(&'parent ArraySlice<'parent, T>), + SliceParent(&'parent ArraySlice<'static, T>), + MutSliceParent(&'parent MutArraySlice<'static, T>), BaseParent(&'parent ArrayBase), } @@ -193,6 +217,7 @@ impl<'parent, T> Array for ArraySlice<'parent, T> { fn dimension_info<'a>(&'a self) -> &'a [DimensionInfo] { let info = match self.parent { SliceParent(p) => p.dimension_info(), + MutSliceParent(p) => p.dimension_info(), BaseParent(p) => p.dimension_info() }; info.slice_from(1) @@ -201,9 +226,11 @@ impl<'parent, T> Array for ArraySlice<'parent, T> { fn slice<'a>(&'a self, idx: int) -> ArraySlice<'a, T> { assert!(self.dimension_info().len() != 1, "Attempted to slice a one-dimensional array"); - ArraySlice { - parent: SliceParent(self), - idx: self.shift_idx(idx) + unsafe { + ArraySlice { + parent: SliceParent(cast::transmute(self)), + idx: self.shift_idx(idx), + } } } @@ -220,31 +247,97 @@ impl<'parent, T> InternalArray for ArraySlice<'parent, T> { let idx = size * self.idx + idx; match self.parent { SliceParent(p) => p.raw_get(idx, size), + MutSliceParent(p) => p.raw_get(idx, size), BaseParent(p) => p.raw_get(idx, size) } } } +enum MutArrayParent<'parent, T> { + MutSliceMutParent(&'parent mut MutArraySlice<'static, T>), + MutBaseParent(&'parent mut ArrayBase), +} + /// A mutable slice of a multi-dimensional array pub struct MutArraySlice<'parent, T> { - slice: ArraySlice<'parent, T> + parent: MutArrayParent<'parent, T>, + idx: uint, } impl<'parent, T> Array for MutArraySlice<'parent, T> { fn dimension_info<'a>(&'a self) -> &'a [DimensionInfo] { - self.slice.dimension_info() + let info : &'a [DimensionInfo] = unsafe { + match self.parent { + MutSliceMutParent(ref p) => cast::transmute(p.dimension_info()), + MutBaseParent(ref p) => cast::transmute(p.dimension_info()), + } + }; + info.slice_from(1) } fn slice<'a>(&'a self, idx: int) -> ArraySlice<'a, T> { - self.slice.slice(idx) + assert!(self.dimension_info().len() != 1, + "Attempted to slice a one-dimensional array"); + unsafe { + ArraySlice { + parent: MutSliceParent(cast::transmute(self)), + idx: self.shift_idx(idx), + } + } } fn get<'a>(&'a self, idx: int) -> &'a T { - self.slice.get(idx) + assert!(self.dimension_info().len() == 1, + "Attempted to get from a multi-dimensional array"); + self.raw_get(self.shift_idx(idx), 1) } } -impl<'parent, T> MutableArray for MutArraySlice<'parent, T> {} +impl<'parent, T> MutableArray for MutArraySlice<'parent, T> { + fn slice_mut<'a>(&'a mut self, idx: int) -> MutArraySlice<'a, T> { + assert!(self.dimension_info().len() != 1, + "Attempted to slice_mut a one-dimensional array"); + unsafe { + MutArraySlice { + idx: self.shift_idx(idx), + parent: MutSliceMutParent(cast::transmute(self)), + } + } + } + + fn get_mut<'a>(&'a mut self, idx: int) -> &'a mut T { + assert!(self.dimension_info().len() == 1, + "Attempted to get_mut from a multi-dimensional array"); + let idx = self.shift_idx(idx); + self.raw_get_mut(idx, 1) + } +} + +impl<'parent, T> InternalArray for MutArraySlice<'parent, T> { + fn raw_get<'a>(&'a self, idx: uint, size: uint) -> &'a T { + let size = size * self.dimension_info()[0].len; + let idx = size * self.idx + idx; + unsafe { + match self.parent { + MutSliceMutParent(ref p) => cast::transmute(p.raw_get(idx, size)), + MutBaseParent(ref p) => cast::transmute(p.raw_get(idx, size)) + } + } + } +} + +impl<'parent, T> InternalMutableArray for MutArraySlice<'parent, T> { + fn raw_get_mut<'a>(&'a mut self, idx: uint, size: uint) -> &'a mut T { + let size = size * self.dimension_info()[0].len; + let idx = size * self.idx + idx; + unsafe { + match self.parent { + MutSliceMutParent(ref mut p) => cast::transmute(p.raw_get_mut(idx, size)), + MutBaseParent(ref mut p) => cast::transmute(p.raw_get_mut(idx, size)) + } + } + } +} #[cfg(test)] mod tests {