1use {
4 crate::{
5 list::{ListView, ListViewMut, ListViewReadOnly},
6 primitives::PodU32,
7 },
8 bytemuck::Pod,
9 solana_program_error::ProgramError,
10};
11
12#[deprecated(
13 since = "0.6.0",
14 note = "This struct will be removed in the next major release (1.0.0). Please use `ListView` instead."
15)]
16#[allow(deprecated)]
18pub struct PodSlice<'data, T: Pod> {
19 inner: ListViewReadOnly<'data, T, PodU32>,
20}
21
22#[allow(deprecated)]
23impl<'data, T: Pod> PodSlice<'data, T> {
24 pub fn unpack<'a>(data: &'a [u8]) -> Result<Self, ProgramError>
26 where
27 'a: 'data,
28 {
29 let inner = ListView::<T, PodU32>::unpack(data)?;
30 Ok(Self { inner })
31 }
32
33 pub fn data(&self) -> &[T] {
35 let len = self.inner.len();
36 &self.inner.data[..len]
37 }
38
39 pub fn size_of(num_items: usize) -> Result<usize, ProgramError> {
41 ListView::<T, PodU32>::size_of(num_items)
42 }
43}
44
45#[deprecated(
46 since = "0.6.0",
47 note = "This struct will be removed in the next major release (1.0.0). Please use `ListView` instead."
48)]
49pub struct PodSliceMut<'data, T: Pod> {
52 inner: ListViewMut<'data, T, PodU32>,
53}
54
55#[allow(deprecated)]
56impl<'data, T: Pod> PodSliceMut<'data, T> {
57 pub fn unpack<'a>(data: &'a mut [u8]) -> Result<Self, ProgramError>
59 where
60 'a: 'data,
61 {
62 let inner = ListView::<T, PodU32>::unpack_mut(data)?;
63 Ok(Self { inner })
64 }
65
66 pub fn init<'a>(data: &'a mut [u8]) -> Result<Self, ProgramError>
69 where
70 'a: 'data,
71 {
72 let inner = ListView::<T, PodU32>::init(data)?;
73 Ok(Self { inner })
74 }
75
76 pub fn push(&mut self, t: T) -> Result<(), ProgramError> {
78 self.inner.push(t)
79 }
80}
81
82#[cfg(test)]
83#[allow(deprecated)]
84mod tests {
85 use {
86 super::*,
87 crate::{bytemuck::pod_slice_to_bytes, error::PodSliceError},
88 bytemuck_derive::{Pod, Zeroable},
89 };
90
91 #[repr(C)]
92 #[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)]
93 struct TestStruct {
94 test_field: u8,
95 test_pubkey: [u8; 32],
96 }
97
98 const LENGTH_SIZE: usize = std::mem::size_of::<PodU32>();
99
100 #[test]
101 fn test_pod_slice() {
102 let test_field_bytes = [0];
103 let test_pubkey_bytes = [1; 32];
104 let len_bytes = [2, 0, 0, 0];
105
106 let mut data_bytes = [0; 66];
108 data_bytes[0..1].copy_from_slice(&test_field_bytes);
109 data_bytes[1..33].copy_from_slice(&test_pubkey_bytes);
110 data_bytes[33..34].copy_from_slice(&test_field_bytes);
111 data_bytes[34..66].copy_from_slice(&test_pubkey_bytes);
112
113 let mut pod_slice_bytes = [0; 70];
114 pod_slice_bytes[0..4].copy_from_slice(&len_bytes);
115 pod_slice_bytes[4..70].copy_from_slice(&data_bytes);
116
117 let pod_slice = PodSlice::<TestStruct>::unpack(&pod_slice_bytes).unwrap();
118 let pod_slice_data = pod_slice.data();
119
120 assert_eq!(pod_slice.inner.len(), 2);
121 assert_eq!(pod_slice_to_bytes(pod_slice.data()), data_bytes);
122 assert_eq!(pod_slice_data[0].test_field, test_field_bytes[0]);
123 assert_eq!(pod_slice_data[0].test_pubkey, test_pubkey_bytes);
124 assert_eq!(PodSlice::<TestStruct>::size_of(1).unwrap(), 37);
125 }
126
127 #[test]
128 fn test_pod_slice_buffer_too_large() {
129 let data_len = LENGTH_SIZE + std::mem::size_of::<TestStruct>() + 6;
132 let mut pod_slice_bytes = vec![1; data_len];
133 pod_slice_bytes[0..4].copy_from_slice(&[1, 0, 0, 0]);
134 let err = PodSlice::<TestStruct>::unpack(&pod_slice_bytes)
135 .err()
136 .unwrap();
137 assert!(matches!(err, ProgramError::InvalidArgument));
138 }
139
140 #[test]
141 fn test_pod_slice_buffer_larger_than_length_value() {
142 let length: u32 = 12;
146 let length_le = length.to_le_bytes();
147
148 let data_len = PodSlice::<TestStruct>::size_of(length as usize + 2).unwrap();
150 let mut data = vec![0; data_len];
151
152 data[..LENGTH_SIZE].copy_from_slice(&length_le);
155
156 let pod_slice = PodSlice::<TestStruct>::unpack(&data).unwrap();
157 let pod_slice_len = pod_slice.inner.len() as u32;
158 let data = pod_slice.data();
159 let data_vec = data.to_vec();
160
161 assert_eq!(pod_slice_len, length);
162 assert_eq!(data.len(), length as usize);
163 assert_eq!(data_vec.len(), length as usize);
164 }
165
166 #[test]
167 fn test_pod_slice_buffer_too_small() {
168 let pod_slice_bytes = [1; 36];
171 let err = PodSlice::<TestStruct>::unpack(&pod_slice_bytes)
172 .err()
173 .unwrap();
174 assert!(matches!(err, ProgramError::InvalidArgument));
175 }
176
177 #[test]
178 fn test_pod_slice_buffer_shorter_than_length_value() {
179 let length: u32 = 12;
182 let length_le = length.to_le_bytes();
183 for num_items in 0..length {
184 let data_len = PodSlice::<TestStruct>::size_of(num_items as usize).unwrap();
186 let mut data = vec![0; data_len];
187
188 data[..LENGTH_SIZE].copy_from_slice(&length_le);
191
192 let err = PodSlice::<TestStruct>::unpack(&data).err().unwrap();
194 assert_eq!(
195 err,
196 PodSliceError::BufferTooSmall.into(),
197 "Expected an `PodSliceError::BufferTooSmall` error"
198 );
199 }
200 }
201
202 #[test]
203 fn test_pod_slice_mut() {
204 let mut pod_slice_bytes = [0; 70];
206 let len_bytes = [1, 0, 0, 0];
208 pod_slice_bytes[0..4].copy_from_slice(&len_bytes);
209
210 let mut pod_slice = PodSliceMut::<TestStruct>::unpack(&mut pod_slice_bytes).unwrap();
211
212 assert_eq!(pod_slice.inner.len(), 1);
213 pod_slice.push(TestStruct::default()).unwrap();
214 assert_eq!(pod_slice.inner.len(), 2);
215
216 let err = pod_slice
217 .push(TestStruct::default())
218 .expect_err("Expected an `PodSliceError::BufferTooSmall` error");
219 assert_eq!(err, PodSliceError::BufferTooSmall.into());
220 }
221}