1#![deny(missing_docs, warnings)]
2
3extern crate traitobject;
11
12use std::any::Any;
13use std::mem;
14
15pub trait UnsafeAny: Any {}
18impl<T: Any> UnsafeAny for T {}
19
20impl UnsafeAny {
21 pub unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T {
27 mem::transmute(traitobject::data(self))
28 }
29
30 pub unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T {
36 mem::transmute(traitobject::data_mut(self))
37 }
38
39 pub unsafe fn downcast_unchecked<T: Any>(self: Box<UnsafeAny>) -> Box<T> {
45 let raw: *mut UnsafeAny = mem::transmute(self);
46 mem::transmute(traitobject::data_mut(raw))
47 }
48}
49
50pub unsafe trait UnsafeAnyExt {
52 unsafe fn downcast_ref_unchecked<T: Any>(&self) -> &T {
58 mem::transmute(traitobject::data(self))
59 }
60
61 unsafe fn downcast_mut_unchecked<T: Any>(&mut self) -> &mut T {
67 mem::transmute(traitobject::data_mut(self))
68 }
69
70 unsafe fn downcast_unchecked<T: Any>(self: Box<Self>) -> Box<T> {
76 let raw: *mut Self = mem::transmute(self);
77 mem::transmute(traitobject::data_mut(raw))
78 }
79}
80
81unsafe impl UnsafeAnyExt for Any { }
82unsafe impl UnsafeAnyExt for UnsafeAny { }
83unsafe impl UnsafeAnyExt for Any + Send { }
84unsafe impl UnsafeAnyExt for Any + Sync { }
85unsafe impl UnsafeAnyExt for Any + Send + Sync { }
86unsafe impl UnsafeAnyExt for UnsafeAny + Send { }
87unsafe impl UnsafeAnyExt for UnsafeAny + Sync { }
88unsafe impl UnsafeAnyExt for UnsafeAny + Send + Sync { }
89
90#[cfg(test)]
91mod test {
92 use super::{UnsafeAny, UnsafeAnyExt};
93 use std::any::Any;
94
95 #[test] fn test_simple_downcast_ext() {
96 let a = Box::new(7usize) as Box<Any>;
97 unsafe { assert_eq!(*a.downcast_ref_unchecked::<usize>(), 7); }
98
99 let mut a = Box::new(7usize) as Box<Any>;
100 unsafe { assert_eq!(*a.downcast_mut_unchecked::<usize>(), 7); }
101
102 let mut a = Box::new(7usize) as Box<Any>;
103 unsafe {
104 *a.downcast_mut_unchecked::<usize>() = 8;
105 assert_eq!(*a.downcast_mut_unchecked::<usize>(), 8);
106 }
107 }
108
109 #[test] fn test_simple_downcast_inherent() {
110 let a = Box::new(7usize) as Box<UnsafeAny>;
111 unsafe { assert_eq!(*a.downcast_ref_unchecked::<usize>(), 7); }
112
113 let mut a = Box::new(7usize) as Box<UnsafeAny>;
114 unsafe { assert_eq!(*a.downcast_mut_unchecked::<usize>(), 7); }
115
116 let mut a = Box::new(7usize) as Box<UnsafeAny>;
117 unsafe {
118 *a.downcast_mut_unchecked::<usize>() = 8;
119 assert_eq!(*a.downcast_mut_unchecked::<usize>(), 8);
120 }
121 }
122
123 #[test] fn test_box_downcast_no_double_free() {
124 use std::sync::atomic::{AtomicUsize, Ordering};
125 use std::sync::Arc;
126
127 struct Dropper {
128 x: Arc<AtomicUsize>
129 }
130
131 impl Drop for Dropper {
132 fn drop(&mut self) {
133 self.x.fetch_add(1, Ordering::SeqCst);
134 }
135 }
136
137 let x = Arc::new(AtomicUsize::new(0));
138 let a = Box::new(Dropper { x: x.clone() }) as Box<UnsafeAny>;
139
140 let dropper = unsafe { a.downcast_unchecked::<Dropper>() };
141 drop(dropper);
142
143 assert_eq!(x.load(Ordering::SeqCst), 1);
144
145 let x = Arc::new(AtomicUsize::new(0));
147 let a = Box::new(Dropper { x: x.clone() }) as Box<Any>;
148
149 let dropper = unsafe { a.downcast_unchecked::<Dropper>() };
150 drop(dropper);
151
152 assert_eq!(x.load(Ordering::SeqCst), 1);
153 }
154}
155