ferroui_base/utilities/
array_slice.rs1use std::cell::{Ref, RefCell, RefMut};
10use std::rc::Rc;
11
12pub struct ArraySlice<T> {
14 data: Rc<RefCell<Vec<T>>>,
15 start: usize,
16 length: usize,
17}
18
19impl<T> ArraySlice<T> {
20 pub fn empty() -> Self {
22 Self { data: Rc::new(RefCell::new(Vec::new())), start: 0, length: 0 }
23 }
24
25 pub fn new(data: Vec<T>) -> Self {
27 let length = data.len();
28 Self { data: Rc::new(RefCell::new(data)), start: 0, length }
29 }
30
31 pub fn from_shared(data: Rc<RefCell<Vec<T>>>, start: usize, length: usize) -> Self {
35 {
36 let array = data.borrow();
37 assert!(start <= array.len() && length <= array.len() - start, "range outside of the array");
38 }
39 Self { data, start, length }
40 }
41
42 #[inline]
44 pub fn data(&self) -> &Rc<RefCell<Vec<T>>> {
45 &self.data
46 }
47
48 #[inline]
50 pub fn is_empty(&self) -> bool {
51 self.length == 0
52 }
53
54 #[inline]
56 pub fn start(&self) -> usize {
57 self.start
58 }
59
60 #[inline]
62 pub fn length(&self) -> usize {
63 self.length
64 }
65
66 #[inline]
70 pub fn span(&self) -> Ref<'_, [T]> {
71 Ref::map(self.data.borrow(), |array| &array[self.start..self.start + self.length])
72 }
73
74 #[inline]
78 pub fn span_mut(&self) -> RefMut<'_, [T]> {
79 RefMut::map(self.data.borrow_mut(), |array| &mut array[self.start..self.start + self.length])
80 }
81
82 #[inline]
84 pub fn set(&self, index: usize, value: T) {
85 self.span_mut()[index] = value;
86 }
87
88 pub fn slice(&self, start: usize, length: usize) -> Self {
91 Self::from_shared(self.data.clone(), start, length)
92 }
93
94 pub fn take(&self, length: usize) -> Self {
98 if self.is_empty() {
99 return self.clone();
100 }
101 assert!(length <= self.length, "length out of range");
102 Self { data: self.data.clone(), start: self.start, length }
103 }
104
105 pub fn skip(&self, length: usize) -> Self {
109 if self.is_empty() {
110 return self.clone();
111 }
112 assert!(length <= self.length, "length out of range");
113 Self { data: self.data.clone(), start: self.start + length, length: self.length - length }
114 }
115}
116
117impl<T: Copy> ArraySlice<T> {
118 #[inline]
120 pub fn get(&self, index: usize) -> T {
121 self.span()[index]
122 }
123
124 pub fn fill(&self, value: T) {
126 self.span_mut().fill(value);
127 }
128}
129
130impl<T> Clone for ArraySlice<T> {
131 fn clone(&self) -> Self {
132 Self { data: self.data.clone(), start: self.start, length: self.length }
133 }
134}
135
136impl<T> From<Vec<T>> for ArraySlice<T> {
137 fn from(data: Vec<T>) -> Self {
138 Self::new(data)
139 }
140}
141
142#[cfg(test)]
143mod tests {
144 use super::*;
145
146 #[test]
147 fn slices_alias_the_array() {
148 let slice = ArraySlice::new(vec![1, 2, 3, 4, 5]);
149 let tail = slice.skip(2);
150 tail.set(0, 30);
151 assert_eq!(&*slice.span(), &[1, 2, 30, 4, 5]);
152 assert_eq!(tail.start(), 2);
153 assert_eq!(tail.take(2).length(), 2);
154 assert_eq!(&*tail.slice(1, 2).span(), &[2, 30]);
156 slice.take(2).fill(0);
157 assert_eq!(slice.get(1), 0);
158 }
159}