1 //! A library providing direct casting among trait objects implemented by a type. 2 //! 3 //! In Rust, an object of a sub-trait of [`Any`] can be downcast to a concrete type 4 //! at runtime if the type is known. But no direct casting between two trait objects 5 //! (i.e. without involving the concrete type of the backing value) is possible 6 //! (even no coercion from a trait object to that of its super-trait yet). 7 //! 8 //! With this crate, any trait object with [`CastFrom`] as its super-trait can be cast directly 9 //! to another trait object implemented by the underlying type if the target traits are 10 //! registered beforehand with the macros provided by this crate. 11 //! 12 //! # Usage 13 //! ``` 14 //! use intertrait::*; 15 //! use intertrait::cast::*; 16 //! 17 //! struct Data; 18 //! 19 //! trait Source: CastFrom {} 20 //! 21 //! trait Greet { 22 //! fn greet(&self); 23 //! } 24 //! 25 //! #[cast_to] 26 //! impl Greet for Data { 27 //! fn greet(&self) { 28 //! println!("Hello"); 29 //! } 30 //! } 31 //! 32 //! impl Source for Data {} 33 //! 34 //! let data = Data; 35 //! let source: &dyn Source = &data; 36 //! let greet = source.cast::<dyn Greet>(); 37 //! greet.unwrap().greet(); 38 //! ``` 39 //! 40 //! Target traits must be explicitly designated beforehand. There are three ways to do it: 41 //! 42 //! * [`#[cast_to]`][cast_to] to `impl` item 43 //! * [`#[cast_to(Trait)]`][cast_to] to type definition 44 //! * [`castable_to!(Type => Trait1, Trait2)`][castable_to] 45 //! 46 //! If the underlying type involved is `Sync + Send` and you want to use it with [`Arc`], 47 //! use [`CastFromSync`] in place of [`CastFrom`] and add `[sync]` flag before the list 48 //! of traits in the macros. Refer to the documents for each of macros for details. 49 //! 50 //! For casting, refer to traits defined in [`cast`] module. 51 //! 52 //! [cast_to]: ./attr.cast_to.html 53 //! [castable_to]: ./macro.castable_to.html 54 //! [`CastFrom`]: ./trait.CastFrom.html 55 //! [`CastFromSync`]: ./trait.CastFromSync.html 56 //! [`cast`]: ./cast/index.html 57 //! [`Any`]: https://doc.rust-lang.org/std/any/trait.Any.html 58 //! [`Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.html 59 60 #![cfg_attr(target_os = "none", no_std)] 61 62 extern crate alloc; 63 extern crate core; 64 65 use core::{ 66 any::{Any, TypeId}, 67 marker::{Send, Sync}, 68 }; 69 70 use alloc::boxed::Box; 71 use alloc::rc::Rc; 72 use alloc::sync::Arc; 73 74 use hashbrown::HashMap; 75 use linkme::distributed_slice; 76 77 pub use intertrait_macros::*; 78 79 use crate::hasher::BuildFastHasher; 80 81 pub mod cast; 82 mod hasher; 83 84 #[doc(hidden)] 85 pub type BoxedCaster = Box<dyn Any + Send + Sync>; 86 87 #[cfg(doctest)] 88 doc_comment::doctest!("../README.md"); 89 90 /// A distributed slice gathering constructor functions for [`Caster<T>`]s. 91 /// 92 /// A constructor function returns `TypeId` of a concrete type involved in the casting 93 /// and a `Box` of a trait object backed by a [`Caster<T>`]. 94 /// 95 /// [`Caster<T>`]: ./struct.Caster.html 96 #[doc(hidden)] 97 #[distributed_slice] 98 pub static CASTERS: [fn() -> (TypeId, BoxedCaster)] = [..]; 99 100 /// A `HashMap` mapping `TypeId` of a [`Caster<T>`] to an instance of it. 101 /// 102 /// [`Caster<T>`]: ./struct.Caster.html 103 #[cfg(not(target_os = "none"))] 104 static CASTER_MAP: once_cell::sync::Lazy<HashMap<(TypeId, TypeId), BoxedCaster, BuildFastHasher>> = 105 once_cell::sync::Lazy::new(|| { 106 CASTERS 107 .iter() 108 .map(|f| { 109 let (type_id, caster) = f(); 110 ((type_id, (*caster).type_id()), caster) 111 }) 112 .collect() 113 }); 114 115 /// CasterMap 116 /// 117 /// key.0: type_id of source 118 /// key.1: type_id of target 119 /// 120 /// value: A BoxedCaster which can cast source to target 121 #[cfg(target_os = "none")] 122 static mut CASTER_MAP: Option<HashMap<(TypeId, TypeId), BoxedCaster, BuildFastHasher>> = None; 123 124 #[cfg(target_os = "none")] 125 pub fn caster_map() -> &'static HashMap<(TypeId, TypeId), BoxedCaster, BuildFastHasher> { 126 return unsafe { 127 CASTER_MAP.as_ref().unwrap_or_else(|| { 128 panic!("intertrait_caster_map() must be called after CASTER_MAP is initialized") 129 }) 130 }; 131 } 132 133 /// Initializes the global [`CASTER_MAP`] with [`CASTERS`]. 134 /// 135 /// no_std环境下,需要手动调用此函数初始化CASTER_MAP 136 #[cfg(target_os = "none")] 137 pub fn init_caster_map() { 138 use core::sync::atomic::AtomicBool; 139 140 let pd = AtomicBool::new(false); 141 let r = pd.compare_exchange( 142 false, 143 true, 144 core::sync::atomic::Ordering::SeqCst, 145 core::sync::atomic::Ordering::SeqCst, 146 ); 147 148 if r.is_err() { 149 panic!("init_caster_map() must be called only once"); 150 } 151 152 let hashmap = CASTERS 153 .iter() 154 .map(|f| { 155 let (type_id, caster) = f(); 156 ((type_id, (*caster).type_id()), caster) 157 }) 158 .collect(); 159 160 unsafe { CASTER_MAP = Some(hashmap) }; 161 } 162 163 #[cfg(not(target_os = "none"))] 164 pub fn init_caster_map() {} 165 166 fn cast_arc_panic<T: ?Sized + 'static>(_: Arc<dyn Any + Sync + Send>) -> Arc<T> { 167 panic!("Prepend [sync] to the list of target traits for Sync + Send types") 168 } 169 170 /// A `Caster` knows how to cast a reference to or `Box` of a trait object for `Any` 171 /// to a trait object of trait `T`. Each `Caster` instance is specific to a concrete type. 172 /// That is, it knows how to cast to single specific trait implemented by single specific type. 173 /// 174 /// An implementation of a trait for a concrete type doesn't need to manually provide 175 /// a `Caster`. Instead attach `#[cast_to]` to the `impl` block. 176 #[doc(hidden)] 177 pub struct Caster<T: ?Sized + 'static> { 178 /// Casts an immutable reference to a trait object for `Any` to a reference 179 /// to a trait object for trait `T`. 180 pub cast_ref: fn(from: &dyn Any) -> &T, 181 182 /// Casts a mutable reference to a trait object for `Any` to a mutable reference 183 /// to a trait object for trait `T`. 184 pub cast_mut: fn(from: &mut dyn Any) -> &mut T, 185 186 /// Casts a `Box` holding a trait object for `Any` to another `Box` holding a trait object 187 /// for trait `T`. 188 pub cast_box: fn(from: Box<dyn Any>) -> Box<T>, 189 190 /// Casts an `Rc` holding a trait object for `Any` to another `Rc` holding a trait object 191 /// for trait `T`. 192 pub cast_rc: fn(from: Rc<dyn Any>) -> Rc<T>, 193 194 /// Casts an `Arc` holding a trait object for `Any + Sync + Send + 'static` 195 /// to another `Arc` holding a trait object for trait `T`. 196 pub cast_arc: fn(from: Arc<dyn Any + Sync + Send + 'static>) -> Arc<T>, 197 } 198 199 impl<T: ?Sized + 'static> Caster<T> { 200 pub fn new( 201 cast_ref: fn(from: &dyn Any) -> &T, 202 cast_mut: fn(from: &mut dyn Any) -> &mut T, 203 cast_box: fn(from: Box<dyn Any>) -> Box<T>, 204 cast_rc: fn(from: Rc<dyn Any>) -> Rc<T>, 205 ) -> Caster<T> { 206 Caster::<T> { 207 cast_ref, 208 cast_mut, 209 cast_box, 210 cast_rc, 211 cast_arc: cast_arc_panic, 212 } 213 } 214 215 pub fn new_sync( 216 cast_ref: fn(from: &dyn Any) -> &T, 217 cast_mut: fn(from: &mut dyn Any) -> &mut T, 218 cast_box: fn(from: Box<dyn Any>) -> Box<T>, 219 cast_rc: fn(from: Rc<dyn Any>) -> Rc<T>, 220 cast_arc: fn(from: Arc<dyn Any + Sync + Send>) -> Arc<T>, 221 ) -> Caster<T> { 222 Caster::<T> { 223 cast_ref, 224 cast_mut, 225 cast_box, 226 cast_rc, 227 cast_arc, 228 } 229 } 230 } 231 232 /// Returns a `Caster<S, T>` from a concrete type `S` to a trait `T` implemented by it. 233 /// 234 /// ## 参数 235 /// 236 /// - type_id: 源类型的type_id 237 /// 238 /// T: 目标trait 239 fn caster<T: ?Sized + 'static>(type_id: TypeId) -> Option<&'static Caster<T>> { 240 #[cfg(not(target_os = "none"))] 241 { 242 CASTER_MAP 243 .get(&(type_id, TypeId::of::<Caster<T>>())) 244 .and_then(|caster| caster.downcast_ref::<Caster<T>>()) 245 } 246 247 #[cfg(target_os = "none")] 248 { 249 caster_map() 250 .get(&(type_id, TypeId::of::<Caster<T>>())) 251 .and_then(|caster| caster.downcast_ref::<Caster<T>>()) 252 } 253 } 254 255 /// `CastFrom` must be extended by a trait that wants to allow for casting into another trait. 256 /// 257 /// It is used for obtaining a trait object for [`Any`] from a trait object for its sub-trait, 258 /// and blanket implemented for all `Sized + Any + 'static` types. 259 /// 260 /// # Examples 261 /// ```ignore 262 /// trait Source: CastFrom { 263 /// ... 264 /// } 265 /// ``` 266 pub trait CastFrom: Any + 'static { 267 /// Returns a immutable reference to `Any`, which is backed by the type implementing this trait. 268 fn ref_any(&self) -> &dyn Any; 269 270 /// Returns a mutable reference to `Any`, which is backed by the type implementing this trait. 271 fn mut_any(&mut self) -> &mut dyn Any; 272 273 /// Returns a `Box` of `Any`, which is backed by the type implementing this trait. 274 fn box_any(self: Box<Self>) -> Box<dyn Any>; 275 276 /// Returns an `Rc` of `Any`, which is backed by the type implementing this trait. 277 fn rc_any(self: Rc<Self>) -> Rc<dyn Any>; 278 } 279 280 /// `CastFromSync` must be extended by a trait that is `Any + Sync + Send + 'static` 281 /// and wants to allow for casting into another trait behind references and smart pointers 282 /// especially including `Arc`. 283 /// 284 /// It is used for obtaining a trait object for [`Any + Sync + Send + 'static`] from an object 285 /// for its sub-trait, and blanket implemented for all `Sized + Sync + Send + 'static` types. 286 /// 287 /// # Examples 288 /// ```ignore 289 /// trait Source: CastFromSync { 290 /// ... 291 /// } 292 /// ``` 293 pub trait CastFromSync: CastFrom + Sync + Send + 'static { 294 fn arc_any(self: Arc<Self>) -> Arc<dyn Any + Sync + Send + 'static>; 295 } 296 297 impl<T: Sized + Any + 'static> CastFrom for T { 298 fn ref_any(&self) -> &dyn Any { 299 self 300 } 301 302 fn mut_any(&mut self) -> &mut dyn Any { 303 self 304 } 305 306 fn box_any(self: Box<Self>) -> Box<dyn Any> { 307 self 308 } 309 310 fn rc_any(self: Rc<Self>) -> Rc<dyn Any> { 311 self 312 } 313 } 314 315 impl CastFrom for dyn Any + 'static { 316 fn ref_any(&self) -> &dyn Any { 317 self 318 } 319 320 fn mut_any(&mut self) -> &mut dyn Any { 321 self 322 } 323 324 fn box_any(self: Box<Self>) -> Box<dyn Any> { 325 self 326 } 327 328 fn rc_any(self: Rc<Self>) -> Rc<dyn Any> { 329 self 330 } 331 } 332 333 impl<T: Sized + Sync + Send + 'static> CastFromSync for T { 334 fn arc_any(self: Arc<Self>) -> Arc<dyn Any + Sync + Send + 'static> { 335 self 336 } 337 } 338 339 impl CastFrom for dyn Any + Sync + Send + 'static { 340 fn ref_any(&self) -> &dyn Any { 341 self 342 } 343 344 fn mut_any(&mut self) -> &mut dyn Any { 345 self 346 } 347 348 fn box_any(self: Box<Self>) -> Box<dyn Any> { 349 self 350 } 351 352 fn rc_any(self: Rc<Self>) -> Rc<dyn Any> { 353 self 354 } 355 } 356 357 impl CastFromSync for dyn Any + Sync + Send + 'static { 358 fn arc_any(self: Arc<Self>) -> Arc<dyn Any + Sync + Send + 'static> { 359 self 360 } 361 } 362 363 #[cfg(test)] 364 mod tests { 365 extern crate std; 366 use std::any::{Any, TypeId}; 367 use std::fmt::{Debug, Display}; 368 369 use linkme::distributed_slice; 370 371 use crate::{BoxedCaster, CastFromSync}; 372 373 use super::cast::*; 374 use super::*; 375 376 #[distributed_slice(super::CASTERS)] 377 static TEST_CASTER: fn() -> (TypeId, BoxedCaster) = create_test_caster; 378 379 #[derive(Debug)] 380 struct TestStruct; 381 382 trait SourceTrait: CastFromSync {} 383 384 impl SourceTrait for TestStruct {} 385 386 fn create_test_caster() -> (TypeId, BoxedCaster) { 387 let type_id = TypeId::of::<TestStruct>(); 388 let caster = Box::new(Caster::<dyn Debug> { 389 cast_ref: |from| from.downcast_ref::<TestStruct>().unwrap(), 390 cast_mut: |from| from.downcast_mut::<TestStruct>().unwrap(), 391 cast_box: |from| from.downcast::<TestStruct>().unwrap(), 392 cast_rc: |from| from.downcast::<TestStruct>().unwrap(), 393 cast_arc: |from| from.downcast::<TestStruct>().unwrap(), 394 }); 395 (type_id, caster) 396 } 397 398 #[test] 399 fn cast_ref() { 400 let ts = TestStruct; 401 let st: &dyn SourceTrait = &ts; 402 let debug = st.cast::<dyn Debug>(); 403 assert!(debug.is_some()); 404 } 405 406 #[test] 407 fn cast_mut() { 408 let mut ts = TestStruct; 409 let st: &mut dyn SourceTrait = &mut ts; 410 let debug = st.cast::<dyn Debug>(); 411 assert!(debug.is_some()); 412 } 413 414 #[test] 415 fn cast_box() { 416 let ts = Box::new(TestStruct); 417 let st: Box<dyn SourceTrait> = ts; 418 let debug = st.cast::<dyn Debug>(); 419 assert!(debug.is_ok()); 420 } 421 422 #[test] 423 fn cast_rc() { 424 let ts = Rc::new(TestStruct); 425 let st: Rc<dyn SourceTrait> = ts; 426 let debug = st.cast::<dyn Debug>(); 427 assert!(debug.is_ok()); 428 } 429 430 #[test] 431 fn cast_arc() { 432 let ts = Arc::new(TestStruct); 433 let st: Arc<dyn SourceTrait> = ts; 434 let debug = st.cast::<dyn Debug>(); 435 assert!(debug.is_ok()); 436 } 437 438 #[test] 439 fn cast_ref_wrong() { 440 let ts = TestStruct; 441 let st: &dyn SourceTrait = &ts; 442 let display = st.cast::<dyn Display>(); 443 assert!(display.is_none()); 444 } 445 446 #[test] 447 fn cast_mut_wrong() { 448 let mut ts = TestStruct; 449 let st: &mut dyn SourceTrait = &mut ts; 450 let display = st.cast::<dyn Display>(); 451 assert!(display.is_none()); 452 } 453 454 #[test] 455 fn cast_box_wrong() { 456 let ts = Box::new(TestStruct); 457 let st: Box<dyn SourceTrait> = ts; 458 let display = st.cast::<dyn Display>(); 459 assert!(display.is_err()); 460 } 461 462 #[test] 463 fn cast_rc_wrong() { 464 let ts = Rc::new(TestStruct); 465 let st: Rc<dyn SourceTrait> = ts; 466 let display = st.cast::<dyn Display>(); 467 assert!(display.is_err()); 468 } 469 470 #[test] 471 fn cast_arc_wrong() { 472 let ts = Arc::new(TestStruct); 473 let st: Arc<dyn SourceTrait> = ts; 474 let display = st.cast::<dyn Display>(); 475 assert!(display.is_err()); 476 } 477 478 #[test] 479 fn cast_ref_from_any() { 480 let ts = TestStruct; 481 let st: &dyn Any = &ts; 482 let debug = st.cast::<dyn Debug>(); 483 assert!(debug.is_some()); 484 } 485 486 #[test] 487 fn cast_mut_from_any() { 488 let mut ts = TestStruct; 489 let st: &mut dyn Any = &mut ts; 490 let debug = st.cast::<dyn Debug>(); 491 assert!(debug.is_some()); 492 } 493 494 #[test] 495 fn cast_box_from_any() { 496 let ts = Box::new(TestStruct); 497 let st: Box<dyn Any> = ts; 498 let debug = st.cast::<dyn Debug>(); 499 assert!(debug.is_ok()); 500 } 501 502 #[test] 503 fn cast_rc_from_any() { 504 let ts = Rc::new(TestStruct); 505 let st: Rc<dyn Any> = ts; 506 let debug = st.cast::<dyn Debug>(); 507 assert!(debug.is_ok()); 508 } 509 510 #[test] 511 fn cast_arc_from_any() { 512 let ts = Arc::new(TestStruct); 513 let st: Arc<dyn Any + Send + Sync> = ts; 514 let debug = st.cast::<dyn Debug>(); 515 assert!(debug.is_ok()); 516 } 517 518 #[test] 519 fn impls_ref() { 520 let ts = TestStruct; 521 let st: &dyn SourceTrait = &ts; 522 assert!(st.impls::<dyn Debug>()); 523 } 524 525 #[test] 526 fn impls_mut() { 527 let mut ts = TestStruct; 528 let st: &mut dyn SourceTrait = &mut ts; 529 assert!((*st).impls::<dyn Debug>()); 530 } 531 532 #[test] 533 fn impls_box() { 534 let ts = Box::new(TestStruct); 535 let st: Box<dyn SourceTrait> = ts; 536 assert!((*st).impls::<dyn Debug>()); 537 } 538 539 #[test] 540 fn impls_rc() { 541 let ts = Rc::new(TestStruct); 542 let st: Rc<dyn SourceTrait> = ts; 543 assert!((*st).impls::<dyn Debug>()); 544 } 545 546 #[test] 547 fn impls_arc() { 548 let ts = Arc::new(TestStruct); 549 let st: Arc<dyn SourceTrait> = ts; 550 assert!((*st).impls::<dyn Debug>()); 551 } 552 553 #[test] 554 fn impls_not_ref() { 555 let ts = TestStruct; 556 let st: &dyn SourceTrait = &ts; 557 assert!(!st.impls::<dyn Display>()); 558 } 559 560 #[test] 561 fn impls_not_mut() { 562 let mut ts = TestStruct; 563 let st: &mut dyn Any = &mut ts; 564 assert!(!(*st).impls::<dyn Display>()); 565 } 566 567 #[test] 568 fn impls_not_box() { 569 let ts = Box::new(TestStruct); 570 let st: Box<dyn SourceTrait> = ts; 571 assert!(!st.impls::<dyn Display>()); 572 } 573 574 #[test] 575 fn impls_not_rc() { 576 let ts = Rc::new(TestStruct); 577 let st: Rc<dyn SourceTrait> = ts; 578 assert!(!(*st).impls::<dyn Display>()); 579 } 580 581 #[test] 582 fn impls_not_arc() { 583 let ts = Arc::new(TestStruct); 584 let st: Arc<dyn SourceTrait> = ts; 585 assert!(!(*st).impls::<dyn Display>()); 586 } 587 } 588