use core::error::Error;
use core::fmt;
#[cfg(feature = "alloc")]
use crate::alloc::Global;
use crate::{Allocator, Context};
use super::{
Capture, ContextError, Emit, ErrorMode, Errors, Ignore, NoTrace, Report, Trace, TraceImpl,
TraceMode,
};
pub struct DefaultContext<A, T, C>
where
A: Allocator,
T: TraceMode,
{
alloc: A,
trace: T::Impl<A>,
capture: C,
}
#[cfg(feature = "alloc")]
impl DefaultContext<Global, NoTrace, Ignore> {
#[inline]
pub(super) fn new() -> Self {
Self::new_in(Global::new())
}
}
impl<A> DefaultContext<A, NoTrace, Ignore>
where
A: Allocator,
{
#[inline]
pub(super) fn new_in(alloc: A) -> Self {
let trace = NoTrace::new_in(alloc);
Self {
alloc,
trace,
capture: Ignore,
}
}
}
#[cfg(feature = "alloc")]
impl Default for DefaultContext<Global, NoTrace, Ignore> {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl<A, T, C> DefaultContext<A, T, C>
where
A: Allocator,
T: TraceMode,
C: ErrorMode<A>,
{
#[inline]
pub fn with_trace(self) -> DefaultContext<A, Trace, C> {
let trace = Trace::new_in(self.alloc);
DefaultContext {
alloc: self.alloc,
trace,
capture: self.capture,
}
}
#[inline]
pub fn with_capture<E>(self) -> DefaultContext<A, T, Capture<E>>
where
E: ContextError<A>,
{
DefaultContext {
alloc: self.alloc,
trace: self.trace,
capture: Capture::new(),
}
}
#[inline]
pub fn with_error<E>(self) -> DefaultContext<A, T, Emit<E>>
where
E: ContextError<A>,
{
DefaultContext {
alloc: self.alloc,
trace: self.trace,
capture: Emit::new(),
}
}
}
impl<A, C> DefaultContext<A, Trace, C>
where
A: Allocator,
{
#[inline]
pub fn with_type(mut self) -> Self {
self.trace.include_type();
self
}
#[inline]
pub fn report(&self) -> Report<'_, A> {
self.trace.report()
}
#[inline]
pub fn errors(&self) -> Errors<'_, A> {
self.trace.errors()
}
}
impl<A, T, E> DefaultContext<A, T, Capture<E>>
where
A: Allocator,
T: TraceMode,
E: ContextError<A>,
{
#[inline]
pub fn unwrap(&self) -> E {
self.capture.unwrap()
}
#[inline]
pub fn result(&self) -> Result<(), E> {
self.capture.result()
}
}
impl<A, T, C> Context for &DefaultContext<A, T, C>
where
A: Allocator,
T: TraceMode,
C: ErrorMode<A>,
{
type Error = C::Error;
type Mark = <<T as TraceMode>::Impl<A> as TraceImpl<A>>::Mark;
type Allocator = A;
#[inline]
fn clear(self) {
self.trace.clear();
self.capture.clear();
}
#[inline]
fn alloc(self) -> Self::Allocator {
self.alloc
}
#[inline]
fn custom<E>(self, message: E) -> Self::Error
where
E: 'static + Send + Sync + Error,
{
self.trace.custom(self.alloc, &message);
self.capture.custom(self.alloc, message)
}
#[inline]
fn message<M>(self, message: M) -> Self::Error
where
M: fmt::Display,
{
self.trace.message(self.alloc, &message);
self.capture.message(self.alloc, message)
}
#[inline]
fn message_at<M>(self, mark: &Self::Mark, message: M) -> Self::Error
where
M: fmt::Display,
{
self.trace.message_at(self.alloc, mark, &message);
self.capture.message(self.alloc, message)
}
#[inline]
fn custom_at<E>(self, mark: &Self::Mark, message: E) -> Self::Error
where
E: 'static + Send + Sync + Error,
{
self.trace.custom_at(self.alloc, mark, &message);
self.capture.custom(self.alloc, message)
}
#[inline]
fn mark(self) -> Self::Mark {
self.trace.mark()
}
#[inline]
fn restore(self, mark: &Self::Mark) {
self.trace.restore(mark);
}
#[inline]
fn advance(self, n: usize) {
self.trace.advance(n);
}
#[inline]
fn enter_named_field<F>(self, name: &'static str, field: F)
where
F: fmt::Display,
{
self.trace.enter_named_field(name, &field);
}
#[inline]
fn enter_unnamed_field<F>(self, index: u32, name: F)
where
F: fmt::Display,
{
self.trace.enter_unnamed_field(index, &name);
}
#[inline]
fn leave_field(self) {
self.trace.leave_field();
}
#[inline]
fn enter_struct(self, name: &'static str) {
self.trace.enter_struct(name);
}
#[inline]
fn leave_struct(self) {
self.trace.leave_struct();
}
#[inline]
fn enter_enum(self, name: &'static str) {
self.trace.enter_enum(name);
}
#[inline]
fn leave_enum(self) {
self.trace.leave_enum();
}
#[inline]
fn enter_variant<V>(self, name: &'static str, tag: V)
where
V: fmt::Display,
{
self.trace.enter_variant(name, &tag);
}
#[inline]
fn leave_variant(self) {
self.trace.leave_variant();
}
#[inline]
fn enter_sequence_index(self, index: usize) {
self.trace.enter_sequence_index(index);
}
#[inline]
fn leave_sequence_index(self) {
self.trace.leave_sequence_index();
}
#[inline]
fn enter_map_key<F>(self, field: F)
where
F: fmt::Display,
{
self.trace.enter_map_key(self.alloc, &field);
}
#[inline]
fn leave_map_key(self) {
self.trace.leave_map_key();
}
}