1#[cfg(feature = "dynamic")]
32#[macro_use]
33extern crate lazy_static;
34
35use std::any::{TypeId, Any};
36use std::ptr;
37use std::cmp::Ordering;
38use std::hash::{Hash, Hasher};
39use std::collections::hash_map::DefaultHasher;
40use std::fmt::{Debug, Display};
41use std::path::PathBuf;
42
43#[cfg(feature = "dynamic")]
44#[macro_use]
45pub mod dynamic;
46
47#[doc(hidden)]
50#[repr(C)]
51#[derive(Copy, Clone, Debug)]
52pub struct VTable(*const ());
53
54impl VTable {
55 pub fn none() -> VTable {
56 VTable(ptr::null())
57 }
58}
59
60unsafe impl Send for VTable {}
61unsafe impl Sync for VTable {}
62
63#[doc(hidden)]
66#[repr(C)]
67#[derive(Copy, Clone, Debug)]
68pub struct TraitObject {
69 pub data: *const (),
70 pub vtable: VTable
71}
72
73#[doc(hidden)]
76#[macro_export]
77macro_rules! vtable_for {
78 ($x:ty as $y:ty) => ({
79 let x = ::std::ptr::null::<$x>() as *const $y;
80 #[allow(unused_unsafe)]
81 unsafe { ::std::mem::transmute::<_, $crate::TraitObject>(x).vtable }
82 })
83}
84
85#[macro_export]
102macro_rules! mopo {
103 ($name:ty) => (
104 impl $name {
105 pub fn query_ref<U: ::std::any::Any + ?Sized>(&self) -> Option<&U> {
106 if let Some(vtable) = self.query_vtable(::std::any::TypeId::of::<U>()) {
107 unsafe {
108 let data = self as *const Self;
109 let u = $crate::TraitObject { data: data as *const (), vtable: vtable };
110 Some(*::std::mem::transmute::<_, &&U>(&u))
111 }
112 } else {
113 None
114 }
115 }
116 pub fn query_mut<U: ::std::any::Any + ?Sized>(&mut self) -> Option<&mut U> {
117 if let Some(vtable) = self.query_vtable(::std::any::TypeId::of::<U>()) {
118 unsafe {
119 let data = self as *mut Self;
120 let mut u = $crate::TraitObject { data: data as *const (), vtable: vtable };
121 Some(*::std::mem::transmute::<_, &mut &mut U>(&mut u))
122 }
123 } else {
124 None
125 }
126 }
127 pub fn query<U: ::std::any::Any + ?Sized>(self: Box<Self>) -> ::std::result::Result<Box<U>, Box<Self>> {
128 if let Some(vtable) = self.query_vtable(::std::any::TypeId::of::<U>()) {
129 unsafe {
130 let data = Box::into_raw(self);
131 let mut u = $crate::TraitObject { data: data as *const (), vtable: vtable };
132 Ok(Box::from_raw(*::std::mem::transmute::<_, &mut *mut U>(&mut u)))
133 }
134 } else {
135 Err(self)
136 }
137 }
138 pub fn query_arc<U: ::std::any::Any + ?Sized>(self_: ::std::sync::Arc<Self>) -> ::std::result::Result<::std::sync::Arc<U>, ::std::sync::Arc<Self>> {
139 if let Some(vtable) = self_.query_vtable(::std::any::TypeId::of::<U>()) {
140 unsafe {
141 let data = ::std::sync::Arc::into_raw(self_);
142 let mut u = $crate::TraitObject { data: data as *const (), vtable: vtable };
143 Ok(::std::sync::Arc::from_raw(*::std::mem::transmute::<_, &mut *mut U>(&mut u)))
144 }
145 } else {
146 Err(self_)
147 }
148 }
149 pub fn query_rc<U: ::std::any::Any + ?Sized>(self_: ::std::rc::Rc<Self>) -> ::std::result::Result<::std::rc::Rc<U>, ::std::rc::Rc<Self>> {
150 if let Some(vtable) = self_.query_vtable(::std::any::TypeId::of::<U>()) {
151 unsafe {
152 let data = ::std::rc::Rc::into_raw(self_);
153 let mut u = $crate::TraitObject { data: data as *const (), vtable: vtable };
154 Ok(::std::rc::Rc::from_raw(*::std::mem::transmute::<_, &mut *mut U>(&mut u)))
155 }
156 } else {
157 Err(self_)
158 }
159 }
160 pub fn obj_partial_eq(&self, other: &Self) -> bool {
161 if let Some(x) = self.query_ref::<$crate::ObjectPartialEq>() {
162 x.obj_eq(other.query_ref().unwrap())
163 } else {
164 (self as *const Self) == (other as *const Self)
165 }
166 }
167 pub fn obj_partial_cmp(&self, other: &Self) -> Option<::std::cmp::Ordering> {
168 if let Some(x) = self.query_ref::<$crate::ObjectPartialOrd>() {
169 x.obj_partial_cmp(other.query_ref().unwrap())
170 } else {
171 None
172 }
173 }
174 }
175 impl ::std::clone::Clone for Box<$name> {
176 fn clone(&self) -> Self {
177 (**self).to_owned()
178 }
179 }
180 impl ::std::borrow::ToOwned for $name {
181 type Owned = Box<$name>;
182 fn to_owned(&self) -> Box<$name> {
183 self.query_ref::<$crate::ObjectClone>().expect("Object not clonable!").obj_clone().query::<$name>().unwrap()
184 }
185 }
186 impl ::std::fmt::Debug for $name {
187 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
188 if let Some(o) = self.query_ref::<::std::fmt::Debug>() {
189 o.fmt(f)
190 } else {
191 writeln!(f, "Object {{ <no `Debug` implementation> }}")
192 }
193 }
194 }
195 impl ::std::cmp::PartialEq for $name {
196 fn eq(&self, other: &Self) -> bool {
197 if let Some(x) = self.query_ref::<$crate::ObjectEq>() {
200 x.obj_eq(other.query_ref().unwrap())
201 } else {
202 (self as *const Self) == (other as *const Self)
204 }
205 }
206 }
207 impl ::std::cmp::Eq for $name {}
208 impl ::std::cmp::PartialOrd for $name {
209 fn partial_cmp(&self, other: &Self) -> Option<::std::cmp::Ordering> {
210 Some(self.cmp(other))
211 }
212 }
213 impl ::std::cmp::Ord for $name {
214 fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
215 if let Some(x) = self.query_ref::<$crate::ObjectOrd>() {
216 if let Some(o) = x.obj_cmp(other.query_ref().unwrap()) {
217 return o
218 }
219 }
220 Ord::cmp(&(self as *const Self), &(other as *const Self))
221 }
222 }
223 impl ::std::hash::Hash for $name {
224 fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
225 if let Some(x) = self.query_ref::<$crate::ObjectHash>() {
226 x.obj_hash(state)
227 } else {
228 state.write_usize(self as *const Self as *const () as usize)
229 }
230 }
231 }
232 )
233}
234
235pub unsafe trait Object: Any {
239 #[doc(hidden)]
242 fn query_vtable(&self, id: TypeId) -> Option<VTable>;
243}
244
245pub unsafe trait HasInterface<I: ?Sized> {}
256
257mopo!(Object);
258
259
260pub trait ObjectClone {
264 fn obj_clone(&self) -> Box<Object>;
265}
266impl<T: Clone + Object> ObjectClone for T {
267 fn obj_clone(&self) -> Box<Object> {
268 Box::new(self.clone())
269 }
270}
271
272pub trait ObjectPartialEq {
276 fn obj_eq(&self, other: &Object) -> bool;
277}
278impl<T: PartialEq + Object> ObjectPartialEq for T {
279 fn obj_eq(&self, other: &Object) -> bool {
280 if let Some(o) = other.query_ref::<Self>() {
281 self == o
282 } else {
283 false
284 }
285 }
286}
287
288pub trait ObjectEq: ObjectPartialEq {}
292impl<T: Eq + Object> ObjectEq for T {}
293
294pub trait ObjectPartialOrd {
298 fn obj_partial_cmp(&self, other: &Object) -> Option<Ordering>;
299}
300impl<T: PartialOrd + Object> ObjectPartialOrd for T {
301 fn obj_partial_cmp(&self, other: &Object) -> Option<Ordering> {
302 if let Some(o) = other.query_ref::<Self>() {
303 self.partial_cmp(o)
304 } else {
305 None
306 }
307 }
308}
309
310pub trait ObjectOrd {
314 fn obj_cmp(&self, other: &Object) -> Option<Ordering>;
315}
316impl<T: Ord + Object> ObjectOrd for T {
317 fn obj_cmp(&self, other: &Object) -> Option<Ordering> {
318 if let Some(o) = other.query_ref::<Self>() {
319 Some(self.cmp(o))
320 } else {
321 None
322 }
323 }
324}
325
326pub trait ObjectHash {
333 fn obj_hash(&self, state: &mut Hasher);
334}
335impl<T: Hash + Object> ObjectHash for T {
336 fn obj_hash(&self, state: &mut Hasher) {
337 let mut h = DefaultHasher::new();
338 self.hash(&mut h);
339 state.write_u64(h.finish());
340 }
341}
342
343#[macro_export]
358macro_rules! interfaces {
359 (@unbracket $(($($v:tt)*))*) => ($($($v)*)*);
360 (@inner $imp:tt $cond:tt $name:ty: $($iface:ty),+ {}) => (
361 interfaces!(@unbracket $imp ($crate::HasInterface<$name> for $name) $cond ({}));
362 interfaces!(@unbracket $imp ($crate::HasInterface<$crate::Object> for $name) $cond ({}));
363 $(interfaces!(@unbracket $imp ($crate::HasInterface<$iface> for $name) $cond ({}));)*
364 interfaces!(@unbracket $imp ($crate::Object for $name) $cond ({
365 fn query_vtable(&self, id: ::std::any::TypeId) -> Option<$crate::VTable> {
366 if id == ::std::any::TypeId::of::<$name>() {
367 Some($crate::VTable::none())
368 } else if id == ::std::any::TypeId::of::<$crate::Object>() {
369 Some(vtable_for!($name as $crate::Object))
370 } else $(if id == ::std::any::TypeId::of::<$iface>() {
371 Some(vtable_for!($name as $iface))
372 } else)* {
373 #[cfg(feature = "dynamic")]
376 { $crate::dynamic::find_in_registry::<$name>(id) }
377 #[cfg(not(feature = "dynamic"))]
379 { None }
380 }
381 }
382 }));
383 );
384 (@imp ($($result:tt)*) $name:ty: $($iface:ty),+ $(where $($cond:tt)*)*) => (
385 interfaces!(@inner (unsafe impl<$($result)*>) ($(where $($cond)*)*) $name: $($iface),+ {});
386 );
387 (@parse < $($rest:tt)*) => (
388 interfaces!(@parseArg () $($rest)*);
389 );
390 (@parse $($rest:tt)*) => (
391 interfaces!(@imp () $($rest)*);
392 );
393 (@parseArg ($($result:tt)*) $name:ident , $($rest:tt)*) => (
394 interfaces!(@parseArg ($($result)* $name ,) $($rest)*);
395 );
396 (@parseArg ($($result:tt)*) $name:ident : $($rest:tt)*) => (
397 interfaces!(@parseBound ($($result)* $name : ) $($rest)*);
398 );
399 (@parseArg ($($result:tt)*) $name:ident > $($rest:tt)*) => (
400 interfaces!(@imp ($($result)* $name) $($rest)*);
401 );
402 (@parseBound ($($result:tt)*) $bound:tt + $($rest:tt)*) => (
403 interfaces!(@parseBound ($($result)* $bound +) $($rest)*);
404 );
405 (@parseBound ($($result:tt)*) $bound:tt , $($rest:tt)*) => (
406 interfaces!(@parseArg ($($result)* $bound ,) $($rest)*);
407 );
408 (@parseBound ($($result:tt)*) $bound:tt > $($rest:tt)*) => (
409 interfaces!(@imp ($($result)* $bound) $($rest)*);
410 );
411 (< $($rest:tt)*) => (
412 interfaces!(@parse < $($rest)*);
413 );
414 ($x:ty: $($rest:tt)*) => (
415 interfaces!(@parse $x: $($rest)*);
416 );
417 (@expand2 ($name:ty) ($($rest:tt)*)) => (
418 interfaces!($name $($rest)*);
419 );
420 (@expand {$($name:ty),*} $rest:tt) => (
421 $( interfaces!(@expand2 ($name) $rest); )*
422 );
423 ({$($name:ty),*} $($rest:tt)*) => (
424 interfaces!(@expand {$($name),*} ($($rest)*));
425 );
426}
427
428interfaces!({
430 bool, i8, u8, i16, u16, i32, u32, i64, u64, char
431}: ObjectClone, Debug, Display, ObjectPartialEq, ObjectPartialOrd, ObjectEq, ObjectOrd, ObjectHash, ToString);
432
433interfaces!({
435 f32, f64
436}: ObjectClone, Debug, Display, ObjectPartialEq, ObjectPartialOrd, ToString);
437
438interfaces!(String: ObjectClone, Debug, Display, ObjectPartialEq, ObjectPartialOrd, ObjectEq, ObjectOrd, ObjectHash, ToString);
440
441interfaces!(PathBuf: ObjectClone, Debug, ObjectPartialEq, ObjectPartialOrd, ObjectEq, ObjectOrd, ObjectHash);
443
444interfaces!({
446 Vec<bool>, Vec<i8>, Vec<u8>, Vec<i16>, Vec<u16>, Vec<i32>, Vec<u32>, Vec<i64>, Vec<u64>, Vec<char>
447}: ObjectClone, Debug, ObjectPartialEq, ObjectPartialOrd, ObjectEq, ObjectOrd, ObjectHash);
448interfaces!({
449 Vec<f32>, Vec<f64>
450}: ObjectClone, Debug, ObjectPartialEq, ObjectPartialOrd);
451interfaces!({
452 Vec<String>, Vec<PathBuf>
453}: ObjectClone, Debug, ObjectPartialEq, ObjectPartialOrd, ObjectEq, ObjectOrd, ObjectHash);
454
455
456#[cfg(test)]
457mod tests {
458 use std::fmt::Debug;
459 use std::sync::Arc;
460 use std::rc::Rc;
461
462 #[derive(Debug, Clone)]
463 struct Bar;
464 interfaces!(Bar: Foo, super::ObjectClone, Debug, Custom);
465
466 trait Foo: Debug {
467 fn test(&self) -> bool { false }
468 }
469 trait Foo2: Debug {}
470 impl Foo for Bar {
471 fn test(&self) -> bool { true }
472 }
473 impl Foo2 for Bar {}
474
475 #[derive(Debug, Clone)]
476 struct GenericBar<T>(T);
477 interfaces!(<T: Debug + 'static> GenericBar<T>: super::ObjectClone, Debug where T: Clone);
478
479 #[test]
480 fn test_ref() {
481 let x = Box::new(Bar) as Box<super::Object>;
482 let foo: Option<&Foo> = x.query_ref();
483 assert!(foo.is_some());
484 assert!(foo.unwrap().test());
485 let foo2: Option<&Foo2> = x.query_ref();
486 assert!(foo2.is_none());
487 let bar: Option<&Bar> = x.query_ref();
488 assert!(bar.is_some());
489 }
490
491 #[test]
492 fn test_mut() {
493 let mut x = Box::new(Bar) as Box<super::Object>;
494 {
495 let foo = x.query_mut::<Foo>();
496 assert!(foo.is_some());
497 assert!(foo.unwrap().test());
498 }
499 {
500 let foo2 = x.query_mut::<Foo2>();
501 assert!(foo2.is_none());
502 }
503 {
504 let bar = x.query_mut::<Bar>();
505 assert!(bar.is_some());
506 }
507 }
508
509 #[test]
510 fn test_owned() {
511 let x = Box::new(Bar) as Box<super::Object>;
512 let foo: Result<Box<Foo>, _> = x.clone().query();
513 assert!(foo.is_ok());
514 assert!(foo.unwrap().test());
515 let foo2: Result<Box<Foo2>, _> = x.clone().query();
516 assert!(foo2.is_err());
517 let bar: Result<Box<Bar>, _> = x.clone().query();
518 assert!(bar.is_ok());
519 }
520
521 #[test]
522 fn test_rc() {
523 let x = Rc::new(Bar) as Rc<super::Object>;
524 let foo: Result<Rc<Foo>, _> = super::Object::query_rc(x.clone());
525 assert!(foo.is_ok());
526 assert!(foo.unwrap().test());
527 let foo2: Result<Rc<Foo2>, _> = super::Object::query_rc(x.clone());
528 assert!(foo2.is_err());
529 let bar: Result<Rc<Bar>, _> = super::Object::query_rc(x.clone());
530 assert!(bar.is_ok());
531 }
532
533 #[test]
534 fn test_arc() {
535 let x = Arc::new(Bar) as Arc<super::Object>;
536 let foo: Result<Arc<Foo>, _> = super::Object::query_arc(x.clone());
537 assert!(foo.is_ok());
538 assert!(foo.unwrap().test());
539 let foo2: Result<Arc<Foo2>, _> = super::Object::query_arc(x.clone());
540 assert!(foo2.is_err());
541 let bar: Result<Arc<Bar>, _> = super::Object::query_arc(x.clone());
542 assert!(bar.is_ok());
543 }
544
545 trait Custom : super::Object {}
546 impl Custom for Bar {}
547 mopo!(Custom);
548
549 #[test]
550 fn test_derived() {
551 let x = Box::new(Bar) as Box<Custom>;
552 let foo: Result<Box<Foo>, _> = x.clone().query();
553 assert!(foo.is_ok());
554 assert!(foo.unwrap().test());
555 let foo2: Result<Box<Foo2>, _> = x.clone().query();
556 assert!(foo2.is_err());
557 let bar: Result<Box<Bar>, _> = x.clone().query();
558 assert!(bar.is_ok());
559 }
560
561 trait Dynamic {
562 fn test(&self) -> u32;
563 }
564 impl Dynamic for Bar {
565 fn test(&self) -> u32 { 42 }
566 }
567
568 #[test]
569 fn test_dynamic() {
570 let x = Box::new(Bar) as Box<super::Object>;
571 let dyn1: Option<&Dynamic> = x.query_ref();
572 assert!(dyn1.is_none());
573
574 dynamic_interfaces! {
575 Bar: Dynamic;
576 }
577
578 let dyn2: Option<&Dynamic> = x.query_ref();
579 assert!(dyn2.unwrap().test() == 42);
580 }
581
582 #[test]
583 fn test_primitives() {
584 Box::new(1) as Box<super::Object>;
585 Box::new(1f32) as Box<super::Object>;
586 Box::new("test".to_string()) as Box<super::Object>;
587 Box::new(vec![1,2,3]) as Box<super::Object>;
588 }
589}