apple-quant-core 0.2.0

Apple Quant's core library.
Documentation
use std::ops::Deref;

use smallvec::SmallVec;
use tracing::Subscriber;

use tracing_subscriber::{layer::Context, registry::LookupSpan};

use super::{Ctx, Frame, StaticError};

#[derive(Debug, Default)]
pub(crate) struct ChainLink {
	pub(crate) frame: Option<Frame>,
	pub(crate) message: Option<String>,
}

#[derive(Debug, Default)]
pub(crate) struct Chain(SmallVec<[ChainLink; 16]>);

impl Chain {
	pub(crate) fn new<S>(
		tracing_context: &Context<'_, S>,
		error: &StaticError,
	) -> Self
	where
		S: Subscriber + for<'l> LookupSpan<'l>,
	{
		let mut chain = Self::default();
		let mut current_error = Some(error);

		while let Some(
			error,
		) = current_error {
			let Some(
				ctx,
			) = error.downcast_ref::<Ctx>() else {
				chain.0.push(ChainLink {
					frame: None,
					message: Some(error.to_string()),
				});

				current_error = error.source();
				continue;
			};

			let span_ref = ctx.span.id().and_then(|id| tracing_context.span(&id));

			let Some(
				span_ref,
			) = span_ref else {
				let chain_link = ChainLink {
					frame: None,
					message: ctx.message.clone(),
				};

				chain.0.push(chain_link);
				continue;
			};

			let frame = Frame::new(span_ref, &ctx.location);

			chain.0.push(ChainLink {
				frame,
				message: Some(error.to_string()),
			});

			current_error = error.source();
		}

		chain
	}
}

impl Deref for Chain {
	type Target = SmallVec<[ChainLink; 16]>;

	fn deref(
		&self,
	) -> &Self::Target {
		&self.0
	}
}