Advertisement
Guest User

Untitled

a guest
Sep 17th, 2019
100
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.44 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. while self.init_len < self.len {
  50. unsafe {
  51. let value = f(self.ptr.read());
  52. (self.ptr as *mut U).write(value);
  53.  
  54. self.ptr = self.ptr.add(1);
  55. self.init_len += 1;
  56. }
  57. }
  58.  
  59. let ptr = self.start;
  60. let len = self.len;
  61. let cap = self.cap;
  62.  
  63. // we don't want to free the memory
  64. // which is what dropping this `MapIter` will do
  65. std::mem::forget(self);
  66.  
  67. unsafe {
  68. Vec::from_raw_parts(ptr, len, cap)
  69. }
  70. }
  71. }
  72.  
  73. impl<T, U> Drop for MapIter<T, U> {
  74. fn drop(&mut self) {
  75. unsafe {
  76. // assert!(std::thread::panicking());
  77.  
  78. // offset by 1 because self.ptr is pointing to
  79. // memory that was just read from, dropping that
  80. // would lead to a double free
  81. std::ptr::drop_in_place(
  82. std::slice::from_raw_parts_mut(
  83. self.ptr.add(1),
  84. self.len - self.init_len - 1,
  85. )
  86. );
  87.  
  88. Vec::from_raw_parts(
  89. self.start,
  90. self.init_len,
  91. self.cap
  92. );
  93. }
  94. }
  95. }
  96.  
  97. fn main() {
  98. assert_eq!(
  99. vec![0u32, 1, 2, 3, 4].map(|x| x as f32),
  100. [0.0, 1.0, 2.0, 3.0, 4.0]
  101. );
  102. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement