1use {
4 crate::{list::list_trait::List, pod_length::PodLength, primitives::PodU32},
5 bytemuck::Pod,
6 std::ops::Deref,
7};
8
9#[derive(Debug)]
10pub struct ListViewReadOnly<'data, T: Pod, L: PodLength = PodU32> {
11 pub(crate) length: &'data L,
12 pub(crate) data: &'data [T],
13 pub(crate) capacity: usize,
14}
15
16impl<T: Pod, L: PodLength> List for ListViewReadOnly<'_, T, L> {
17 type Item = T;
18 type Length = L;
19
20 fn capacity(&self) -> usize {
21 self.capacity
22 }
23}
24
25impl<T: Pod, L: PodLength> Deref for ListViewReadOnly<'_, T, L> {
26 type Target = [T];
27
28 fn deref(&self) -> &Self::Target {
29 let len = (*self.length).into();
30 &self.data[..len]
31 }
32}
33
34#[cfg(test)]
35mod tests {
36 use {
37 super::*,
38 crate::{
39 list::ListView,
40 pod_length::PodLength,
41 primitives::{PodU32, PodU64},
42 },
43 bytemuck_derive::{Pod as DerivePod, Zeroable},
44 std::mem::size_of,
45 };
46
47 #[repr(C, align(16))]
48 #[derive(DerivePod, Zeroable, Copy, Clone, Debug, PartialEq)]
49 struct TestStruct(u128);
50
51 fn build_test_buffer<T: Pod, L: PodLength>(
53 length: usize,
54 capacity: usize,
55 items: &[T],
56 ) -> Vec<u8>
57 where
58 <L as TryFrom<usize>>::Error: std::fmt::Debug,
59 {
60 let size = ListView::<T, L>::size_of(capacity).unwrap();
61 let mut buffer = vec![0u8; size];
62
63 let pod_len = L::try_from(length).unwrap();
65 let len_bytes = bytemuck::bytes_of(&pod_len);
66 buffer[0..size_of::<L>()].copy_from_slice(len_bytes);
67
68 if !items.is_empty() {
70 let data_start = ListView::<T, L>::size_of(0).unwrap();
71 let items_bytes = bytemuck::cast_slice(items);
72 buffer[data_start..data_start.saturating_add(items_bytes.len())]
73 .copy_from_slice(items_bytes);
74 }
75
76 buffer
77 }
78
79 #[test]
80 fn test_len_and_capacity() {
81 let items = [10u32, 20, 30];
82 let buffer = build_test_buffer::<u32, PodU32>(items.len(), 5, &items);
83 let view = ListView::<u32>::unpack(&buffer).unwrap();
84
85 assert_eq!(view.len(), 3);
86 assert_eq!(view.capacity(), 5);
87 }
88
89 #[test]
90 fn test_as_slice() {
91 let items = [10u32, 20, 30];
92 let buffer = build_test_buffer::<u32, PodU32>(items.len(), 5, &items);
94 let view = ListView::<u32, PodU32>::unpack(&buffer).unwrap();
95
96 assert_eq!(*view, items[..]);
98 }
99
100 #[test]
101 fn test_is_empty() {
102 let buffer_full = build_test_buffer::<u32, PodU32>(1, 2, &[10]);
104 let view_full = ListView::<u32>::unpack(&buffer_full).unwrap();
105 assert!(!view_full.is_empty());
106
107 let buffer_empty = build_test_buffer::<u32, PodU32>(0, 2, &[]);
109 let view_empty = ListView::<u32>::unpack(&buffer_empty).unwrap();
110 assert!(view_empty.is_empty());
111 }
112
113 #[test]
114 fn test_iter() {
115 let items = [TestStruct(1), TestStruct(2)];
116 let buffer = build_test_buffer::<TestStruct, PodU64>(items.len(), 3, &items);
117 let view = ListView::<TestStruct, PodU64>::unpack(&buffer).unwrap();
118
119 let mut iter = view.iter();
120 assert_eq!(iter.next(), Some(&items[0]));
121 assert_eq!(iter.next(), Some(&items[1]));
122 assert_eq!(iter.next(), None);
123 let collected: Vec<_> = view.iter().collect();
124 assert_eq!(collected, vec![&items[0], &items[1]]);
125 }
126
127 #[test]
128 fn test_iter_on_empty_list() {
129 let buffer = build_test_buffer::<u32, PodU32>(0, 5, &[]);
130 let view = ListView::<u32, PodU32>::unpack(&buffer).unwrap();
131
132 assert_eq!(view.iter().count(), 0);
133 assert_eq!(view.iter().next(), None);
134 }
135
136 #[test]
137 fn test_zero_capacity() {
138 let buffer = build_test_buffer::<TestStruct, PodU32>(0, 0, &[]);
140 let view = ListView::<TestStruct, PodU32>::unpack(&buffer).unwrap();
141
142 assert_eq!(view.len(), 0);
143 assert_eq!(view.capacity(), 0);
144 assert!(view.is_empty());
145 assert_eq!(*view, []);
146 }
147
148 #[test]
149 fn test_with_padding() {
150 let header_size = ListView::<TestStruct>::size_of(0).unwrap();
154 assert_eq!(header_size, 16);
155
156 let items = [TestStruct(123), TestStruct(456)];
157 let buffer = build_test_buffer::<TestStruct, PodU32>(items.len(), 4, &items);
158 let view = ListView::<TestStruct>::unpack(&buffer).unwrap();
159
160 assert_eq!(view.len(), 2);
162 assert_eq!(view.capacity(), 4);
163 assert_eq!(*view, items[..]);
164 }
165
166 #[test]
167 fn test_bytes_used_and_allocated() {
168 let items = [10u32, 20, 30];
170 let capacity = 5;
171 let buffer = build_test_buffer::<u32, PodU32>(items.len(), capacity, &items);
172 let view = ListView::<u32>::unpack(&buffer).unwrap();
173
174 let expected_used = ListView::<u32>::size_of(view.len()).unwrap();
175 let expected_cap = ListView::<u32>::size_of(view.capacity()).unwrap();
176
177 assert_eq!(view.bytes_used().unwrap(), expected_used);
178 assert_eq!(view.bytes_allocated().unwrap(), expected_cap);
179 }
180
181 #[test]
182 fn test_get() {
183 let items = [10u32, 20, 30];
184 let buffer = build_test_buffer::<u32, PodU32>(items.len(), 5, &items);
185 let view = ListView::<u32>::unpack(&buffer).unwrap();
186
187 assert_eq!(view.first(), Some(&10u32));
189 assert_eq!(view.get(1), Some(&20u32));
190 assert_eq!(view.get(2), Some(&30u32));
191
192 assert_eq!(view.get(3), None);
194
195 assert_eq!(view.get(100), None);
197 }
198
199 #[test]
200 fn test_get_on_empty_list() {
201 let buffer = build_test_buffer::<u32, PodU32>(0, 5, &[]);
202 let view = ListView::<u32, PodU32>::unpack(&buffer).unwrap();
203 assert_eq!(view.first(), None);
204 }
205}