Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- mod some_lib {
- use crate::rel_ptr::RelPtr;
- mod ffi {
- pub
- struct Context ([u8; 3]);
- pub
- struct Thing (());
- pub
- unsafe extern "C" fn mk_context () -> Context
- { Context([0; 3]) }
- pub
- unsafe extern "C" fn mk_thing (_: *mut Context) -> Thing
- { Thing(()) }
- pub
- unsafe extern "C" fn free_thing (ctx: *mut Context, thing: *mut Thing)
- {
- eprintln!(
- "[C] Freeing thing at {:p}, with context at {:p}",
- thing,
- ctx,
- );
- }
- pub
- unsafe extern "C" fn free_context (ctx: *mut Context)
- {
- eprintln!( "[C] Freeing context at {:p}", ctx);
- }
- }
- #[repr(transparent)]
- pub
- struct Context (ffi::Context);
- impl Context {
- pub
- fn new () -> Self
- {
- Context(unsafe { ffi::mk_context() })
- }
- }
- impl Drop for Context { fn drop (&mut self) {
- unsafe { ffi::free_context(&mut self.0) }
- }}
- pub
- struct Thing (
- Option<(ffi::Thing, RelPtr<Context>)>
- );
- impl Thing {
- pub
- fn new () -> Self {
- Thing(None)
- }
- /// # Safety
- ///
- /// The relative offset between `*self` and `*context` must not change
- pub
- unsafe fn init (
- self: &'_ mut Self,
- context: &'_ mut Context,
- )
- {
- *self = Thing(Some((
- ffi::mk_thing(&mut context.0),
- RelPtr::default(),
- )));
- if let Thing(Some((_, ref mut rel_ptr))) = *self {
- rel_ptr.set(context)
- } else {
- ::std::hint::unreachable_unchecked()
- }
- }
- pub
- fn get_thing (
- self: &'_ Self,
- ) -> Option<&'_ ffi::Thing>
- {
- Some(&self.0.as_ref()?.0)
- }
- pub
- unsafe fn get_context_mut (
- self: &'_ mut Self,
- ) -> Option<&'_ mut ffi::Context>
- {
- Some(&mut self.0.as_mut()?.1.get_mut()?.0)
- }
- pub
- fn drop (&mut self)
- { unsafe {
- if let Thing(Some(ref mut slf)) = *self {
- let thing = &mut slf.0;
- slf.1.get_mut().map(|context| {
- ffi::free_thing(
- &mut context.0,
- &mut *thing,
- );
- });
- self.0 = None;
- }
- }}
- }
- impl Drop for Thing { fn drop (&mut self) {
- self.drop()
- }}
- }
- use some_lib::{
- Context,
- Thing,
- };
- // use core::mem::ManuallyDrop;
- #[repr(packed)]
- pub
- struct SelfRef {
- _pad: u8,
- thing: Thing,
- context: Context,
- }
- impl SelfRef {
- pub
- fn new () -> Self
- {
- unsafe {
- let mut ret = SelfRef {
- _pad: 0,
- context: Context::new(),
- thing: /*ManuallyDrop::new(*/Thing::new()/*)*/,
- };
- ret.thing.init(&mut ret.context);
- ret
- }
- }
- }
- impl Drop for SelfRef { fn drop (&mut self) {
- self.thing.drop() // ManuallyDrop::drop(&mut self.thing)
- }}
- fn main ()
- {
- let mut self_ref = SelfRef::new();
- eprintln!("thing at {:p}", unsafe {
- self_ref.thing.get_thing().unwrap()
- });
- eprintln!("thing thinks context is at {:p}", unsafe {
- self_ref.thing.get_context_mut().unwrap()
- });
- eprintln!("context at {:p}", &self_ref.context);
- }
- mod rel_ptr {
- use ::std::*;
- #[derive(Debug)]
- pub
- struct RelPtr<T : Sized> /* = */ {
- offset: Option<num::NonZeroUsize>,
- marker: marker::PhantomData<*mut T>,
- }
- impl<T : Sized> Default for RelPtr<T> { fn default () -> Self {
- RelPtr {
- offset: None,
- marker: marker::PhantomData,
- }
- }}
- impl<T : Sized> RelPtr<T> {
- pub
- fn set(
- self: &'_ mut Self,
- target: &'_ mut T,
- )
- {
- unsafe {
- self.offset = Some(num::NonZeroUsize::
- new_unchecked(usize::wrapping_sub(
- target as *mut T as _,
- self as *mut Self as _,
- ))
- );
- }
- }
- pub
- unsafe fn get_mut (
- self: &'_ mut Self,
- ) -> Option<&'_ mut T>
- {
- <*mut T>::as_mut(
- usize::wrapping_add(
- self as *mut Self as usize,
- self.offset?.get(),
- ) as *mut T
- )
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement