1use im::vector;
13use im::vector::Vector;
14use sealed::sealed;
15use static_cow::{IntoOwning, ToOwning};
16use std::iter::FusedIterator;
17use std::mem::MaybeUninit;
18use std::ops::Range;
19
20struct OwningFocus {
28 vector: *mut Vector<u8>,
29 focus: MaybeUninit<vector::Focus<'static, u8>>,
30}
31
32impl OwningFocus {
33 fn new(vector: Box<Vector<u8>>) -> OwningFocus {
34 let vector_ref = Box::leak(vector);
35 let vector_ptr = vector_ref as *mut Vector<u8>;
36 let focus = MaybeUninit::new(vector_ref.focus());
37
38 OwningFocus {
43 vector: vector_ptr,
44 focus,
45 }
46 }
47
48 fn as_vector(&self) -> &Vector<u8> {
50 unsafe { &*self.vector }
52 }
53
54 fn as_focus(&mut self) -> &mut vector::Focus<'_, u8> {
55 unsafe { std::mem::transmute(self.focus.assume_init_mut()) }
57 }
58
59 fn update<F, R>(&mut self, f: F) -> R
60 where
61 F: FnOnce(&mut Vector<u8>) -> R,
62 {
63 unsafe {
64 let call_result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
69 self.focus.assume_init_drop();
70 f(&mut *self.vector)
71 }));
72
73 let focus_result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
77 self.focus.write((*self.vector).focus());
78 }));
79
80 if focus_result.is_err() {
81 std::process::abort();
85 };
86
87 match call_result {
90 Ok(r) => r,
91 Err(payload) => std::panic::resume_unwind(payload),
92 }
93 }
94 }
95
96 fn index(&mut self, index: usize) -> u8 {
98 *self.as_focus().index(index)
99 }
100
101 fn chunk_at(&mut self, index: usize) -> (Range<usize>, &[u8]) {
103 self.as_focus().chunk_at(index)
104 }
105}
106
107impl Clone for OwningFocus {
108 fn clone(&self) -> Self {
109 OwningFocus::new(Box::new(self.as_vector().clone()))
110 }
111}
112
113impl Drop for OwningFocus {
114 fn drop(&mut self) {
115 unsafe {
118 self.focus.assume_init_drop();
119 std::mem::drop(Box::from_raw(self.vector));
120 }
121 }
122}
123
124#[allow(clippy::module_name_repetitions)]
126pub struct BorrowingAccessor<'a> {
127 vector: &'a Vector<u8>,
128 focus: vector::Focus<'a, u8>,
129 front_index: usize,
130 back_index: usize,
131}
132
133impl<'a> BorrowingAccessor<'a> {
134 pub(crate) fn new(vector: &'a Vector<u8>) -> BorrowingAccessor<'a> {
135 BorrowingAccessor {
136 vector,
137 focus: vector.focus(),
138 front_index: 0,
139 back_index: vector.len(),
140 }
141 }
142}
143
144impl<'a> ToOwning for BorrowingAccessor<'a> {
145 type Owning = OwningAccessor;
146
147 fn to_owning(&self) -> Self::Owning {
148 OwningAccessor::from_borrowed(self.vector, self.front_index, self.back_index)
149 }
150}
151
152impl<'a> IntoOwning for BorrowingAccessor<'a> {
153 fn into_owning(self) -> Self::Owning {
154 self.to_owning()
155 }
156}
157
158#[derive(Clone)]
165#[allow(clippy::module_name_repetitions)]
166pub struct OwningAccessor {
167 focus: OwningFocus,
168 proper_front_index: usize,
171 proper_back_index: usize,
174 focal_front_index: usize,
177 focal_back_index: usize,
180}
181
182impl OwningAccessor {
183 pub(crate) fn new(vector: Vector<u8>) -> OwningAccessor {
184 let len = vector.len();
185 OwningAccessor {
186 focus: OwningFocus::new(Box::new(vector)),
187 proper_front_index: 0,
188 proper_back_index: len,
189 focal_front_index: 0,
190 focal_back_index: len,
191 }
192 }
193
194 fn from_borrowed(vector: &Vector<u8>, front_index: usize, back_index: usize) -> OwningAccessor {
195 let mut owning = OwningAccessor {
196 focus: OwningFocus::new(Box::new(vector.clone())),
197 proper_front_index: front_index,
198 proper_back_index: back_index,
199 focal_front_index: 0,
200 focal_back_index: vector.len(),
201 };
202
203 owning.gc();
204 owning
205 }
206
207 fn gc(&mut self) {
208 let cur_len = self.proper_back_index - self.proper_front_index;
209 let orig_len = self.focal_back_index - self.focal_front_index;
210
211 if orig_len > 256 && orig_len / 2 >= cur_len {
212 self.focus.update(|vector| {
213 *vector = vector.split_off(self.proper_front_index - self.focal_front_index);
214 vector.truncate(self.proper_back_index - self.proper_front_index);
215 });
216 self.focal_front_index = self.proper_front_index;
217 self.focal_back_index = self.proper_back_index;
218 }
219 }
220}
221
222pub struct ByteIter<'a, A>(&'a mut A);
224
225#[sealed]
227pub trait Accessor: IntoOwning<Owning = OwningAccessor> {
228 fn front_byte(&mut self) -> Option<(usize, u8)>;
230 fn back_byte(&mut self) -> Option<(usize, u8)>;
232 fn front_chunk(&mut self) -> Option<(Range<usize>, &[u8])>;
235 fn back_chunk(&mut self) -> Option<(Range<usize>, &[u8])>;
238
239 fn take_front(&mut self, index: usize) -> Vector<u8>;
242 fn take_back(&mut self, index: usize) -> Vector<u8>;
245
246 #[must_use]
248 fn front_index(&self) -> usize;
249 #[must_use]
251 fn back_index(&self) -> usize;
252
253 fn byte_iter(&mut self) -> ByteIter<'_, Self> {
255 ByteIter(self)
256 }
257
258 #[must_use]
266 fn shallow_clone(&self) -> Self;
267}
268
269impl<'a, A> Iterator for ByteIter<'a, A>
270where
271 A: Accessor,
272{
273 type Item = u8;
274
275 fn next(&mut self) -> Option<Self::Item> {
276 Some(self.0.front_byte()?.1)
277 }
278
279 fn size_hint(&self) -> (usize, Option<usize>) {
280 let len = self.0.back_index() - self.0.front_index();
281 (len, Some(len))
282 }
283
284 fn last(mut self) -> Option<Self::Item> {
285 self.next_back()
286 }
287}
288
289impl<'a, A> DoubleEndedIterator for ByteIter<'a, A>
290where
291 A: Accessor,
292{
293 fn next_back(&mut self) -> Option<Self::Item> {
294 Some(self.0.back_byte()?.1)
295 }
296}
297
298impl<'a, A> FusedIterator for ByteIter<'a, A> where A: Accessor {}
299
300impl<'a, A> ExactSizeIterator for ByteIter<'a, A> where A: Accessor {}
301
302#[sealed]
303impl<'a> Accessor for BorrowingAccessor<'a> {
304 fn front_byte(&mut self) -> Option<(usize, u8)> {
305 if self.front_index == self.back_index {
306 None
307 } else {
308 let byte = *self.focus.index(self.front_index);
309 let index = self.front_index;
310 self.front_index += 1;
311 Some((index, byte))
312 }
313 }
314
315 fn back_byte(&mut self) -> Option<(usize, u8)> {
316 if self.front_index == self.back_index {
317 None
318 } else {
319 self.back_index -= 1;
320 Some((self.back_index, *self.focus.index(self.back_index)))
321 }
322 }
323
324 fn front_chunk(&mut self) -> Option<(Range<usize>, &[u8])> {
325 if self.front_index == self.back_index {
326 None
327 } else {
328 let (unclamped_range, unclamped_chunk) = self.focus.chunk_at(self.front_index);
329 let clamped_range = std::cmp::max(unclamped_range.start, self.front_index)
330 ..std::cmp::min(unclamped_range.end, self.back_index);
331 let cut_range = (clamped_range.start - unclamped_range.start)
332 ..(unclamped_chunk.len() - (unclamped_range.end - clamped_range.end));
333 self.front_index = clamped_range.end;
334 Some((clamped_range, &unclamped_chunk[cut_range]))
335 }
336 }
337
338 fn back_chunk(&mut self) -> Option<(Range<usize>, &[u8])> {
339 if self.front_index == self.back_index {
340 None
341 } else {
342 let (unclamped_range, unclamped_chunk) = self.focus.chunk_at(self.back_index - 1);
343 let clamped_range = std::cmp::max(unclamped_range.start, self.front_index)
344 ..std::cmp::min(unclamped_range.end, self.back_index);
345 let cut_range = (clamped_range.start - unclamped_range.start)
346 ..(unclamped_chunk.len() - (unclamped_range.end - clamped_range.end));
347 self.back_index = clamped_range.start;
348 Some((clamped_range, &unclamped_chunk[cut_range]))
349 }
350 }
351
352 fn take_front(&mut self, index: usize) -> Vector<u8> {
353 let mut vector = self.vector.skip(self.front_index);
354 vector.truncate(index - self.front_index);
355 self.front_index = index;
356 vector
357 }
358
359 fn take_back(&mut self, index: usize) -> Vector<u8> {
360 let mut vector = self.vector.skip(index);
361 vector.truncate(self.back_index - index);
362 self.back_index = index;
363 vector
364 }
365
366 fn front_index(&self) -> usize {
367 self.front_index
368 }
369
370 fn back_index(&self) -> usize {
371 self.back_index
372 }
373
374 fn shallow_clone(&self) -> Self {
375 BorrowingAccessor {
376 vector: self.vector,
377 focus: self.focus.clone(),
378 front_index: self.front_index,
379 back_index: self.back_index,
380 }
381 }
382}
383
384#[sealed]
385impl Accessor for OwningAccessor {
386 fn front_byte(&mut self) -> Option<(usize, u8)> {
387 if self.proper_front_index == self.proper_back_index {
388 None
389 } else {
390 let byte = self
391 .focus
392 .index(self.proper_front_index - self.focal_front_index);
393 let index = self.proper_front_index;
394 self.proper_front_index += 1;
395 self.gc();
396 Some((index, byte))
397 }
398 }
399
400 fn back_byte(&mut self) -> Option<(usize, u8)> {
401 if self.proper_front_index == self.proper_back_index {
402 None
403 } else {
404 self.proper_back_index -= 1;
405 let byte = self
406 .focus
407 .index(self.proper_back_index - self.focal_front_index);
408 self.gc();
409 Some((self.proper_back_index, byte))
410 }
411 }
412
413 fn front_chunk(&mut self) -> Option<(Range<usize>, &[u8])> {
414 if self.proper_front_index == self.proper_back_index {
415 None
416 } else {
417 self.gc();
418 let (focal_range, chunk) = self
419 .focus
420 .chunk_at(self.proper_front_index - self.focal_front_index);
421 let unclamped_proper_range = focal_range.start + self.focal_front_index
422 ..focal_range.end + self.focal_front_index;
423 let clamped_proper_range =
424 std::cmp::max(unclamped_proper_range.start, self.proper_front_index)
425 ..std::cmp::min(unclamped_proper_range.end, self.proper_back_index);
426 let cut_range = (clamped_proper_range.start - unclamped_proper_range.start)
427 ..(focal_range.len() - (unclamped_proper_range.end - clamped_proper_range.end));
428
429 self.proper_front_index = clamped_proper_range.end;
430 Some((clamped_proper_range, &chunk[cut_range]))
431 }
432 }
433
434 fn back_chunk(&mut self) -> Option<(Range<usize>, &[u8])> {
435 if self.proper_front_index == self.proper_back_index {
436 None
437 } else {
438 self.gc();
439 let (focal_range, chunk) = self
440 .focus
441 .chunk_at(self.proper_back_index - self.focal_front_index - 1);
442 let unclamped_proper_range = focal_range.start + self.focal_front_index
443 ..focal_range.end + self.focal_front_index;
444 let clamped_proper_range =
445 std::cmp::max(unclamped_proper_range.start, self.proper_front_index)
446 ..std::cmp::min(unclamped_proper_range.end, self.proper_back_index);
447 let cut_range = (clamped_proper_range.start - unclamped_proper_range.start)
448 ..(focal_range.len() - (unclamped_proper_range.end - clamped_proper_range.end));
449
450 self.proper_back_index = clamped_proper_range.start;
451 Some((clamped_proper_range, &chunk[cut_range]))
452 }
453 }
454
455 fn take_front(&mut self, index: usize) -> Vector<u8> {
456 let mut vector = self
457 .focus
458 .as_vector()
459 .skip(self.proper_front_index - self.focal_front_index);
460 vector.truncate(index - self.proper_front_index);
461 self.proper_front_index = index;
462 self.gc();
463 vector
464 }
465
466 fn take_back(&mut self, index: usize) -> Vector<u8> {
467 let mut vector = self.focus.as_vector().skip(index - self.focal_front_index);
468 vector.truncate(self.proper_back_index - index);
469 self.proper_back_index = index;
470 self.gc();
471 vector
472 }
473
474 fn front_index(&self) -> usize {
475 self.proper_front_index
476 }
477
478 fn back_index(&self) -> usize {
479 self.proper_back_index
480 }
481
482 fn shallow_clone(&self) -> Self {
483 self.clone()
484 }
485}
486
487pub(crate) struct PopVecBytes<'a>(pub(crate) &'a mut Vector<u8>);
488
489impl<'a> Iterator for PopVecBytes<'a> {
490 type Item = u8;
491
492 fn next(&mut self) -> Option<Self::Item> {
493 self.0.pop_front()
494 }
495
496 fn size_hint(&self) -> (usize, Option<usize>) {
497 (self.0.len(), Some(self.0.len()))
498 }
499
500 fn last(mut self) -> Option<Self::Item> {
501 self.next_back()
502 }
503}
504
505impl<'a> DoubleEndedIterator for PopVecBytes<'a> {
506 fn next_back(&mut self) -> Option<Self::Item> {
507 self.0.pop_back()
508 }
509}
510
511impl<'a> FusedIterator for PopVecBytes<'a> {}
512impl<'a> ExactSizeIterator for PopVecBytes<'a> {}
513
514#[cfg(test)]
515mod tests {
516 use super::*;
517 use crate::test_utils::StreamStrategy;
518 use proptest::prelude::*;
519 use proptest_derive::Arbitrary;
520
521 #[derive(Debug, Copy, Clone, Arbitrary)]
522 enum Instruction {
523 FrontByte,
524 BackByte,
525 FrontChunk,
526 BackChunk,
527 TakeFront,
528 TakeBack,
529 }
530
531 proptest! {
532 #[test]
533 fn accessors_agree(
534 vec in prop::collection::vec(u8::arbitrary(), 0..1024),
535 ratio in 0.0f64 .. 1.0,
536 mut stream in StreamStrategy(Instruction::arbitrary()))
537 {
538 let start_size = vec.len();
539 #[allow(clippy::cast_possible_truncation,clippy::cast_precision_loss,clippy::cast_sign_loss)]
540 let end_size = (ratio * (start_size as f64)).round() as usize;
541 assert!(end_size <= start_size);
542
543 let v = Vector::from(vec);
544
545 let mut borrowing = BorrowingAccessor::new(&v);
546 while borrowing.back_index() - borrowing.front_index() > end_size {
547 match stream.gen() {
548 Instruction::FrontByte => {
549 borrowing.front_byte();
550 }
551 Instruction::BackByte => {
552 borrowing.back_byte();
553 }
554 Instruction::FrontChunk => {
555 borrowing.front_chunk();
556 }
557 Instruction::BackChunk => {
558 borrowing.back_chunk();
559 }
560 Instruction::TakeFront => {
561 let i = std::cmp::min(borrowing.front_index() + 32, borrowing.back_index());
562 borrowing.take_front(i);
563 }
564 Instruction::TakeBack => {
565 let i = std::cmp::max(
566 borrowing.back_index().saturating_sub(32),
567 borrowing.front_index());
568
569 borrowing.take_back(i);
570 }
571 }
572 }
573
574 let mut owning = borrowing.to_owning();
575
576 while borrowing.front_index() != borrowing.back_index() {
577 prop_assert_eq!(borrowing.front_index(), owning.front_index());
578 prop_assert_eq!(borrowing.back_index(), owning.back_index());
579
580 match stream.gen() {
581 Instruction::FrontByte => {
582 prop_assert_eq!(borrowing.front_byte(), owning.front_byte());
583 }
584 Instruction::BackByte => {
585 prop_assert_eq!(borrowing.back_byte(), owning.back_byte());
586 }
587 Instruction::FrontChunk => {
588 prop_assert_eq!(borrowing.front_chunk(), owning.front_chunk());
589 }
590 Instruction::BackChunk => {
591 prop_assert_eq!(borrowing.back_chunk(), owning.back_chunk());
592 }
593 Instruction::TakeFront => {
594 let i = std::cmp::min(borrowing.front_index() + 32, borrowing.back_index());
595 prop_assert_eq!(borrowing.take_front(i), owning.take_front(i));
596 }
597 Instruction::TakeBack => {
598 let i = std::cmp::max(
599 borrowing.back_index().saturating_sub(32),
600 borrowing.front_index(),
601 );
602 prop_assert_eq!(borrowing.take_back(i), owning.take_back(i));
603 }
604 }
605 }
606 }
607 }
608}