Skip to main content

mdarray/expr/
into_expr.rs

1use core::fmt::{Debug, Formatter, Result};
2use core::mem::ManuallyDrop;
3use core::ptr;
4
5use crate::buffer::Buffer;
6use crate::expr::expression::Expression;
7use crate::expr::iter::Iter;
8use crate::slice::Slice;
9
10/// Expression that moves elements out of an array.
11pub struct IntoExpr<T, B: Buffer<Item = ManuallyDrop<T>>> {
12    buffer: B,
13    index: usize,
14}
15
16impl<T, B: Buffer<Item = ManuallyDrop<T>>> IntoExpr<T, B> {
17    /// Creates an expression from an array buffer.
18    #[inline]
19    pub fn new(buffer: B) -> Self {
20        Self { buffer, index: 0 }
21    }
22}
23
24impl<T, B: Buffer<Item = ManuallyDrop<T>>> AsMut<Slice<T, B::Shape>> for IntoExpr<T, B> {
25    #[inline]
26    fn as_mut(&mut self) -> &mut Slice<T, B::Shape> {
27        debug_assert!(self.index == 0, "expression in use");
28
29        unsafe {
30            &mut *(self.buffer.as_mut_slice() as *mut Slice<ManuallyDrop<T>, B::Shape>
31                as *mut Slice<T, B::Shape>)
32        }
33    }
34}
35
36impl<T, B: Buffer<Item = ManuallyDrop<T>>> AsRef<Slice<T, B::Shape>> for IntoExpr<T, B> {
37    #[inline]
38    fn as_ref(&self) -> &Slice<T, B::Shape> {
39        debug_assert!(self.index == 0, "expression in use");
40
41        unsafe {
42            &*(self.buffer.as_slice() as *const Slice<ManuallyDrop<T>, B::Shape>
43                as *const Slice<T, B::Shape>)
44        }
45    }
46}
47
48impl<T, B: Buffer<Item = ManuallyDrop<T>> + Clone> Clone for IntoExpr<T, B> {
49    #[inline]
50    fn clone(&self) -> Self {
51        assert!(self.index == 0, "expression in use");
52
53        Self { buffer: self.buffer.clone(), index: 0 }
54    }
55
56    #[inline]
57    fn clone_from(&mut self, source: &Self) {
58        assert!(self.index == 0 && source.index == 0, "expression in use");
59
60        self.buffer.clone_from(&source.buffer);
61    }
62}
63
64impl<T: Debug, B: Buffer<Item = ManuallyDrop<T>>> Debug for IntoExpr<T, B> {
65    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
66        f.debug_tuple("IntoExpr").field(&self.as_ref()).finish()
67    }
68}
69
70impl<T, B: Buffer<Item = ManuallyDrop<T>> + Default> Default for IntoExpr<T, B> {
71    #[inline]
72    fn default() -> Self {
73        Self { buffer: Default::default(), index: 0 }
74    }
75}
76
77impl<T, B: Buffer<Item = ManuallyDrop<T>>> Drop for IntoExpr<T, B> {
78    #[inline]
79    fn drop(&mut self) {
80        unsafe {
81            let ptr = self.buffer.as_mut_slice().as_mut_ptr().add(self.index) as *mut T;
82            let len = self.buffer.as_slice().len() - self.index;
83
84            ptr::slice_from_raw_parts_mut(ptr, len).drop_in_place();
85        }
86    }
87}
88
89impl<T, B: Buffer<Item = ManuallyDrop<T>>> Expression for IntoExpr<T, B> {
90    type Shape = B::Shape;
91
92    const IS_REPEATABLE: bool = false;
93
94    #[inline]
95    fn shape(&self) -> &B::Shape {
96        self.buffer.as_slice().shape()
97    }
98
99    #[inline]
100    unsafe fn get_unchecked(&mut self, _: usize) -> T {
101        debug_assert!(self.index < self.buffer.as_slice().len(), "index out of bounds");
102
103        self.index += 1; // Keep track of that the element is moved out.
104
105        unsafe {
106            ManuallyDrop::take(&mut *self.buffer.as_mut_slice().as_mut_ptr().add(self.index - 1))
107        }
108    }
109
110    #[inline]
111    fn inner_rank(&self) -> usize {
112        usize::MAX
113    }
114
115    #[inline]
116    unsafe fn reset_dim(&mut self, _: usize, _: usize) {}
117
118    #[inline]
119    unsafe fn step_dim(&mut self, _: usize) {}
120}
121
122impl<T, B: Buffer<Item = ManuallyDrop<T>>> IntoIterator for IntoExpr<T, B> {
123    type Item = T;
124    type IntoIter = Iter<Self>;
125
126    #[inline]
127    fn into_iter(self) -> Iter<Self> {
128        Iter::new(self)
129    }
130}