Advertisement
Guest User

Untitled

a guest
Mar 19th, 2019
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.64 KB | None | 0 0
  1. mod some_lib {
  2. use crate::rel_ptr::RelPtr;
  3.  
  4. mod ffi {
  5. pub
  6. struct Context ([u8; 3]);
  7.  
  8. pub
  9. struct Thing (());
  10.  
  11. pub
  12. unsafe extern "C" fn mk_context () -> Context
  13. { Context([0; 3]) }
  14.  
  15. pub
  16. unsafe extern "C" fn mk_thing (_: *mut Context) -> Thing
  17. { Thing(()) }
  18.  
  19. pub
  20. unsafe extern "C" fn free_thing (ctx: *mut Context, thing: *mut Thing)
  21. {
  22. eprintln!(
  23. "[C] Freeing thing at {:p}, with context at {:p}",
  24. thing,
  25. ctx,
  26. );
  27. }
  28.  
  29. pub
  30. unsafe extern "C" fn free_context (ctx: *mut Context)
  31. {
  32. eprintln!( "[C] Freeing context at {:p}", ctx);
  33. }
  34. }
  35.  
  36. #[repr(transparent)]
  37. pub
  38. struct Context (ffi::Context);
  39. impl Context {
  40. pub
  41. fn new () -> Self
  42. {
  43. Context(unsafe { ffi::mk_context() })
  44. }
  45. }
  46. impl Drop for Context { fn drop (&mut self) {
  47. unsafe { ffi::free_context(&mut self.0) }
  48. }}
  49.  
  50. pub
  51. struct Thing (
  52. Option<(ffi::Thing, RelPtr<Context>)>
  53. );
  54. impl Thing {
  55. pub
  56. fn new () -> Self {
  57. Thing(None)
  58. }
  59.  
  60. /// # Safety
  61. ///
  62. /// The relative offset between `*self` and `*context` must not change
  63. pub
  64. unsafe fn init (
  65. self: &'_ mut Self,
  66. context: &'_ mut Context,
  67. )
  68. {
  69. *self = Thing(Some((
  70. ffi::mk_thing(&mut context.0),
  71. RelPtr::default(),
  72. )));
  73. if let Thing(Some((_, ref mut rel_ptr))) = *self {
  74. rel_ptr.set(context)
  75. } else {
  76. ::std::hint::unreachable_unchecked()
  77. }
  78. }
  79.  
  80. pub
  81. fn get_thing (
  82. self: &'_ Self,
  83. ) -> Option<&'_ ffi::Thing>
  84. {
  85. Some(&self.0.as_ref()?.0)
  86. }
  87.  
  88. pub
  89. unsafe fn get_context_mut (
  90. self: &'_ mut Self,
  91. ) -> Option<&'_ mut ffi::Context>
  92. {
  93. Some(&mut self.0.as_mut()?.1.get_mut()?.0)
  94. }
  95.  
  96. pub
  97. fn drop (&mut self)
  98. { unsafe {
  99. if let Thing(Some(ref mut slf)) = *self {
  100. let thing = &mut slf.0;
  101. slf.1.get_mut().map(|context| {
  102. ffi::free_thing(
  103. &mut context.0,
  104. &mut *thing,
  105. );
  106. });
  107. self.0 = None;
  108. }
  109. }}
  110. }
  111. impl Drop for Thing { fn drop (&mut self) {
  112. self.drop()
  113. }}
  114. }
  115.  
  116. use some_lib::{
  117. Context,
  118. Thing,
  119. };
  120.  
  121. // use core::mem::ManuallyDrop;
  122.  
  123. #[repr(packed)]
  124. pub
  125. struct SelfRef {
  126. _pad: u8,
  127. thing: Thing,
  128. context: Context,
  129. }
  130.  
  131. impl SelfRef {
  132. pub
  133. fn new () -> Self
  134. {
  135. unsafe {
  136. let mut ret = SelfRef {
  137. _pad: 0,
  138. context: Context::new(),
  139. thing: /*ManuallyDrop::new(*/Thing::new()/*)*/,
  140. };
  141. ret.thing.init(&mut ret.context);
  142. ret
  143. }
  144. }
  145. }
  146.  
  147. impl Drop for SelfRef { fn drop (&mut self) {
  148.  
  149. self.thing.drop() // ManuallyDrop::drop(&mut self.thing)
  150.  
  151. }}
  152.  
  153. fn main ()
  154. {
  155. let mut self_ref = SelfRef::new();
  156. eprintln!("thing at {:p}", unsafe {
  157. self_ref.thing.get_thing().unwrap()
  158. });
  159. eprintln!("thing thinks context is at {:p}", unsafe {
  160. self_ref.thing.get_context_mut().unwrap()
  161. });
  162. eprintln!("context at {:p}", &self_ref.context);
  163. }
  164.  
  165. mod rel_ptr {
  166. use ::std::*;
  167.  
  168. #[derive(Debug)]
  169. pub
  170. struct RelPtr<T : Sized> /* = */ {
  171. offset: Option<num::NonZeroUsize>,
  172. marker: marker::PhantomData<*mut T>,
  173. }
  174.  
  175. impl<T : Sized> Default for RelPtr<T> { fn default () -> Self {
  176. RelPtr {
  177. offset: None,
  178. marker: marker::PhantomData,
  179. }
  180. }}
  181.  
  182. impl<T : Sized> RelPtr<T> {
  183. pub
  184. fn set(
  185. self: &'_ mut Self,
  186. target: &'_ mut T,
  187. )
  188. {
  189. unsafe {
  190. self.offset = Some(num::NonZeroUsize::
  191. new_unchecked(usize::wrapping_sub(
  192. target as *mut T as _,
  193. self as *mut Self as _,
  194. ))
  195. );
  196. }
  197. }
  198.  
  199. pub
  200. unsafe fn get_mut (
  201. self: &'_ mut Self,
  202. ) -> Option<&'_ mut T>
  203. {
  204. <*mut T>::as_mut(
  205. usize::wrapping_add(
  206. self as *mut Self as usize,
  207. self.offset?.get(),
  208. ) as *mut T
  209. )
  210. }
  211. }
  212. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement