manual_share/shared_vec.rs
1//! # Manually shared vector
2//!
3//! `SharedVec` is the `Vec`-based counterpart to `SharedBox`.
4//! It owns the original allocation and lets you create multiple immutable `SharedVecRef`
5//! values that can be sent to other threads while keeping a single shared owner.
6//!
7//! The API is similar to `SharedBox`:
8//! - use `SharedVec::from_vec` to create a shared vector from a `Vec`
9//! - use `SharedVec::borrow` to create a `SharedVecRef`
10//! - use `SharedVec::try_return` to give a borrowed reference back
11//! - use `SharedVec::try_into_vec` to recover the original `Vec` once no references remain
12//!
13//! ```
14//! use std::thread;
15//! use manual_share::SharedVec;
16//!
17//! let values = vec![1, 2, 3];
18//! let mut shared = SharedVec::from_vec(values);
19//!
20//! let shared_ref = shared.borrow();
21//! let handle = thread::spawn(move || {
22//! assert_eq!(shared_ref.as_slice(), &[1, 2, 3]);
23//! shared_ref
24//! });
25//!
26//! let shared_ref = shared.borrow();
27//! let handle2 = thread::spawn(move || {
28//! assert_eq!(shared_ref.as_slice(), &[1, 2, 3]);
29//! shared_ref
30//! });
31//!
32//! shared.try_return(handle.join().unwrap()).unwrap();
33//! shared.try_return(handle2.join().unwrap()).unwrap();
34//!
35//! let values = shared.try_into_vec().unwrap();
36//! assert_eq!(values, vec![1, 2, 3]);
37//! ```
38//!
39
40use std::ops::{Deref, DerefMut};
41
42/// A structure owning the original `Vec` which can be used to create multiple immutable
43/// `SharedVecRef` values to send to other threads.
44/// It uses a counter to record how many references have been created and not returned yet.
45///
46/// Dropping `SharedVec` without returning all `SharedVecRef` values leaks the underlying allocation.
47/// When the `panic-on-drop` feature is enabled, it will panic:
48/// ```should_panic
49/// let r = {
50/// let mut values = manual_share::SharedVec::from_vec(vec![0]);
51/// values.borrow()
52/// };
53/// println!("{:?}", r.as_slice());
54/// ```
55///
56/// Once all `SharedVecRef` values have been returned, `SharedVec` can be converted back into
57/// a `Vec` and its allocation will be released when dropped:
58/// ```
59/// let mut values = manual_share::SharedVec::from_vec(vec![0]);
60/// let reference = values.borrow();
61/// values.try_return(reference).unwrap();
62/// let values = values.try_into_vec().unwrap();
63/// assert_eq!(values, vec![0]);
64/// ```
65#[derive(Debug)]
66pub struct SharedVec<T> {
67 borrow_count: usize,
68 ptr: *mut T,
69 len: usize,
70 cap: usize,
71}
72impl<T> SharedVec<T> {
73 /// Create a `SharedVec` by consuming a `Vec`.
74 pub fn from_vec(vec: Vec<T>) -> Self {
75 let (ptr, len, cap) = vec.into_raw_parts();
76 Self {
77 borrow_count: 0,
78 ptr,
79 len,
80 cap,
81 }
82 }
83 /// Create a `SharedVecRef` and increase the borrow count.
84 ///
85 /// ```
86 /// let mut values = manual_share::SharedVec::from_vec(vec![1, 2, 3]);
87 /// let reference = values.borrow();
88 /// assert_eq!(reference.as_slice(), &[1, 2, 3]);
89 /// values.try_return(reference).unwrap();
90 /// ```
91 ///
92 /// # panics
93 /// Panics when borrow count overflows `usize`.
94 pub fn borrow(&mut self) -> SharedVecRef<T> {
95 self.borrow_count = self.borrow_count.checked_add(1).unwrap();
96 SharedVecRef {
97 ptr: self.ptr,
98 len: self.len,
99 }
100 }
101 /// Try to return back a `SharedVecRef`.
102 /// Returns `Err` if the `SharedVecRef` does not originate from the same `SharedVec`.
103 ///
104 /// ```
105 /// let mut first = manual_share::SharedVec::from_vec(vec![8]);
106 /// let first_ref = first.borrow();
107 /// first.try_return(first_ref).unwrap();
108 ///
109 /// let mut second = manual_share::SharedVec::from_vec(vec![9]);
110 /// let second_ref = second.borrow();
111 /// let err = first.try_return(second_ref).unwrap_err();
112 ///
113 /// assert_eq!(err.as_slice(), &[9]);
114 /// second.try_return(err).unwrap();
115 /// ```
116 pub fn try_return(&mut self, reference: SharedVecRef<T>) -> Result<(), SharedVecRef<T>> {
117 if !core::ptr::eq(self.ptr, reference.ptr) {
118 return Err(reference);
119 }
120
121 if size_of::<T>() == 0 {
122 if self.len != reference.len {
123 return Err(reference);
124 }
125
126 if let Some(new_count) = self.borrow_count.checked_sub(1) {
127 self.borrow_count = new_count;
128 let _ = core::mem::ManuallyDrop::new(reference);
129 Ok(())
130 } else {
131 Err(reference)
132 }
133 } else {
134 self.borrow_count -= 1;
135 let _ = core::mem::ManuallyDrop::new(reference);
136 Ok(())
137 }
138 }
139 /// Try to convert `Self` into a `Vec` once all borrowed references are returned.
140 /// Note that the returned error type is `Self`, dropping it may cause panic.
141 ///
142 /// ```
143 /// let mut values = manual_share::SharedVec::from_vec(vec![0]);
144 /// let reference = values.borrow();
145 ///
146 /// // Try to convert to Vec without returning all SharedVecRef returns Err.
147 /// let mut values = values.try_into_vec().unwrap_err();
148 ///
149 /// values.try_return(reference).unwrap();
150 /// let values = values.try_into_vec().unwrap();
151 ///
152 /// assert_eq!(values, vec![0]);
153 /// ```
154 pub fn try_into_vec(self) -> Result<Vec<T>, Self> {
155 if self.borrow_count > 0 {
156 Err(self)
157 } else {
158 let r = core::mem::ManuallyDrop::new(self);
159 Ok(unsafe { Vec::from_raw_parts(r.ptr, r.len, r.cap) })
160 }
161 }
162 /// Directly get a slice to the values inside the `SharedVec`.
163 /// This use rust built-in lifetime check to ensure the slice is valid as long as the `SharedVec` is alive,
164 /// and has no runtime overhead.
165 pub fn get(&self) -> &[T] {
166 // SAFETY:
167 // The pointer is valid as long as the SharedVec is alive.
168 // All other references can only get immutable reference.
169 unsafe { core::slice::from_raw_parts(self.ptr, self.len) }
170 }
171
172 /// Get a mutable reference if borrow count is 0.
173 ///
174 /// ```
175 /// use manual_share::SharedVec;
176 ///
177 /// let mut b = SharedVec::from_vec(vec![0]);
178 /// let r = b.borrow();
179 ///
180 /// assert!(b.get_mut().is_none());
181 ///
182 /// b.try_return(r).unwrap();
183 ///
184 /// let r = b.get_mut().unwrap();
185 /// r[0] += 1;
186 ///
187 /// assert_eq!(b[0], 1);
188 /// ```
189 pub fn get_mut(&mut self) -> Option<&mut [T]> {
190 if self.borrow_count == 0 {
191 // SAFETY:
192 // The pointer is valid as long as the SharedVec is alive.
193 // And there is no other references.
194 let r = unsafe { core::slice::from_raw_parts_mut(self.ptr, self.len) };
195 Some(r)
196 } else {
197 None
198 }
199 }
200}
201
202unsafe impl<T: Send> Send for SharedVec<T> {}
203unsafe impl<T: Sync> Sync for SharedVec<T> {}
204
205impl<T> Drop for SharedVec<T> {
206 fn drop(&mut self) {
207 #[cfg(feature = "panic-on-drop")]
208 {
209 // Let user deal with other panics.
210 #[cfg(feature = "do-not-panic-when-panicking")]
211 if std::thread::panicking() {
212 return;
213 }
214
215 if self.borrow_count > 0 {
216 panic!("Dropping a SharedVec without giving back all SharedVecRef")
217 }
218 }
219 // Only drops when there are no outstanding SharedBoxRef values to prevent use-after-free.
220 if self.borrow_count == 0 {
221 unsafe {
222 drop(Vec::from_raw_parts(self.ptr, self.len, self.cap));
223 }
224 }
225 }
226}
227
228impl<T> Deref for SharedVec<T> {
229 type Target = [T];
230 fn deref(&self) -> &Self::Target {
231 self.get()
232 }
233}
234
235/// A reference to `SharedVec` that can be sent to other threads.
236///
237/// Dropping a `SharedVecRef` leaks the heap allocation it points to.
238/// When the `panic-on-drop` feature is enabled, dropping it will panic:
239/// ```should_panic
240/// let mut values = manual_share::SharedVec::from_vec(vec![1]);
241/// values.borrow();
242///
243/// // forget SharedVecMut to make sure the panic is not caused by dropping it first.
244/// std::mem::forget(values);
245///
246/// // panic here due to dropping ShareVecRef
247/// ```
248///
249/// Use `SharedVec::try_return` to consume it without causing panic.
250/// ```
251/// let mut values = manual_share::SharedVec::from_vec(vec![1]);
252/// let reference = values.borrow();
253/// values.try_return(reference).unwrap();
254/// ```
255#[derive(Debug)]
256pub struct SharedVecRef<T> {
257 ptr: *const T,
258 len: usize,
259}
260
261impl<T> SharedVecRef<T> {
262 /// View the referenced data as a slice.
263 ///
264 /// ```
265 /// let mut values = manual_share::SharedVec::from_vec(vec![1, 2, 3]);
266 /// let reference = values.borrow();
267 /// assert_eq!(reference.as_slice(), &[1, 2, 3]);
268 /// values.try_return(reference).unwrap();
269 /// ```
270 pub fn as_slice(&self) -> &[T] {
271 unsafe { core::slice::from_raw_parts(self.ptr, self.len) }
272 }
273}
274
275impl<T> Drop for SharedVecRef<T> {
276 fn drop(&mut self) {
277 #[cfg(feature = "panic-on-drop")]
278 {
279 // Let user deal with other panics.
280 #[cfg(feature = "do-not-panic-when-panicking")]
281 if std::thread::panicking() {
282 return;
283 }
284
285 panic!("Dropping a SharedVecRef without returning it to the SharedVec")
286 }
287 }
288}
289
290unsafe impl<T: Sync + Send> Send for SharedVecRef<T> {}
291unsafe impl<T: Sync> Sync for SharedVecRef<T> {}
292
293impl<T> Deref for SharedVecRef<T> {
294 type Target = [T];
295 fn deref(&self) -> &Self::Target {
296 self.as_slice()
297 }
298}
299
300/// A container of a `Vec` allocation that can be split into multiple `SharedVecPart` values.
301///
302/// This type is useful when a single `Vec` needs to be partitioned into multiple independently
303/// owned segments that still refer to the same underlying allocation.
304/// ```
305/// let mut values = manual_share::SharedVecMut::from_vec(vec![1, 2, 3, 4]);
306/// let mut part = values.split_off(2).unwrap();
307///
308/// let join_handle = std::thread::spawn(|| {
309/// part.as_slice_mut().iter_mut().for_each(|v| *v += 1);
310/// part
311/// });
312///
313/// let part = join_handle.join().unwrap();
314///
315/// assert_eq!(part.as_slice(), &[4, 5]);
316/// assert!(values.try_unsplit_off(part).is_ok());
317/// ```
318///
319/// Dropping the `SharedVecMut` without returning all `SharedVecPart` values leaks the underlying allocation.
320/// When the `panic-on-drop` feature is enabled, it will panic:
321/// ```should_panic
322/// let r = {
323/// let mut values = manual_share::SharedVecMut::from_vec(vec![0]);
324/// values.split_off(1).unwrap()
325///
326/// // panic here because the part was not returned to the original SharedVecMut.
327/// };
328/// println!("{:?}", r.as_slice());
329/// ```
330#[derive(Debug)]
331pub struct SharedVecMut<T> {
332 borrow_count: usize,
333
334 ptr: *mut T,
335 len: usize,
336 cap: usize,
337
338 remain_start: usize,
339 remain_len: usize,
340}
341
342impl<T> SharedVecMut<T> {
343 /// Create a `SharedVecMut` by consuming a `Vec`.
344 pub fn from_vec(vec: Vec<T>) -> Self {
345 let (ptr, len, cap) = vec.into_raw_parts();
346 Self {
347 borrow_count: 0,
348 ptr,
349 len,
350 cap,
351 remain_start: 0,
352 remain_len: len,
353 }
354 }
355 /// Split off the suffix of the vector starting at `at`.
356 /// This method is similar to `bytes::BytesMut::split_off`.
357 ///
358 /// Returns None when:
359 /// 1. `at` is greater than the length of the vector.
360 /// 2. `borrow_count` overflows `usize`.
361 ///
362 /// If successful, the returned part will contain [at, len) and self will contain [0, at).
363 ///
364 /// Here is an example of splitting a `SharedVecMut` into 3 parts:
365 /// ```
366 /// let mut values = manual_share::SharedVecMut::from_vec(vec![1, 2, 3]);
367 ///
368 /// let part1 = values.split_off(2).unwrap();
369 /// let part2 = values.split_off(1).unwrap();
370 /// let part3 = values.split_off(0).unwrap();
371 ///
372 /// assert_eq!(part1.as_slice(), &[3]);
373 /// assert_eq!(part2.as_slice(), &[2]);
374 /// assert_eq!(part3.as_slice(), &[1]);
375 ///
376 /// values.try_unsplit_off(part3).unwrap();
377 /// values.try_unsplit_off(part2).unwrap();
378 /// values.try_unsplit_off(part1).unwrap();
379 /// ```
380 ///
381 pub fn split_off(&mut self, at: usize) -> Option<SharedVecPart<T>> {
382 if at > self.remain_len {
383 return None;
384 }
385 self.borrow_count = self.borrow_count.checked_add(1)?;
386
387 let last_len = self.remain_len;
388 self.remain_len = at;
389
390 Some(SharedVecPart {
391 ptr: self.ptr,
392 start: self.remain_start + at,
393 len: last_len - at,
394 })
395 }
396 /// Split off the prefix of the vector ending at `at`.
397 /// This method is similar to `bytes::BytesMut::split_to`.
398 ///
399 /// Returns None when:
400 /// 1. `at` is greater than the length of the vector.
401 /// 2. `borrow_count` overflows `usize`.
402 ///
403 /// If successful, the returned part will contain [0, at) and self will contain [at, len).
404 ///
405 /// Here is an example of splitting a `SharedVecMut` into 3 parts:
406 /// ```
407 /// let mut values = manual_share::SharedVecMut::from_vec(vec![1, 2, 3]);
408 ///
409 /// let part1 = values.split_to(1).unwrap();
410 /// let part2 = values.split_to(1).unwrap();
411 /// let part3 = values.split_to(1).unwrap();
412 ///
413 /// assert_eq!(part1.as_slice(), &[1]);
414 /// assert_eq!(part2.as_slice(), &[2]);
415 /// assert_eq!(part3.as_slice(), &[3]);
416 ///
417 /// values.try_unsplit_to(part3).unwrap();
418 /// values.try_unsplit_to(part2).unwrap();
419 /// values.try_unsplit_to(part1).unwrap();
420 /// ```
421 pub fn split_to(&mut self, at: usize) -> Option<SharedVecPart<T>> {
422 if at > self.remain_len {
423 return None;
424 }
425 self.borrow_count = self.borrow_count.checked_add(1)?;
426
427 let last_start = self.remain_start;
428 self.remain_start += at;
429 self.remain_len -= at;
430
431 Some(SharedVecPart {
432 ptr: self.ptr,
433 start: last_start,
434 len: at,
435 })
436 }
437 /// Try to unsplit a part that was previously split off with `split_off`.
438 pub fn try_unsplit_off(&mut self, part: SharedVecPart<T>) -> Result<(), SharedVecPart<T>> {
439 if !core::ptr::eq(self.ptr, part.ptr) {
440 return Err(part);
441 }
442 if part.start != self.remain_start + self.remain_len {
443 return Err(part);
444 }
445
446 self.remain_len += part.len;
447
448 self.consume_part(part)
449 }
450 /// Try to unsplit a part that was previously split off with `split_to`.
451 pub fn try_unsplit_to(&mut self, part: SharedVecPart<T>) -> Result<(), SharedVecPart<T>> {
452 if !core::ptr::eq(self.ptr, part.ptr) {
453 return Err(part);
454 }
455 if self.remain_start != part.start + part.len {
456 return Err(part);
457 }
458
459 self.remain_start = part.start;
460 self.remain_len += part.len;
461
462 self.consume_part(part)
463 }
464 fn consume_part(&mut self, part: SharedVecPart<T>) -> Result<(), SharedVecPart<T>> {
465 if size_of::<T>() == 0 {
466 // ZST types can have multiple allocations to the same address, so we need to check for overflow.
467 if let Some(new_count) = self.borrow_count.checked_sub(1) {
468 self.borrow_count = new_count;
469 let _ = core::mem::ManuallyDrop::new(part);
470 Ok(())
471 } else {
472 Err(part)
473 }
474 } else {
475 self.borrow_count -= 1;
476 let _ = core::mem::ManuallyDrop::new(part);
477 Ok(())
478 }
479 }
480 fn can_convert_back(&self) -> bool {
481 self.borrow_count == 0
482 && self.remain_start == 0
483 && if size_of::<T>() == 0 {
484 self.remain_len == self.len
485 } else {
486 true
487 }
488 }
489 /// Try to convert the mutable view back into a `Vec` when no parts remain outstanding.
490 /// Note that the returned error type is `Self`, dropping it may cause panic.
491 pub fn try_into_vec(self) -> Result<Vec<T>, Self> {
492 if self.can_convert_back() {
493 let r = core::mem::ManuallyDrop::new(self);
494 let vec = unsafe { Vec::from_raw_parts(r.ptr, r.remain_len, r.cap) };
495
496 Ok(vec)
497 } else {
498 Err(self)
499 }
500 }
501 /// Directly get a slice of the remaining part of the `SharedVecMut`.
502 /// ```
503 /// let mut values = manual_share::SharedVecMut::from_vec(vec![1, 2, 3]);
504 ///
505 /// let part1 = values.split_to(1).unwrap();
506 /// let part2 = values.split_off(1).unwrap();
507 ///
508 /// assert_eq!(values.as_slice(), &[2]);
509 /// assert_eq!(part1.as_slice(), &[1]);
510 /// assert_eq!(part2.as_slice(), &[3]);
511 ///
512 /// values.try_unsplit_off(part2).unwrap();
513 /// values.try_unsplit_to(part1).unwrap();
514 /// assert_eq!(values.as_slice(), &[1, 2, 3]);
515 /// ```
516 ///
517 /// Further splitting is no longer possible as long as the returned slice is held alive:
518 /// ```compile_fail
519 /// let mut values = manual_share::SharedVecMut::from_vec(vec![1, 2, 3]);
520 /// let slice = values.as_slice();
521 /// let part = values.split_off(1).unwrap();
522 ///
523 /// println!("{:?}", slice);
524 /// ```
525 pub fn as_slice(&self) -> &[T] {
526 // SAFETY:
527 // The pointer is valid as long as the SharedVecMut is alive.
528 // SharedVecPart cannot point to the same or overlapping region as self.
529 // Also, splitting methods can't be called when the returned slice is alive.
530 unsafe { core::slice::from_raw_parts(self.ptr.add(self.remain_start), self.remain_len) }
531 }
532 /// Directly get a mutable slice of the remaining part of the `SharedVecMut`.
533 pub fn as_slice_mut(&mut self) -> &mut [T] {
534 // SAFETY:
535 // The pointer is valid as long as the SharedVecMut is alive.
536 // SharedVecPart cannot point to the same or overlapping region as self.
537 // Also, splitting methods can't be called when the returned slice is alive.
538 unsafe { core::slice::from_raw_parts_mut(self.ptr.add(self.remain_start), self.remain_len) }
539 }
540}
541
542unsafe impl<T: Send> Send for SharedVecMut<T> {}
543unsafe impl<T: Sync> Sync for SharedVecMut<T> {}
544
545impl<T> Drop for SharedVecMut<T> {
546 fn drop(&mut self) {
547 #[cfg(feature = "panic-on-drop")]
548 {
549 // Let user deal with other panics.
550 #[cfg(feature = "do-not-panic-when-panicking")]
551 if std::thread::panicking() {
552 return;
553 }
554
555 if self.borrow_count > 0 {
556 panic!("Dropping a SharedVecMut without giving back all SharedVecRef")
557 }
558 }
559
560 if self.can_convert_back() {
561 unsafe {
562 drop(Vec::from_raw_parts(self.ptr, self.len, self.cap));
563 }
564 }
565 }
566}
567
568impl<T> Deref for SharedVecMut<T> {
569 type Target = [T];
570 fn deref(&self) -> &Self::Target {
571 self.as_slice()
572 }
573}
574
575impl<T> DerefMut for SharedVecMut<T> {
576 fn deref_mut(&mut self) -> &mut Self::Target {
577 self.as_slice_mut()
578 }
579}
580
581/// A slice-like view into a segment of a `SharedVecMut` allocation.
582///
583/// It can be read as a slice or mutated in place while the underlying allocation is still owned
584/// by the original `SharedVecMut`.
585///
586/// Dropping a `SharedVecPart` leaks the underlying allocation.
587/// When the **`panic-on-drop`** feature is enabled, dropping it will panic:
588/// ```should_panic
589/// let mut values = manual_share::SharedVecMut::from_vec(vec![1, 2, 3, 4]);
590/// let mut part = values.split_off(2).unwrap();
591///
592/// // forget SharedVecMut to make sure the panic is not caused by dropping it first.
593/// std::mem::forget(values);
594///
595/// // panic here due to dropping ShareVecPart
596/// ```
597#[derive(Debug)]
598pub struct SharedVecPart<T> {
599 ptr: *mut T,
600 start: usize,
601 len: usize,
602}
603
604impl<T> SharedVecPart<T> {
605 /// View the part as an immutable slice.
606 pub fn as_slice(&self) -> &[T] {
607 unsafe { core::slice::from_raw_parts(self.ptr.add(self.start), self.len) }
608 }
609 /// View the part as a mutable slice.
610 pub fn as_slice_mut(&mut self) -> &mut [T] {
611 unsafe { core::slice::from_raw_parts_mut(self.ptr.add(self.start), self.len) }
612 }
613}
614
615impl<T> Drop for SharedVecPart<T> {
616 fn drop(&mut self) {
617 #[cfg(feature = "panic-on-drop")]
618 {
619 // Let user deal with other panics.
620 #[cfg(feature = "do-not-panic-when-panicking")]
621 if std::thread::panicking() {
622 return;
623 }
624
625 panic!("Dropping a SharedVecPart without returning it to the SharedVecMut")
626 }
627 }
628}
629
630unsafe impl<T: Send> Send for SharedVecPart<T> {}
631unsafe impl<T: Sync> Sync for SharedVecPart<T> {}
632
633impl<T> Deref for SharedVecPart<T> {
634 type Target = [T];
635 fn deref(&self) -> &Self::Target {
636 self.as_slice()
637 }
638}
639
640impl<T> DerefMut for SharedVecPart<T> {
641 fn deref_mut(&mut self) -> &mut Self::Target {
642 self.as_slice_mut()
643 }
644}
645
646#[cfg(test)]
647mod test {
648 use super::*;
649
650 #[test]
651 fn zst() {
652 let mut b1: SharedVec<()> = SharedVec::from_vec(Vec::new());
653 let mut b2: SharedVec<()> = SharedVec::from_vec(Vec::new());
654
655 let r11 = b1.borrow();
656 let r12 = b1.borrow();
657
658 let r2 = b2.borrow();
659
660 b1.try_return(r2).unwrap();
661
662 b1.try_return(r11).unwrap();
663 let r12 = b1.try_return(r12).unwrap_err();
664
665 b2.try_return(r12).unwrap();
666 }
667
668 #[test]
669 fn zst_different_length() {
670 let mut b1 = SharedVec::from_vec(vec![()]);
671 let mut b2 = SharedVec::from_vec(vec![(), ()]);
672
673 let r1 = b1.borrow();
674 let r2 = b2.borrow();
675
676 let r2 = b1.try_return(r2).unwrap_err();
677 let r1 = b2.try_return(r1).unwrap_err();
678
679 b1.try_return(r1).unwrap();
680 b2.try_return(r2).unwrap();
681 }
682
683 #[test]
684 fn mut_zst() {
685 let mut b1: SharedVecMut<()> = SharedVecMut::from_vec(Vec::new());
686 let mut b2: SharedVecMut<()> = SharedVecMut::from_vec(Vec::new());
687
688 let r11 = b1.split_off(0).unwrap();
689 let r12 = b1.split_off(0).unwrap();
690
691 let r2 = b2.split_off(0).unwrap();
692
693 b1.try_unsplit_off(r2).unwrap();
694
695 b1.try_unsplit_off(r11).unwrap();
696 let r12 = b1.try_unsplit_off(r12).unwrap_err();
697
698 b2.try_unsplit_off(r12).unwrap();
699 }
700
701 #[test]
702 fn mut_zst_different_length() {
703 let mut b1 = SharedVecMut::from_vec(vec![(), ()]);
704 let mut b2 = SharedVecMut::from_vec(vec![()]);
705
706 let r1 = b1.split_off(0).unwrap();
707 let r2 = b2.split_off(0).unwrap();
708
709 b1.try_unsplit_off(r2).unwrap();
710
711 let mut b1 = b1.try_into_vec().unwrap_err();
712
713 let r2 = b1.split_off(0).unwrap();
714
715 b1.try_unsplit_off(r1).unwrap();
716 b2.try_unsplit_off(r2).unwrap();
717
718 assert_eq!(b1.try_into_vec().unwrap(), [(), ()]);
719 assert_eq!(b2.try_into_vec().unwrap(), [()]);
720 }
721}