Skip to main content

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}