use crate::AnyFnError;
use alloc::boxed::Box;
use core::{
any::{Any, TypeId},
cell::{Ref, RefCell, RefMut},
};
pub struct Value(RefCell<Box<dyn Any>>);
impl Value {
pub fn new(value: impl Any) -> Self {
Self(RefCell::new(Box::new(value)))
}
pub fn type_id(&self) -> Result<TypeId, AnyFnError> {
Ok((**self.0.try_borrow()?).type_id())
}
pub fn downcast<T: Any>(self) -> Result<T, AnyFnError> {
self.0
.into_inner()
.downcast()
.map_err(|_| AnyFnError::Downcast)
.map(|value| *value)
}
pub fn downcast_ref<T: Any>(&self) -> Result<Ref<'_, T>, AnyFnError> {
Ref::filter_map(self.0.try_borrow()?, |value| value.downcast_ref())
.map_err(|_| AnyFnError::Downcast)
}
pub fn downcast_mut<T: Any>(&self) -> Result<RefMut<'_, T>, AnyFnError> {
RefMut::filter_map(self.0.try_borrow_mut()?, |value| value.downcast_mut())
.map_err(|_| AnyFnError::Downcast)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn type_id() {
assert_eq!(
Value::new(42usize).type_id().unwrap(),
TypeId::of::<usize>()
);
}
}