#![expect(deprecated, reason = "We use `Context` to maintain compatibility")]
use alloc::boxed::Box;
use core::{any::Any, error::Error, fmt};
use crate::{AttachmentKind, Context, Frame, FrameKind};
pub(super) trait FrameImpl: Send + Sync + 'static {
fn kind(&self) -> FrameKind<'_>;
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
fn into_any(self: Box<Self>) -> Box<dyn Any + Send + Sync>;
}
impl fmt::Debug for Box<dyn FrameImpl> {
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
unreachable!()
}
}
impl fmt::Display for Box<dyn FrameImpl> {
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
unreachable!()
}
}
impl Error for Box<dyn FrameImpl> {}
struct ContextFrame<C> {
context: C,
}
impl<C: Context> FrameImpl for ContextFrame<C> {
fn kind(&self) -> FrameKind<'_> {
FrameKind::Context(&self.context)
}
fn as_any(&self) -> &dyn Any {
&self.context
}
fn as_any_mut(&mut self) -> &mut dyn Any {
&mut self.context
}
fn into_any(self: Box<Self>) -> Box<dyn Any + Send + Sync> {
Box::new(self.context)
}
}
struct AttachmentFrame<A> {
attachment: A,
}
impl<A: 'static + Send + Sync> FrameImpl for AttachmentFrame<A> {
fn kind(&self) -> FrameKind<'_> {
FrameKind::Attachment(AttachmentKind::Opaque(&self.attachment))
}
fn as_any(&self) -> &dyn Any {
&self.attachment
}
fn as_any_mut(&mut self) -> &mut dyn Any {
&mut self.attachment
}
fn into_any(self: Box<Self>) -> Box<dyn Any + Send + Sync> {
Box::new(self.attachment)
}
}
struct PrintableAttachmentFrame<A> {
attachment: A,
}
impl<A: 'static + fmt::Debug + fmt::Display + Send + Sync> FrameImpl
for PrintableAttachmentFrame<A>
{
fn kind(&self) -> FrameKind<'_> {
FrameKind::Attachment(AttachmentKind::Printable(&self.attachment))
}
fn as_any(&self) -> &dyn Any {
&self.attachment
}
fn as_any_mut(&mut self) -> &mut dyn Any {
&mut self.attachment
}
fn into_any(self: Box<Self>) -> Box<dyn Any + Send + Sync> {
Box::new(self.attachment)
}
}
#[cfg(feature = "anyhow")]
struct AnyhowContext(anyhow::Error);
#[cfg(feature = "anyhow")]
impl fmt::Debug for AnyhowContext {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.0, f)
}
}
#[cfg(feature = "anyhow")]
impl fmt::Display for AnyhowContext {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
#[cfg(feature = "anyhow")]
impl Context for AnyhowContext {}
#[cfg(feature = "anyhow")]
impl FrameImpl for AnyhowContext {
fn kind(&self) -> FrameKind<'_> {
FrameKind::Context(self)
}
fn as_any(&self) -> &dyn Any {
&self.0
}
fn as_any_mut(&mut self) -> &mut dyn Any {
&mut self.0
}
fn into_any(self: Box<Self>) -> Box<dyn Any + Send + Sync> {
Box::new(self.0)
}
}
#[cfg(feature = "eyre")]
struct EyreContext(eyre::Report);
#[cfg(feature = "eyre")]
impl fmt::Debug for EyreContext {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.0, f)
}
}
#[cfg(feature = "eyre")]
impl fmt::Display for EyreContext {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
#[cfg(feature = "eyre")]
impl Context for EyreContext {}
#[cfg(feature = "eyre")]
impl FrameImpl for EyreContext {
fn kind(&self) -> FrameKind<'_> {
FrameKind::Context(self)
}
fn as_any(&self) -> &dyn Any {
&self.0
}
fn as_any_mut(&mut self) -> &mut dyn Any {
&mut self.0
}
fn into_any(self: Box<Self>) -> Box<dyn Any + Send + Sync> {
Box::new(self.0)
}
}
impl Frame {
pub(crate) fn from_context<C>(context: C, sources: Box<[Self]>) -> Self
where
C: Context,
{
Self {
frame: Box::new(ContextFrame { context }),
sources,
}
}
pub(crate) fn from_attachment<A>(attachment: A, sources: Box<[Self]>) -> Self
where
A: Send + Sync + 'static,
{
Self {
frame: Box::new(AttachmentFrame { attachment }),
sources,
}
}
pub(crate) fn from_printable_attachment<A>(attachment: A, sources: Box<[Self]>) -> Self
where
A: fmt::Display + fmt::Debug + Send + Sync + 'static,
{
Self {
frame: Box::new(PrintableAttachmentFrame { attachment }),
sources,
}
}
#[cfg(feature = "anyhow")]
pub(crate) fn from_anyhow(error: anyhow::Error, sources: Box<[Self]>) -> Self {
Self {
frame: Box::new(AnyhowContext(error)),
sources,
}
}
#[cfg(feature = "eyre")]
pub(crate) fn from_eyre(report: eyre::Report, sources: Box<[Self]>) -> Self {
Self {
frame: Box::new(EyreContext(report)),
sources,
}
}
}