Guest User

Untitled

a guest
Jan 19th, 2019
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.82 KB | None | 0 0
  1. /// Implement this trait to opt-in your type to `MultiGet`.
  2. ///
  3. /// The methods should be trivial passthroughs to the existing
  4. /// `get_mut` and `index_mut` methods.
  5. ///
  6. /// # Safety
  7. ///
  8. /// This trait is unsafe because by implementing it you're promising that
  9. /// it's ok for multiple mutable references from these methods to be alive
  10. /// at the same time so long as they're at different addresses.
  11. pub unsafe trait SingleGet<Idx=usize> {
  12. type Output;
  13. fn single_get(&mut self, i: Idx) -> Option<&mut Self::Output>;
  14. fn single_index(&mut self, i: Idx) -> &mut Self::Output;
  15. }
  16.  
  17. unsafe impl<T> SingleGet for Vec<T> {
  18. type Output = T;
  19. fn single_get(&mut self, i: usize) -> Option<&mut T> { self.get_mut(i) }
  20. fn single_index(&mut self, i: usize) -> &mut T { &mut self[i] }
  21. }
  22.  
  23. pub trait MultiGet<'a, Args: internals::MultiGetArgs<'a, Self>>: Sized {
  24. fn multi_get(&'a mut self, args: Args) -> Option<Args::GetOutput>;
  25. fn multi_index(&'a mut self, args: Args) -> Args::IndexOutput;
  26. }
  27. impl<'a, T, A: internals::MultiGetArgs<'a, T>> MultiGet<'a, A> for T {
  28. fn multi_get(&'a mut self, a: A) -> Option<A::GetOutput> {
  29. a.get(self)
  30. }
  31.  
  32. fn multi_index(&'a mut self, a: A) -> A::IndexOutput {
  33. a.index(self)
  34. }
  35. }
  36.  
  37. mod internals {
  38. use super::*;
  39.  
  40. pub trait MultiGetArgs<'a, T> {
  41. type GetOutput;
  42. fn get(self, t: &'a mut T) -> Option<Self::GetOutput>;
  43. type IndexOutput;
  44. fn index(self, t: &'a mut T) -> Self::IndexOutput;
  45. }
  46.  
  47. trait TupleAsSlice<T> {
  48. fn on_slice<F, R>(&self, f: F) -> R
  49. where F: FnOnce(&[&T]) -> R;
  50. fn any<F>(&self, f: F) -> bool
  51. where F: Fn(&T) -> bool
  52. {
  53. self.on_slice(|s| s.iter().any(|&x| f(x)))
  54. }
  55. }
  56.  
  57. trait TupleMap<T, U> {
  58. type Output;
  59. fn map<F>(self, f: F) -> Self::Output
  60. where F: FnMut(T) -> U;
  61. }
  62.  
  63. macro_rules! replace_type {
  64. ($_t:tt => $sub:ty) => {$sub};
  65. }
  66. macro_rules! impl_tuple_ops {
  67. () => { impl_tuple_ops!(@); };
  68. ( $i0:ident $($i:ident)* ) => {
  69. impl_tuple_ops!( $($i)* );
  70. impl_tuple_ops!(@ $i0 $($i)* );
  71. };
  72. (@ $($i:ident)* ) => {
  73.  
  74. impl<T> TupleAsSlice<T> for ( $( replace_type!($i => T), )* ) {
  75. fn on_slice<F, R>(&self, f: F) -> R
  76. where F: FnOnce(&[&T]) -> R
  77. {
  78. let &( $(ref $i,)* ) = self;
  79. let slice = [ $($i,)* ];
  80. f(&slice)
  81. }
  82. }
  83.  
  84. impl<T,U> TupleMap<T,U> for ( $( replace_type!($i => T), )* ) {
  85. type Output = ( $( replace_type!($i => U), )* );
  86. #[allow(unused_variables, unused_mut)]
  87. fn map<F>(self, mut f: F) -> Self::Output
  88. where F: FnMut(T) -> U
  89. {
  90. let ( $($i,)* ) = self;
  91. ( $(f($i),)* )
  92. }
  93. }
  94. };
  95. }
  96. impl_tuple_ops!(a b c d e f g h i);
  97.  
  98. macro_rules! impl_multi_get {
  99. () => { impl_multi_get!(@); };
  100. ( $i0:ident $($i:ident)* ) => {
  101. impl_multi_get!( $($i)* );
  102. impl_multi_get!(@ $i0 $($i)* );
  103. };
  104. (@) => {
  105. impl<'a, T: 'a> MultiGetArgs<'a, T> for () {
  106. type GetOutput = ();
  107. fn get(self, _: &'a mut T) -> Option<()> { Some(()) }
  108. type IndexOutput = ();
  109. fn index(self, _: &'a mut T) -> () { () }
  110. }
  111. };
  112. (@ $($i:ident)+ ) => {
  113.  
  114. impl<'a, T: 'a, I> MultiGetArgs<'a, T> for ( $( replace_type!($i => I), )* )
  115. where T: SingleGet<I>, T::Output: 'a
  116. {
  117. type GetOutput = ( $( replace_type!($i => Option<&'a mut T::Output>), )* );
  118. fn get(self, t: &'a mut T) -> Option<Self::GetOutput> {
  119. let pointers = self.map(|i| option_as_mut_ptr(t.single_get(i)));
  120. if pointers.on_slice(duplicate_positions).is_some() {
  121. None
  122. } else {
  123. unsafe { Some(pointers.map(|p| p.as_mut())) }
  124. }
  125. }
  126.  
  127. type IndexOutput = ( $( replace_type!($i => &'a mut T::Output), )* );
  128. fn index(self, t: &'a mut T) -> Self::IndexOutput {
  129. let pointers = self.map(|i| t.single_index(i) as *mut _);
  130. if let Some((i, j)) = pointers.on_slice(duplicate_positions) {
  131. panic!("Aliasing violation between args.{} and args.{}", i, j);
  132. }
  133. pointers.map(|p| unsafe { &mut* p })
  134. }
  135. }
  136. };
  137. }
  138. impl_multi_get!(a b c d e f g h i);
  139.  
  140. fn option_as_mut_ptr<T>(x: Option<&mut T>) -> *mut T {
  141. x.map_or(std::ptr::null_mut(), |r| r as *mut _)
  142. }
  143.  
  144. fn duplicate_positions<T>(s: &[&*mut T]) -> Option<(usize, usize)> {
  145. for (i, &p) in s.iter().enumerate() {
  146. if !p.is_null() {
  147. if let Some(j) = s[..i].iter().position(|&q| p == q) {
  148. return Some((j, i));
  149. }
  150. }
  151. }
  152. None
  153. }
  154. }
  155.  
  156. #[cfg(test)]
  157. mod tests {
  158. use super::MultiGet;
  159.  
  160. #[test]
  161. fn it_works() {
  162. let mut v = vec![1, 2, 3, 4, 5];
  163. assert_eq!(v.multi_index(()), ());
  164. assert_eq!(v.multi_get(()), Some(()));
  165. {
  166. let (a,) = v.multi_index((2,));
  167. *a = 9;
  168. }
  169. assert_eq!(v, vec![1, 2, 9, 4, 5]);
  170. {
  171. let (a, b) = v.multi_index((1, 3));
  172. ::std::mem::swap(a, b);
  173. }
  174. assert_eq!(v, vec![1, 4, 9, 2, 5]);
  175. }
  176.  
  177. #[test]
  178. #[should_panic(expected = "Aliasing violation between args.0 and args.2")]
  179. fn foo() {
  180. let mut v = vec![1, 2, 3, 4, 5];
  181. v.multi_index((0,1,0));
  182. }
  183. }
Add Comment
Please, Sign In to add comment