Guest User

Untitled

a guest
Oct 23rd, 2018
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.54 KB | None | 0 0
  1. #![feature(unsize)]
  2.  
  3. mod heterogeneous_vec {
  4. use std::alloc::{self, Layout};
  5. use std::mem;
  6. use std::num::NonZeroUsize;
  7. use std::ptr;
  8.  
  9. pub struct HeterogeneousVec {
  10. ptr: *mut u8,
  11. // In bytes:
  12. len: usize,
  13. capacity: usize,
  14. align: NonZeroUsize,
  15. }
  16.  
  17. unsafe fn realloc_with_align(ptr: *mut u8, old_layout: Layout, new_layout: Layout)
  18. -> *mut u8 {
  19. if new_layout.align() == old_layout.align() {
  20. alloc::realloc(ptr, old_layout, new_layout.size())
  21. } else {
  22. let new_ptr = alloc::alloc(new_layout);
  23. if !new_ptr.is_null() {
  24. let size = old_layout.size().min(new_layout.size());
  25. ptr::copy_nonoverlapping(ptr, new_ptr, size);
  26. alloc::dealloc(ptr, old_layout);
  27. }
  28. new_ptr
  29. }
  30. }
  31.  
  32. fn align_to(position: usize, align: usize) -> usize {
  33. let remainder = position % align;
  34. if remainder > 0 {
  35. position.checked_add(align - remainder).unwrap()
  36. } else {
  37. position
  38. }
  39. }
  40.  
  41. impl HeterogeneousVec {
  42. pub fn new() -> Self {
  43. Self {
  44. ptr: ptr::null_mut(),
  45. len: 0,
  46. capacity: 0,
  47. align: NonZeroUsize::new(1).unwrap(),
  48. }
  49. }
  50.  
  51. pub fn push<T>(&mut self, value: T) {
  52. let value_size = mem::size_of::<T>();
  53. let value_align = mem::align_of::<T>();
  54. let value_position = align_to(self.len, value_align);
  55. let available = self.capacity.saturating_sub(value_position);
  56. let align = self.align.get();
  57. if available < value_size || align < value_align {
  58. let required_capacity = self.len.checked_add(value_size).unwrap();
  59. let new_capacity = self.capacity.max(required_capacity).next_power_of_two();
  60. let new_align = align.max(value_align);
  61. let new_layout = Layout::from_size_align(new_capacity, new_align).unwrap();
  62. let ptr = unsafe {
  63. if self.ptr.is_null() {
  64. alloc::alloc(new_layout)
  65. } else {
  66. let old_layout = Layout::from_size_align(self.capacity, align).unwrap();
  67. realloc_with_align(self.ptr, old_layout, new_layout)
  68. }
  69. };
  70. if ptr.is_null() {
  71. alloc::handle_alloc_error(new_layout)
  72. }
  73. self.ptr = ptr;
  74. self.capacity = new_capacity;
  75. }
  76. unsafe {
  77. let next = self.ptr.add(value_position) as *mut T;
  78. debug_assert!(next as usize % value_align == 0);
  79. next.write(value);
  80. }
  81. self.len = value_position + value_size;
  82. }
  83.  
  84. pub fn iter(&self) -> Iter {
  85. Iter { vec: self, position: 0 }
  86. }
  87. }
  88.  
  89. pub struct Iter<'a> {
  90. vec: &'a HeterogeneousVec,
  91. position: usize,
  92. }
  93.  
  94. impl<'a> Iter<'a> {
  95. pub unsafe fn read_next<T>(&mut self) -> Option<T> {
  96. self.next(Layout::new::<T>()).map(|ptr| (ptr as *mut T).read())
  97. }
  98.  
  99. pub unsafe fn next(&mut self, layout: Layout) -> Option<*mut ()> {
  100. if self.position < self.vec.len {
  101. let value_position = align_to(self.position, layout.align());
  102. let ptr = self.vec.ptr.add(value_position);
  103. self.position = value_position + layout.size();
  104. debug_assert!(self.position <= self.vec.len);
  105. Some(ptr as *mut ())
  106. } else {
  107. None
  108. }
  109. }
  110. }
  111. }
  112.  
  113. use std::alloc::Layout;
  114. use std::marker::{PhantomData, Unsize};
  115. use std::ptr;
  116.  
  117. struct VTable<DST: ?Sized> {
  118. new_dangling: fn() -> *mut DST,
  119. }
  120.  
  121. trait HasVTableFor<DST: ?Sized + 'static> {
  122. const VTABLE: VTable<DST>;
  123. }
  124.  
  125. impl<T, DST: ?Sized + 'static> HasVTableFor<DST> for T where T: Unsize<DST> {
  126. const VTABLE: VTable<DST> = VTable {
  127. new_dangling: || <ptr::NonNull<T>>::dangling().as_ptr()
  128. };
  129. }
  130.  
  131. pub struct VecOfDst<DST: ?Sized + 'static> {
  132. storage: heterogeneous_vec::HeterogeneousVec,
  133. _phantom: PhantomData<DST>,
  134. }
  135.  
  136. impl<DST: ?Sized + 'static> VecOfDst<DST> {
  137. pub fn new() -> Self {
  138. Self {
  139. storage: heterogeneous_vec::HeterogeneousVec::new(),
  140. _phantom: PhantomData,
  141. }
  142. }
  143.  
  144. pub fn push<T: Unsize<DST>>(&mut self, value: T) {
  145. self.storage.push(<T as HasVTableFor<DST>>::VTABLE);
  146. self.storage.push(value);
  147. }
  148.  
  149. pub fn iter(&self) -> impl Iterator<Item=&DST> {
  150. self.iter_raw().map(|ptr| unsafe { &*ptr })
  151. }
  152.  
  153. pub fn iter_mut(&mut self) -> impl Iterator<Item=&mut DST> {
  154. self.iter_raw().map(|ptr| unsafe { &mut *ptr })
  155. }
  156.  
  157. fn iter_raw<'a>(&'a self) -> impl Iterator<Item=*mut DST> + 'a {
  158. struct Iter<'a, DST: ?Sized> {
  159. iter: heterogeneous_vec::Iter<'a>,
  160. _phantom: PhantomData<DST>,
  161. }
  162.  
  163. impl<'a, DST: ?Sized> Iterator for Iter<'a, DST> {
  164. type Item = *mut DST;
  165.  
  166. fn next(&mut self) -> Option<Self::Item> {
  167. unsafe {
  168. self.iter.read_next::<VTable<DST>>().map(|vtable| {
  169. let mut ptr = (vtable.new_dangling)();
  170. let layout = Layout::for_value(&*ptr);
  171. let data_ptr = self.iter.next(layout).unwrap();
  172. ptr::write(&mut ptr as *mut _ as _, data_ptr);
  173. ptr
  174. })
  175. }
  176. }
  177. }
  178.  
  179. Iter {
  180. iter: self.storage.iter(),
  181. _phantom: PhantomData,
  182. }
  183. }
  184. }
  185.  
  186. impl<DST: ?Sized + 'static> Drop for VecOfDst<DST> {
  187. fn drop(&mut self) {
  188. for item in self.iter_raw() {
  189. unsafe {
  190. item.drop_in_place()
  191. }
  192. }
  193. }
  194. }
  195.  
  196. #[test]
  197. fn trait_objets() {
  198. #[repr(align(1024))]
  199. #[derive(Debug)]
  200. struct SuperAligned(u32);
  201.  
  202. let mut v = VecOfDst::<dyn std::fmt::Debug>::new();
  203. v.push(4);
  204. v.push(SuperAligned(7));
  205. v.push("foo");
  206. assert_eq!(debugs(v.iter()), ["4", "SuperAligned(7)", "\"foo\""]);
  207. }
  208.  
  209. #[test]
  210. fn slices() {
  211. let mut v = VecOfDst::<[u32]>::new();
  212. v.push([4]);
  213. v.push([9000, 1, 3]);
  214. assert_eq!(debugs(v.iter()), ["[4]", "[9000, 1, 3]"]);
  215. }
  216.  
  217. #[cfg(test)]
  218. fn debugs<I>(iter: I) -> Vec<String>
  219. where I: Iterator, I::Item: std::fmt::Debug
  220. {
  221. iter.map(|x| format!("{:?}", x)).collect()
  222. }
Add Comment
Please, Sign In to add comment