[][src]Crate traitcast

#' Casting from Any

In the standard library, the std::any::Any trait comes with downcast methods which let you cast from an Any trait object to a concrete type.

let x: i32 = 7;
let y: &dyn Any = &x;

// Cast to i32 succeeds because x: i32
assert_eq!(y.downcast_ref::<i32>(), Some(&7));
// Cast to f32 fails
assert_eq!(y.downcast_ref::<f32>(), None);

However, it is not possible to downcast to a trait object.

This example deliberately fails to compile
use std::any::Any;
trait Foo {
    fn foo(&self) -> i32;
}

struct A {
    x: i32
}

impl Foo for A {
    fn foo(&self) -> i32 {
        self.x
    }
}

let x = A { x: 7 };
let y: &dyn Any = &x;

// This cast is not possible, because it is only possible to cast to types that
// are Sized. Among other things, this precludes trait objects.
let z: Option<&dyn Foo> = y.downcast_ref();

Traitcast

This library provides a way of casting from dyn Any to trait objects.

use std::any::Any;

// Register the trait.
traitcast::register_trait!(Foo, Foo_Traitcast);

// For each struct that implements the trait, register the implementation.
traitcast::register_impl!(Foo, A);

fn main() {
    let mut x = A { x: 7 };

    {
        let y: &dyn Any = &x;
        // Test whether y is of a type that implements Foo.
        assert!(traitcast::implements_trait::<Foo>(y));
    }

    {
        let y: &dyn Any = &x;
        // Cast an immutable reference.
        let z: &dyn Foo = traitcast::cast_ref(y).unwrap();
        assert_eq!(z.foo(), 7);
    }

    {
        let y: &mut dyn Any = &mut x;
        // Cast a mutable reference
        let z: &mut dyn Foo = traitcast::cast_mut(y).unwrap();
        assert_eq!(z.foo(), 7);
    }

    {
        let y: Box<Any> = Box::new(x);
        // Cast a boxed reference
        let z: Box<dyn Foo> = traitcast::cast_box(y).unwrap();
        assert_eq!(z.foo(), 7);
    }
}

Modules

private

Macros

register_impl

Register an implementation of a castable trait for a particular struct. The struct must implement the trait. This enables objects of this type to be cast into dynamic trait references of this trait, via an Any pointer. It is best not to invoke register_impl! multiple times for the same implementation. This will have no effect but to slightly slow down program load time.

register_trait

Register a trait to allow it to be cast into. Cannot cast from implementing structs unless register_impl is also called for that struct.

Traits

CastableDynTrait

Trait objects that can be cast into implement this trait.

Functions

cast_box

Tries to cast the given pointer to a dynamic trait object. This will always return Err if the implementation of the trait, for the concrete type of x, has not been registered.

cast_mut

Tries to cast the given mutable reference to a dynamic trait object. This will always return None if the implementation of the trait, for the concrete type of x, has not been registered.

cast_ref

Tries to cast the given reference to a dynamic trait object. This will always return None if the implementation of the trait, for the concrete type of x, has not been registered.

implements_trait

Tests whether the given value is castable to some trait object.