]>
Commit | Line | Data |
---|---|---|
fc512014 XL |
1 | use rustc_index::vec::{Idx, IndexVec}; |
2 | use std::mem; | |
fc512014 | 3 | |
a2a8927a | 4 | pub trait IdFunctor: Sized { |
fc512014 XL |
5 | type Inner; |
6 | ||
a2a8927a | 7 | fn try_map_id<F, E>(self, f: F) -> Result<Self, E> |
fc512014 | 8 | where |
a2a8927a | 9 | F: FnMut(Self::Inner) -> Result<Self::Inner, E>; |
fc512014 XL |
10 | } |
11 | ||
12 | impl<T> IdFunctor for Box<T> { | |
13 | type Inner = T; | |
14 | ||
15 | #[inline] | |
a2a8927a | 16 | fn try_map_id<F, E>(self, mut f: F) -> Result<Self, E> |
fc512014 | 17 | where |
a2a8927a | 18 | F: FnMut(Self::Inner) -> Result<Self::Inner, E>, |
fc512014 XL |
19 | { |
20 | let raw = Box::into_raw(self); | |
a2a8927a | 21 | Ok(unsafe { |
fc512014 | 22 | // SAFETY: The raw pointer points to a valid value of type `T`. |
a2a8927a | 23 | let value = raw.read(); |
fc512014 XL |
24 | // SAFETY: Converts `Box<T>` to `Box<MaybeUninit<T>>` which is the |
25 | // inverse of `Box::assume_init()` and should be safe. | |
a2a8927a | 26 | let raw: Box<mem::MaybeUninit<T>> = Box::from_raw(raw.cast()); |
fc512014 | 27 | // SAFETY: Write the mapped value back into the `Box`. |
a2a8927a XL |
28 | Box::write(raw, f(value)?) |
29 | }) | |
fc512014 XL |
30 | } |
31 | } | |
32 | ||
33 | impl<T> IdFunctor for Vec<T> { | |
34 | type Inner = T; | |
35 | ||
36 | #[inline] | |
a2a8927a | 37 | fn try_map_id<F, E>(self, mut f: F) -> Result<Self, E> |
fc512014 | 38 | where |
a2a8927a | 39 | F: FnMut(Self::Inner) -> Result<Self::Inner, E>, |
fc512014 | 40 | { |
a2a8927a XL |
41 | struct HoleVec<T> { |
42 | vec: Vec<mem::ManuallyDrop<T>>, | |
43 | hole: Option<usize>, | |
44 | } | |
45 | ||
46 | impl<T> Drop for HoleVec<T> { | |
47 | fn drop(&mut self) { | |
48 | unsafe { | |
49 | for (index, slot) in self.vec.iter_mut().enumerate() { | |
50 | if self.hole != Some(index) { | |
51 | mem::ManuallyDrop::drop(slot); | |
52 | } | |
53 | } | |
54 | } | |
55 | } | |
56 | } | |
57 | ||
fc512014 | 58 | unsafe { |
a2a8927a XL |
59 | let (ptr, length, capacity) = self.into_raw_parts(); |
60 | let vec = Vec::from_raw_parts(ptr.cast(), length, capacity); | |
61 | let mut hole_vec = HoleVec { vec, hole: None }; | |
62 | ||
63 | for (index, slot) in hole_vec.vec.iter_mut().enumerate() { | |
64 | hole_vec.hole = Some(index); | |
65 | let original = mem::ManuallyDrop::take(slot); | |
66 | let mapped = f(original)?; | |
67 | *slot = mem::ManuallyDrop::new(mapped); | |
68 | hole_vec.hole = None; | |
fc512014 | 69 | } |
a2a8927a XL |
70 | |
71 | mem::forget(hole_vec); | |
72 | Ok(Vec::from_raw_parts(ptr, length, capacity)) | |
fc512014 | 73 | } |
fc512014 XL |
74 | } |
75 | } | |
76 | ||
77 | impl<T> IdFunctor for Box<[T]> { | |
78 | type Inner = T; | |
79 | ||
80 | #[inline] | |
a2a8927a | 81 | fn try_map_id<F, E>(self, f: F) -> Result<Self, E> |
fc512014 | 82 | where |
a2a8927a | 83 | F: FnMut(Self::Inner) -> Result<Self::Inner, E>, |
fc512014 | 84 | { |
a2a8927a | 85 | Vec::from(self).try_map_id(f).map(Into::into) |
fc512014 XL |
86 | } |
87 | } | |
88 | ||
89 | impl<I: Idx, T> IdFunctor for IndexVec<I, T> { | |
90 | type Inner = T; | |
91 | ||
92 | #[inline] | |
a2a8927a | 93 | fn try_map_id<F, E>(self, f: F) -> Result<Self, E> |
fc512014 | 94 | where |
a2a8927a | 95 | F: FnMut(Self::Inner) -> Result<Self::Inner, E>, |
fc512014 | 96 | { |
a2a8927a | 97 | self.raw.try_map_id(f).map(IndexVec::from_raw) |
fc512014 XL |
98 | } |
99 | } |