108 lines
2.2 KiB
Rust
108 lines
2.2 KiB
Rust
use std::borrow::Cow;
|
|
|
|
use crate::{Report, ReportFmt};
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct Context(ContextInner);
|
|
|
|
impl Context {
|
|
pub fn chain(mut self, other: impl IntoContext) -> Self {
|
|
if let ContextInner::Compound(ref mut vec) = self.0 {
|
|
vec.push(other.into_context());
|
|
} else {
|
|
self = Context(ContextInner::Compound(vec![self, other.into_context()]))
|
|
}
|
|
self
|
|
}
|
|
}
|
|
|
|
impl Report for Context {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>, opts: &ReportFmt) -> std::fmt::Result {
|
|
use std::fmt::Write;
|
|
match self.0 {
|
|
ContextInner::String(ref s) => s.fmt(f, opts)?,
|
|
ContextInner::Compound(ref ctxs) => {
|
|
let mut opts = *opts;
|
|
for ctx in ctxs {
|
|
ctx.fmt(f, &opts)?;
|
|
f.write_char('\n')?;
|
|
opts = opts.next();
|
|
}
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
enum ContextInner {
|
|
String(Cow<'static, str>),
|
|
Compound(Vec<Context>),
|
|
}
|
|
|
|
pub trait IntoContext {
|
|
fn into_context(self) -> Context;
|
|
|
|
#[inline]
|
|
fn chain(self, other: impl IntoContext) -> Context
|
|
where
|
|
Self: Sized,
|
|
{
|
|
self.into_context().chain(other)
|
|
}
|
|
}
|
|
|
|
impl IntoContext for Context {
|
|
#[inline(always)]
|
|
fn into_context(self) -> Context {
|
|
self
|
|
}
|
|
}
|
|
|
|
impl IntoContext for String {
|
|
#[inline]
|
|
fn into_context(self) -> Context {
|
|
Context(ContextInner::String(self.into()))
|
|
}
|
|
}
|
|
|
|
impl IntoContext for &'static str {
|
|
#[inline]
|
|
fn into_context(self) -> Context {
|
|
Context(ContextInner::String(self.into()))
|
|
}
|
|
}
|
|
|
|
impl IntoContext for Cow<'static, str> {
|
|
#[inline]
|
|
fn into_context(self) -> Context {
|
|
Context(ContextInner::String(self))
|
|
}
|
|
}
|
|
|
|
impl<C, F> IntoContext for F
|
|
where
|
|
C: IntoContext,
|
|
F: FnOnce() -> C,
|
|
{
|
|
#[inline(always)]
|
|
fn into_context(self) -> Context {
|
|
self().into_context()
|
|
}
|
|
}
|
|
|
|
pub trait ToContext {
|
|
fn to_context(&self) -> Context;
|
|
}
|
|
|
|
impl<C, F> ToContext for F
|
|
where
|
|
C: IntoContext,
|
|
F: Fn() -> C,
|
|
{
|
|
#[inline(always)]
|
|
fn to_context(&self) -> Context {
|
|
self().into_context()
|
|
}
|
|
}
|