cppmm_refptr/
lib.rs

1use std::marker::PhantomData;
2use std::ops::{Deref, DerefMut};
3
4/// This trait describes the relationship between an opaque pointer to a C++
5/// object and the newtype we use to wrap it in Rust.
6///
7/// This trait is unsafe to implement because the associated types are used as
8/// parameters to transmute() in the Ref and RefMut wrappers, so getting this
9/// wrong would be very bad.
10///
11/// To be specific, `SysPointee` must be the pointee C++ type and `Pointee` must
12/// be the newtype wrapper, which must be `#[repr(transparent)]`. For example,
13/// for [`Header`](crate::core::header::Header):
14///
15/// #[repr(transparent)]
16/// pub struct Header(pub(crate) *mut sys::Imf_Header_t);
17///
18/// the `SysPointee` is `sys::Imf_Header_t` and `Pointee` is `Header` and this
19/// is valid because `Header` is a transparent newtype of `sys::Imf_Header_t`
20///
21pub unsafe trait OpaquePtr {
22    type SysPointee;
23    type Pointee;
24}
25
26/// Represents a pointer to a type that is owned by some C++ object, where the
27/// pointer type is also newtyped and we wish to Deref to the newtype rather
28/// than the pointer.
29#[repr(transparent)]
30pub struct Ref<'a, P>
31where
32    P: OpaquePtr,
33{
34    ptr: *const P::SysPointee,
35    _o: PhantomData<&'a ()>,
36    _p: PhantomData<P::Pointee>,
37}
38
39impl<'a, P> Ref<'a, P>
40where
41    P: OpaquePtr,
42{
43    pub fn new(ptr: *const P::SysPointee) -> Ref<'a, P> {
44        Ref {
45            ptr,
46            _o: PhantomData,
47            _p: PhantomData,
48        }
49    }
50
51    pub fn as_ptr(&self) -> *const P::SysPointee {
52        self.ptr
53    }
54}
55
56/// Represents a pointer to a type that is owned by some C++ object, where the
57/// pointer type is also newtyped and we wish to Deref to the newtype rather
58/// than the pointer.
59#[repr(transparent)]
60pub struct RefMut<'a, P>
61where
62    P: OpaquePtr,
63{
64    ptr: *mut P::SysPointee,
65    _o: PhantomData<&'a ()>,
66    _p: PhantomData<P::Pointee>,
67}
68
69impl<'a, P> RefMut<'a, P>
70where
71    P: OpaquePtr,
72{
73    pub fn new(ptr: *mut P::SysPointee) -> RefMut<'a, P> {
74        RefMut {
75            ptr,
76            _o: PhantomData,
77            _p: PhantomData,
78        }
79    }
80
81    pub fn as_ptr(&self) -> *const P::SysPointee {
82        self.ptr
83    }
84
85    pub fn as_mut_ptr(&mut self) -> *mut P::SysPointee {
86        self.ptr
87    }
88}
89
90impl<'a, P> Deref for Ref<'a, P>
91where
92    P: OpaquePtr,
93{
94    type Target = P::Pointee;
95
96    fn deref(&self) -> &Self::Target {
97        unsafe {
98            &*(&self.ptr as *const *const <P as OpaquePtr>::SysPointee
99                as *const <P as OpaquePtr>::Pointee)
100        }
101    }
102}
103
104impl<'a, P> Deref for RefMut<'a, P>
105where
106    P: OpaquePtr,
107{
108    type Target = P::Pointee;
109
110    fn deref(&self) -> &Self::Target {
111        unsafe {
112            &*(&self.ptr as *const *mut <P as OpaquePtr>::SysPointee
113                as *const <P as OpaquePtr>::Pointee)
114        }
115    }
116}
117
118impl<'a, P> DerefMut for RefMut<'a, P>
119where
120    P: OpaquePtr,
121{
122    fn deref_mut(&mut self) -> &mut Self::Target {
123        unsafe {
124            &mut *(&mut self.ptr as *mut *mut <P as OpaquePtr>::SysPointee
125                as *mut <P as OpaquePtr>::Pointee)
126        }
127    }
128}
129
130impl<'a, P> AsRef<P::Pointee> for Ref<'a, P>
131where
132    P: OpaquePtr,
133{
134    fn as_ref(&self) -> &P::Pointee {
135        unsafe {
136            &*(&self.ptr as *const *const <P as OpaquePtr>::SysPointee
137                as *const <P as OpaquePtr>::Pointee)
138        }
139    }
140}
141