use crate::{CordisError, ErrorCode, Result};
use std::any::{Any, type_name};
use std::fmt::{self, Debug, Formatter};
use std::sync::Arc;
#[derive(Clone)]
pub struct Value {
inner: Arc<dyn Any + Send + Sync>,
type_name: &'static str,
}
impl Value {
pub fn new<T>(value: T) -> Self
where
T: Any + Send + Sync,
{
Self {
inner: Arc::new(value),
type_name: type_name::<T>(),
}
}
pub fn from_arc<T>(value: Arc<T>) -> Self
where
T: Any + Send + Sync,
{
Self {
inner: value,
type_name: type_name::<T>(),
}
}
pub const fn type_name(&self) -> &'static str {
self.type_name
}
pub fn is<T: Any>(&self) -> bool {
self.inner.is::<T>()
}
pub fn downcast<T>(&self) -> Result<Arc<T>>
where
T: Any + Send + Sync,
{
self.inner.clone().downcast::<T>().map_err(|_| {
CordisError::with_message(
ErrorCode::TypeMismatch,
format!(
"expected value of type `{}`, found `{}`",
type_name::<T>(),
self.type_name
),
)
})
}
pub fn as_any(&self) -> &(dyn Any + Send + Sync) {
self.inner.as_ref()
}
pub(crate) fn ptr_eq(&self, other: &Value) -> bool {
Arc::ptr_eq(&self.inner, &other.inner)
}
}
impl Default for Value {
fn default() -> Self {
Self::new(())
}
}
impl Debug for Value {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("Value")
.field("type_name", &self.type_name)
.finish_non_exhaustive()
}
}
pub type Config = Value;