blob: 88e5c90c4a5b996a472c64d6fc912f7ec7d2657b (
plain) (
tree)
|
|
// Anycast - Any upcasting
// Copyright (C) 2022 Soni L.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//! Anycast is a library for casting to `::core::any::Any`.
#![cfg_attr(not(feature="std"), no_std)]
use ::core::any::Any;
#[cfg(feature="alloc")]
extern crate alloc;
#[cfg(feature="alloc")]
use ::alloc::boxed::Box;
mod sealed {
pub trait Sealed {
}
}
use sealed::Sealed;
/// Trait for casting to [`::core::any::Any`].
///
/// This is useful to add to your own traits, when you want to expose `Any`
/// upcasting (and downcasting!) ability to your users, on your object-safe
/// traits.
///
/// # Examples
///
/// ```rust
/// use ::anycast::Anycast;
///
/// trait Foo: Anycast {
/// fn foo(&mut self);
/// }
///
/// impl Foo for i32 {
/// fn foo(&mut self) {
/// *self += 1;
/// }
/// }
///
/// let mut x = 10;
/// let x: &mut dyn Foo = &mut x;
/// x.foo();
/// // it's recommended to use Anycast::* due to weird implicit (de)ref.
/// assert_eq!(Anycast::any_ref(x).downcast_ref::<i32>().unwrap(), &11);
/// ```
pub trait Anycast: Any + Sealed {
/// Casts `&Self` to `&dyn Any`.
fn any_ref(&self) -> &dyn Any;
/// Casts `&mut Self` to `&mut dyn Any`.
fn any_mut(&mut self) -> &mut dyn Any;
#[cfg(feature="alloc")]
/// Casts `Box<Self>` to `Box<dyn Any>`.
fn into_any(self: Box<Self>) -> Box<dyn Any>;
}
impl<T> Sealed for T where T: Any {
}
impl<T> Anycast for T where T: Any {
fn any_ref(&self) -> &dyn Any {
self
}
fn any_mut(&mut self) -> &mut dyn Any {
self
}
#[cfg(feature="alloc")]
fn into_any(self: Box<Self>) -> Box<dyn Any> {
self
}
}
#[cfg(test)]
mod test {
use super::Anycast;
#[test]
fn test_anycast() {
let string = "foo";
let anycast: &dyn Anycast = &string;
let any = anycast.any_ref();
let string_ref = any.downcast_ref::<&'static str>().unwrap();
assert!(::core::ptr::eq(string, *string_ref));
}
}
|