use alloc::borrow::Cow;
use alloc::boxed::Box;
use core::fmt;
use crate::AtCrateInfo;
pub(crate) trait AtDebugAny: core::any::Any + fmt::Debug + Send + Sync {
fn as_any(&self) -> &dyn core::any::Any;
fn type_name(&self) -> &'static str;
}
impl<T: core::any::Any + fmt::Debug + Send + Sync> AtDebugAny for T {
fn as_any(&self) -> &dyn core::any::Any {
self
}
fn type_name(&self) -> &'static str {
core::any::type_name::<T>()
}
}
pub(crate) trait AtDisplayAny: core::any::Any + fmt::Display + Send + Sync {
fn as_any(&self) -> &dyn core::any::Any;
fn type_name(&self) -> &'static str;
}
impl<T: core::any::Any + fmt::Display + Send + Sync> AtDisplayAny for T {
fn as_any(&self) -> &dyn core::any::Any {
self
}
fn type_name(&self) -> &'static str {
core::any::type_name::<T>()
}
}
#[non_exhaustive]
pub(crate) enum AtContext {
Text(Cow<'static, str>),
FunctionName(&'static str),
Debug(Box<dyn AtDebugAny>),
Display(Box<dyn AtDisplayAny>),
Crate(&'static AtCrateInfo),
Error(Box<dyn core::error::Error + Send + Sync>),
}
impl AtContext {
pub(crate) fn as_text(&self) -> Option<&str> {
match self {
AtContext::Text(s) => Some(s),
_ => None,
}
}
pub(crate) fn as_function_name(&self) -> Option<&'static str> {
match self {
AtContext::FunctionName(s) => Some(s),
_ => None,
}
}
pub(crate) fn as_crate_info(&self) -> Option<&'static AtCrateInfo> {
match self {
AtContext::Crate(info) => Some(info),
_ => None,
}
}
pub(crate) fn as_error(&self) -> Option<&(dyn core::error::Error + Send + Sync)> {
match self {
AtContext::Error(e) => Some(&**e),
_ => None,
}
}
pub(crate) fn downcast_ref<T: 'static>(&self) -> Option<&T> {
match self {
AtContext::Text(_)
| AtContext::FunctionName(_)
| AtContext::Crate(_)
| AtContext::Error(_) => None,
AtContext::Debug(b) => (**b).as_any().downcast_ref(),
AtContext::Display(b) => (**b).as_any().downcast_ref(),
}
}
pub(crate) fn type_name(&self) -> Option<&'static str> {
match self {
AtContext::Text(_)
| AtContext::FunctionName(_)
| AtContext::Crate(_)
| AtContext::Error(_) => None,
AtContext::Debug(b) => Some((**b).type_name()),
AtContext::Display(b) => Some((**b).type_name()),
}
}
pub(crate) fn is_display(&self) -> bool {
matches!(
self,
AtContext::Text(_) | AtContext::Display(_) | AtContext::Error(_)
)
}
pub(crate) fn is_function_name(&self) -> bool {
matches!(self, AtContext::FunctionName(_))
}
pub(crate) fn is_crate_boundary(&self) -> bool {
matches!(self, AtContext::Crate(_))
}
pub(crate) fn is_error(&self) -> bool {
matches!(self, AtContext::Error(_))
}
}
impl fmt::Debug for AtContext {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AtContext::Text(s) => write!(f, "{:?}", s),
AtContext::FunctionName(s) => write!(f, "in {}", s),
AtContext::Debug(t) => write!(f, "{:?}", &**t),
AtContext::Display(t) => write!(f, "{}", &**t), AtContext::Crate(info) => write!(f, "[crate: {}]", info.name()),
AtContext::Error(e) => write!(f, "caused by: {}", e),
}
}
}
impl fmt::Display for AtContext {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AtContext::Text(s) => write!(f, "{}", s),
AtContext::FunctionName(s) => write!(f, "in {}", s),
AtContext::Debug(t) => write!(f, "{:?}", &**t), AtContext::Display(t) => write!(f, "{}", &**t),
AtContext::Crate(info) => write!(f, "[crate: {}]", info.name()),
AtContext::Error(e) => write!(f, "caused by: {}", e),
}
}
}
#[derive(Clone, Copy)]
pub struct AtContextRef<'a> {
pub(crate) inner: &'a AtContext,
}
impl<'a> AtContextRef<'a> {
#[inline]
pub fn as_text(&self) -> Option<&'a str> {
self.inner.as_text()
}
#[inline]
pub fn as_function_name(&self) -> Option<&'static str> {
self.inner.as_function_name()
}
#[inline]
pub fn is_function_name(&self) -> bool {
self.inner.is_function_name()
}
#[inline]
pub fn as_crate_info(&self) -> Option<&'static AtCrateInfo> {
self.inner.as_crate_info()
}
#[inline]
pub fn downcast_ref<T: 'static>(&self) -> Option<&'a T> {
self.inner.downcast_ref()
}
#[inline]
pub fn type_name(&self) -> Option<&'static str> {
self.inner.type_name()
}
#[inline]
pub fn is_display(&self) -> bool {
self.inner.is_display()
}
#[inline]
pub fn is_crate_boundary(&self) -> bool {
self.inner.is_crate_boundary()
}
#[inline]
pub fn as_error(&self) -> Option<&'a (dyn core::error::Error + Send + Sync)> {
self.inner.as_error()
}
#[inline]
pub fn is_error(&self) -> bool {
self.inner.is_error()
}
}
impl fmt::Debug for AtContextRef<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self.inner, f)
}
}
impl fmt::Display for AtContextRef<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self.inner, f)
}
}