1use crate::element_op::Identity;
9use crate::view::validate_bounds;
10use crate::{Result, StridedView, StridedViewMut};
11
12#[derive(Clone, Copy, Debug)]
18pub struct RawStridedRef<'a, T> {
19 data: &'a [T],
20 dims: &'a [usize],
21 strides: &'a [isize],
22 offset: isize,
23}
24
25impl<'a, T> RawStridedRef<'a, T> {
26 pub fn new(
28 data: &'a [T],
29 dims: &'a [usize],
30 strides: &'a [isize],
31 offset: isize,
32 ) -> Result<Self> {
33 validate_bounds(data.len(), dims, strides, offset)?;
34 Ok(Self {
35 data,
36 dims,
37 strides,
38 offset,
39 })
40 }
41
42 pub unsafe fn new_unchecked(
48 data: &'a [T],
49 dims: &'a [usize],
50 strides: &'a [isize],
51 offset: isize,
52 ) -> Self {
53 Self {
54 data,
55 dims,
56 strides,
57 offset,
58 }
59 }
60
61 #[inline]
62 pub fn data(&self) -> &'a [T] {
63 self.data
64 }
65
66 #[inline]
67 pub fn dims(&self) -> &'a [usize] {
68 self.dims
69 }
70
71 #[inline]
72 pub fn strides(&self) -> &'a [isize] {
73 self.strides
74 }
75
76 #[inline]
77 pub fn offset(&self) -> isize {
78 self.offset
79 }
80
81 #[inline]
82 pub fn ptr(&self) -> *const T {
83 unsafe { self.data.as_ptr().offset(self.offset) }
84 }
85
86 #[inline]
91 pub fn as_view(&self) -> StridedView<'a, T, Identity> {
92 unsafe { StridedView::new_unchecked(self.data, self.dims, self.strides, self.offset) }
93 }
94}
95
96#[derive(Debug)]
101pub struct RawStridedMut<'a, T> {
102 data: &'a mut [T],
103 dims: &'a [usize],
104 strides: &'a [isize],
105 offset: isize,
106}
107
108impl<'a, T> RawStridedMut<'a, T> {
109 pub fn new(
111 data: &'a mut [T],
112 dims: &'a [usize],
113 strides: &'a [isize],
114 offset: isize,
115 ) -> Result<Self> {
116 validate_bounds(data.len(), dims, strides, offset)?;
117 Ok(Self {
118 data,
119 dims,
120 strides,
121 offset,
122 })
123 }
124
125 pub unsafe fn new_unchecked(
131 data: &'a mut [T],
132 dims: &'a [usize],
133 strides: &'a [isize],
134 offset: isize,
135 ) -> Self {
136 Self {
137 data,
138 dims,
139 strides,
140 offset,
141 }
142 }
143
144 #[inline]
145 pub fn data(&self) -> &[T] {
146 self.data
147 }
148
149 #[inline]
150 pub fn data_mut(&mut self) -> &mut [T] {
151 self.data
152 }
153
154 #[inline]
155 pub fn dims(&self) -> &'a [usize] {
156 self.dims
157 }
158
159 #[inline]
160 pub fn strides(&self) -> &'a [isize] {
161 self.strides
162 }
163
164 #[inline]
165 pub fn offset(&self) -> isize {
166 self.offset
167 }
168
169 #[inline]
170 pub fn ptr(&self) -> *const T {
171 unsafe { self.data.as_ptr().offset(self.offset) }
172 }
173
174 #[inline]
175 pub fn as_mut_ptr(&mut self) -> *mut T {
176 unsafe { self.data.as_mut_ptr().offset(self.offset) }
177 }
178
179 #[inline]
184 pub fn as_view(&self) -> StridedView<'_, T, Identity> {
185 unsafe { StridedView::new_unchecked(self.data, self.dims, self.strides, self.offset) }
186 }
187
188 #[inline]
193 pub fn as_view_mut(&mut self) -> StridedViewMut<'_, T> {
194 unsafe { StridedViewMut::new_unchecked(self.data, self.dims, self.strides, self.offset) }
195 }
196}
197
198#[cfg(test)]
199mod tests {
200 use super::*;
201
202 #[test]
203 fn raw_ref_rejects_out_of_bounds_layout() {
204 let data = [0.0f64; 4];
205 let err = RawStridedRef::new(&data, &[2, 3], &[3, 1], 0).unwrap_err();
206 assert!(matches!(err, crate::StridedError::OffsetOverflow));
207 }
208
209 #[test]
210 fn raw_mut_can_reborrow_as_view() {
211 let mut data = [1, 2, 3, 4];
212 let mut raw = RawStridedMut::new(&mut data, &[2, 2], &[2, 1], 0).unwrap();
213 {
214 let view = raw.as_view();
215 assert_eq!(view.dims(), &[2, 2]);
216 }
217 let view_mut = raw.as_view_mut();
218 assert_eq!(view_mut.get(&[1, 1]), 4);
219 }
220}