Advertisement
Guest User

Untitled

a guest
Sep 17th, 2019
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.33 KB | None | 0 0
  1. use std::marker::PhantomData;
  2.  
  3. trait VecExt: Sized {
  4. type T;
  5.  
  6. fn map<U, F: FnMut(Self::T) -> U>(self, f: F) -> Vec<U>;
  7. }
  8.  
  9. impl<T> VecExt for Vec<T> {
  10. type T = T;
  11.  
  12. fn map<U, F: FnMut(Self::T) -> U>(mut self, f: F) -> Vec<U> {
  13. use std::alloc::Layout;
  14.  
  15. if Layout::new::<T>() == Layout::new::<U>() {
  16. let len = self.len();
  17. let cap = self.capacity();
  18. let ptr = self.as_mut_ptr();
  19.  
  20. std::mem::forget(self);
  21.  
  22. let iter = MapIter {
  23. start: ptr as *mut U,
  24. ptr,
  25. init_len: 0,
  26. len,
  27. cap,
  28. drop: PhantomData
  29. };
  30.  
  31. iter.into_vec(f)
  32. } else {
  33. self.into_iter().map(f).collect()
  34. }
  35. }
  36. }
  37.  
  38. struct MapIter<T, U> {
  39. start: *mut U,
  40. ptr: *mut T,
  41. init_len: usize,
  42. len: usize,
  43. cap: usize,
  44. drop: PhantomData<(T, U)>
  45. }
  46.  
  47. impl<T, U> MapIter<T, U> {
  48. fn into_vec<F: FnMut(T) -> U>(mut self, mut f: F) -> Vec<U> {
  49. for i in 0..self.len {
  50. unsafe {
  51. self.init_len = i;
  52.  
  53. let value = f(self.ptr.read());
  54. (self.ptr as *mut U).write(value);
  55.  
  56. self.ptr = self.ptr.add(1);
  57. }
  58. }
  59.  
  60. let ptr = self.start;
  61. let len = self.len;
  62. let cap = self.cap;
  63.  
  64. // we don't want to free the memory
  65. // which is what dropping this `MapIter` will do
  66. std::mem::forget(self);
  67.  
  68. unsafe {
  69. Vec::from_raw_parts(ptr, len, cap)
  70. }
  71. }
  72. }
  73.  
  74. impl<T, U> Drop for MapIter<T, U> {
  75. fn drop(&mut self) {
  76. unsafe {
  77. // assert!(std::thread::panicking());
  78.  
  79. // offset by 1 because self.ptr is pointing to
  80. // memory that was just read from, dropping that
  81. // would lead to a double free
  82. std::ptr::drop_in_place(
  83. std::slice::from_raw_parts_mut(
  84. self.ptr.add(1),
  85. self.len - self.init_len - 1,
  86. )
  87. );
  88.  
  89. Vec::from_raw_parts(
  90. self.start,
  91. self.init_len,
  92. self.cap
  93. );
  94. }
  95. }
  96. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement