Skip to content

Commit c460a1c

Browse files
committed
Delete FnState and add ErasedFn trait
1 parent 407bd8b commit c460a1c

1 file changed

Lines changed: 39 additions & 37 deletions

File tree

libcc2rs/src/fn_ptr.rs

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,19 @@ macro_rules! impl_fn_addr {
3131
}
3232
impl_fn_addr!();
3333

34-
#[derive(Clone)]
35-
pub(crate) struct FnState {
36-
addr: usize,
37-
original: Rc<dyn Any>,
38-
current_cast: Option<Rc<dyn Any>>,
34+
trait ErasedFn: Any {
35+
fn addr(&self) -> usize;
36+
}
37+
38+
impl<T: FnAddr + Any> ErasedFn for T {
39+
fn addr(&self) -> usize {
40+
self.fn_addr()
41+
}
3942
}
4043

4144
pub struct FnPtr<T> {
42-
state: Option<Rc<FnState>>,
45+
original: Option<Rc<dyn ErasedFn>>,
46+
current_cast: Option<Rc<dyn ErasedFn>>,
4347
// FnPtr does not use T, hence wrap in PhantomData
4448
_marker: PhantomData<T>,
4549
}
@@ -48,54 +52,48 @@ impl<T> FnPtr<T> {
4852
#[inline]
4953
pub fn null() -> Self {
5054
FnPtr {
51-
state: None,
55+
original: None,
56+
current_cast: None,
5257
_marker: PhantomData,
5358
}
5459
}
5560

5661
#[inline]
5762
pub fn is_null(&self) -> bool {
58-
self.state.is_none()
63+
self.original.is_none()
5964
}
6065
}
6166

6267
impl<T: FnAddr + 'static> FnPtr<T> {
6368
pub fn new(f: T) -> Self {
64-
let addr = f.fn_addr();
65-
let rc: Rc<dyn Any> = Rc::new(f);
69+
let rc: Rc<dyn ErasedFn> = Rc::new(f);
6670
FnPtr {
67-
state: Some(Rc::new(FnState {
68-
addr,
69-
original: rc.clone(),
70-
current_cast: Some(rc),
71-
})),
71+
original: Some(rc.clone()),
72+
current_cast: Some(rc),
7273
_marker: PhantomData,
7374
}
7475
}
7576
}
7677

7778
impl<T: 'static> FnPtr<T> {
78-
pub fn cast<U: 'static>(&self, adapter: Option<U>) -> FnPtr<U> {
79-
let state = self.state.as_ref().expect("ub: null fn pointer cast");
79+
pub fn cast<U: FnAddr + 'static>(&self, adapter: Option<U>) -> FnPtr<U> {
80+
let original = self.original.as_ref().expect("ub: null fn pointer cast");
8081

81-
let current_cast = if state
82+
let current_cast = if self
8283
.current_cast
8384
.as_ref()
84-
.is_some_and(|rc| (**rc).type_id() == TypeId::of::<U>())
85+
.is_some_and(|rc| Any::type_id(&**rc) == TypeId::of::<U>())
8586
{
86-
state.current_cast.clone()
87-
} else if (*state.original).type_id() == TypeId::of::<U>() {
88-
Some(state.original.clone())
87+
self.current_cast.clone()
88+
} else if Any::type_id(&**original) == TypeId::of::<U>() {
89+
Some(original.clone())
8990
} else {
90-
adapter.map(|a| Rc::new(a) as Rc<dyn Any>)
91+
adapter.map(|a| Rc::new(a) as Rc<dyn ErasedFn>)
9192
};
9293

9394
FnPtr {
94-
state: Some(Rc::new(FnState {
95-
addr: state.addr,
96-
original: state.original.clone(),
97-
current_cast,
98-
})),
95+
original: Some(original.clone()),
96+
current_cast,
9997
_marker: PhantomData,
10098
}
10199
}
@@ -104,20 +102,24 @@ impl<T: 'static> FnPtr<T> {
104102
impl<T: 'static> Deref for FnPtr<T> {
105103
type Target = T;
106104
fn deref(&self) -> &T {
107-
let state = self.state.as_ref().expect("ub: null fn pointer call");
108-
match &state.current_cast {
109-
Some(rc) => rc
110-
.downcast_ref::<T>()
111-
.expect("ub: fn pointer type mismatch"),
112-
None => panic!("ub: calling through incompatible fn pointer type"),
105+
if self.original.is_none() {
106+
panic!("ub: null fn pointer call");
113107
}
108+
let rc = self
109+
.current_cast
110+
.as_ref()
111+
.expect("ub: calling through incompatible fn pointer type");
112+
let any: &dyn Any = &**rc;
113+
any.downcast_ref::<T>()
114+
.expect("ub: fn pointer type mismatch")
114115
}
115116
}
116117

117118
impl<T> Clone for FnPtr<T> {
118119
fn clone(&self) -> Self {
119120
FnPtr {
120-
state: self.state.clone(),
121+
original: self.original.clone(),
122+
current_cast: self.current_cast.clone(),
121123
_marker: PhantomData,
122124
}
123125
}
@@ -131,9 +133,9 @@ impl<T> Default for FnPtr<T> {
131133

132134
impl<T> PartialEq for FnPtr<T> {
133135
fn eq(&self, other: &Self) -> bool {
134-
match (&self.state, &other.state) {
136+
match (&self.original, &other.original) {
135137
(None, None) => true,
136-
(Some(a), Some(b)) => a.addr == b.addr,
138+
(Some(a), Some(b)) => a.addr() == b.addr(),
137139
_ => false,
138140
}
139141
}

0 commit comments

Comments
 (0)