1use crate::{
2 adler32::{adler32, adler32_fold_copy},
3 crc32::Crc32Fold,
4 weak_slice::WeakSliceMut,
5};
6
7#[derive(Debug)]
13pub struct Window<'a> {
14 buf: WeakSliceMut<'a, u8>,
15
16 have: usize, next: usize, }
20
21impl<'a> Window<'a> {
22 pub fn into_raw_parts(self) -> (*mut u8, usize) {
23 self.buf.into_raw_parts()
24 }
25
26 pub unsafe fn from_raw_parts(ptr: *mut u8, len: usize) -> Self {
27 Self {
28 buf: unsafe { WeakSliceMut::from_raw_parts_mut(ptr, len) },
29 have: 0,
30 next: 0,
31 }
32 }
33
34 pub fn is_empty(&self) -> bool {
35 self.size() == 0
36 }
37
38 pub fn buffer_size(&self) -> usize {
41 assert!(self.buf.len().is_power_of_two());
42 self.buf.len()
43 }
44
45 pub fn size(&self) -> usize {
46 assert!(self.buf.is_empty() || self.buf.len() >= Self::padding());
48 self.buf.len().saturating_sub(Self::padding())
49 }
50
51 pub fn have(&self) -> usize {
53 self.have
54 }
55
56 pub unsafe fn set_have(&mut self, have: usize) {
57 self.have = have;
58 }
59
60 pub fn next(&self) -> usize {
62 self.next
63 }
64
65 pub fn empty() -> Self {
66 Self {
67 buf: WeakSliceMut::empty(),
68 have: 0,
69 next: 0,
70 }
71 }
72
73 pub fn clear(&mut self) {
74 self.have = 0;
75 self.next = 0;
76 }
77
78 pub fn as_slice(&self) -> &[u8] {
79 &self.buf.as_slice()[..self.have]
80 }
81
82 pub fn as_ptr(&self) -> *const u8 {
83 self.buf.as_ptr()
84 }
85
86 #[cfg(test)]
87 fn extend_adler32(&mut self, slice: &[u8], checksum: &mut u32) {
88 self.extend(slice, 0, true, checksum, &mut Crc32Fold::new());
89 }
90
91 pub fn extend(
92 &mut self,
93 slice: &[u8],
94 flags: i32,
95 update_checksum: bool,
96 checksum: &mut u32,
97 crc_fold: &mut Crc32Fold,
98 ) {
99 let len = slice.len();
100 let wsize = self.size();
101
102 if len >= wsize {
103 let pos = len.saturating_sub(self.size());
105 let (non_window_slice, window_slice) = slice.split_at(pos);
106
107 if update_checksum {
108 if flags != 0 {
109 crc_fold.fold(non_window_slice, 0);
110 crc_fold.fold_copy(&mut self.buf.as_mut_slice()[..wsize], window_slice);
111 } else {
112 *checksum = adler32(*checksum, non_window_slice);
113 *checksum = adler32_fold_copy(*checksum, self.buf.as_mut_slice(), window_slice);
114 }
115 } else {
116 self.buf.as_mut_slice()[..wsize].copy_from_slice(window_slice);
117 }
118
119 self.next = 0;
120 self.have = self.size();
121 } else {
122 let dist = Ord::min(wsize - self.next, slice.len());
123
124 let (end_part, start_part) = slice.split_at(dist);
127
128 if update_checksum {
129 let dst = &mut self.buf.as_mut_slice()[self.next..][..end_part.len()];
130 if flags != 0 {
131 crc_fold.fold_copy(dst, end_part);
132 } else {
133 *checksum = adler32_fold_copy(*checksum, dst, end_part);
134 }
135 } else {
136 self.buf.as_mut_slice()[self.next..][..end_part.len()].copy_from_slice(end_part);
137 }
138
139 if !start_part.is_empty() {
140 let dst = &mut self.buf.as_mut_slice()[..start_part.len()];
141
142 if update_checksum {
143 if flags != 0 {
144 crc_fold.fold_copy(dst, start_part);
145 } else {
146 *checksum = adler32_fold_copy(*checksum, dst, start_part);
147 }
148 } else {
149 dst.copy_from_slice(start_part);
150 }
151
152 self.next = start_part.len();
153 self.have = self.size();
154 } else {
155 self.next += dist;
156 if self.next == self.size() {
157 self.next = 0;
158 }
159 if self.have < self.size() {
160 self.have += dist;
161 }
162 }
163 }
164 }
165
166 #[cfg(test)]
167 pub fn new_in(alloc: &crate::inflate::Allocator<'a>, window_bits: usize) -> Option<Self> {
168 let len = (1 << window_bits) + Self::padding();
169 let ptr = alloc.allocate_zeroed_buffer(len)?;
170
171 Some(Self {
172 buf: unsafe { WeakSliceMut::from_raw_parts_mut(ptr.as_ptr(), len) },
173 have: 0,
174 next: 0,
175 })
176 }
177
178 pub unsafe fn clone_to(&self, ptr: *mut u8, len: usize) -> Self {
179 debug_assert_eq!(self.buf.len(), len);
180
181 unsafe { core::ptr::copy_nonoverlapping(self.buf.as_ptr(), ptr, len) };
182
183 Self {
184 buf: unsafe { WeakSliceMut::from_raw_parts_mut(ptr, len) },
185 have: self.have,
186 next: self.next,
187 }
188 }
189
190 pub fn padding() -> usize {
192 64 }
194}
195
196#[cfg(all(test, feature = "rust-allocator"))]
197mod test {
198 use super::*;
199
200 fn init_window(window_bits_log2: usize) -> Window<'static> {
201 let mut window = Window::new_in(&crate::allocate::RUST, window_bits_log2).unwrap();
202 window.have = 0;
203 window.next = 0;
204 window
205 }
206
207 #[test]
208 fn extend_in_bounds() {
209 let mut checksum = 0;
210
211 let mut window = init_window(4);
212
213 window.extend_adler32(&[1; 5], &mut checksum);
214 assert_eq!(window.have, 5);
215 assert_eq!(window.next, 5);
216
217 let slice = &window.buf.as_slice()[..window.size()];
218 assert_eq!(&[1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], slice);
219
220 window.extend_adler32(&[2; 7], &mut checksum);
221 assert_eq!(window.have, 12);
222 assert_eq!(window.next, 12);
223
224 let slice = &window.buf.as_slice()[..window.size()];
225 assert_eq!(&[1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0], slice);
226
227 assert_eq!(checksum, 6946835);
228
229 unsafe {
230 crate::allocate::RUST.deallocate(
231 window.buf.as_mut_slice().as_mut_ptr(),
232 window.buf.as_slice().len(),
233 )
234 }
235 }
236
237 #[test]
238 fn extend_crosses_bounds() {
239 let mut checksum = 0;
240
241 let mut window = init_window(2);
242
243 window.extend_adler32(&[1; 3], &mut checksum);
244 assert_eq!(window.have, 3);
245 assert_eq!(window.next, 3);
246
247 let slice = &window.buf.as_slice()[..window.size()];
248 assert_eq!(&[1, 1, 1, 0], slice);
249
250 window.extend_adler32(&[2; 3], &mut checksum);
251 assert_eq!(window.have, 4);
252 assert_eq!(window.next, 2);
253
254 let slice = &window.buf.as_slice()[..window.size()];
255 assert_eq!(&[2, 2, 1, 2], slice);
256
257 assert_eq!(checksum, 1769481);
258
259 unsafe {
260 crate::allocate::RUST.deallocate(
261 window.buf.as_mut_slice().as_mut_ptr(),
262 window.buf.as_slice().len(),
263 )
264 }
265 }
266
267 #[test]
268 fn extend_out_of_bounds() {
269 let mut checksum = 0;
270
271 let mut window = init_window(3);
272
273 window.extend_adler32(&[1, 2, 3, 4, 5, 6, 7, 8, 9], &mut checksum);
275 assert_eq!(window.have, 8);
276 assert_eq!(window.next, 0);
277
278 let slice = &window.as_slice()[..window.size()];
279 assert_eq!(&[2, 3, 4, 5, 6, 7, 8, 9], slice);
280
281 assert_eq!(checksum, 10813485);
282
283 unsafe {
284 crate::allocate::RUST.deallocate(
285 window.buf.as_mut_slice().as_mut_ptr(),
286 window.as_slice().len(),
287 )
288 }
289 }
290}