Skip to content

Commit

Permalink
Added attachment::Dbg (#12)
Browse files Browse the repository at this point in the history
Approved by: @gshuflin, @jkleinknox, @jsgoyette
============
Introduced `attachment::Dbg` to avoid prematurely allocating `String`s through early `format!` calls.

* Moved most `Reportable` method implementations out of `reportable!` and into blanket implementations under the trait proper.
* Removed `ResultAttachExt`
  • Loading branch information
mkatychev authored May 3, 2024
1 parent 5860a60 commit 78e88cb
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 217 deletions.
98 changes: 57 additions & 41 deletions src/attachment.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::time::Duration;
use std::{any, fmt, time::Duration};

use tracing::error;

Expand All @@ -7,22 +7,37 @@ pub use thiserror;

use crate::reportable;

pub trait Display: std::fmt::Display + std::fmt::Debug + Send + Sync + 'static {}
pub trait Display: fmt::Display + fmt::Debug + Send + Sync + 'static {}

impl<A> Display for A where A: std::fmt::Display + std::fmt::Debug + Send + Sync + 'static {}
impl<A> Display for A where A: fmt::Display + fmt::Debug + Send + Sync + 'static {}

pub trait Debug: std::fmt::Debug + Send + Sync + 'static {}
pub trait Debug: fmt::Debug + Send + Sync + 'static {}

impl<A> Debug for A where A: std::fmt::Debug + Send + Sync + 'static {}
impl<A> Debug for A where A: fmt::Debug + Send + Sync + 'static {}

// used to wrap types that only implement `std::fmt::Debug`
#[derive(Debug)]
pub struct Dbg<A: Debug>(pub A);

impl<A: Debug> fmt::Display for Dbg<A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self.0)
}
}

// simple key-value pair attachment
#[derive(Debug, PartialEq, thiserror::Error)]
#[error("{0}: {1}")]
#[derive(Debug, PartialEq)]
pub struct KeyValue<K, V>(pub K, pub V);

impl KeyValue<String, String> {
pub fn dbg(key: impl Debug, value: impl Debug) -> Self {
Self(format!("{key:?}"), format!("{value:?}"))
impl<K: fmt::Display, V: fmt::Display> fmt::Display for KeyValue<K, V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}: {}", self.0, self.1)
}
}

impl<K: Display, V: Debug> KeyValue<K, Dbg<V>> {
pub fn dbg(key: K, value: V) -> Self {
Self(key, Dbg(value))
}
}

Expand All @@ -48,8 +63,8 @@ pub struct Field<Id, S> {
status: S,
}

impl<Id: Display, S: Display> std::fmt::Display for Field<Id, S> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
impl<Id: Display, S: Display> fmt::Display for Field<Id, S> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}: {}", self.id, self.status)
}
}
Expand All @@ -67,22 +82,22 @@ pub struct Type(&'static str);
impl Type {
// const fn when type_name is const fn in stable
pub fn of<T>() -> Self {
Self(std::any::type_name::<T>())
Self(any::type_name::<T>())
}

pub fn of_val<T: ?Sized>(_val: &T) -> Self {
Self(std::any::type_name::<T>())
Self(any::type_name::<T>())
}
}

impl std::fmt::Display for Type {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
impl fmt::Display for Type {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<{}>", self.0)
}
}

impl std::fmt::Debug for Type {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
impl fmt::Debug for Type {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("Type").field(&self.0).finish()
}
}
Expand Down Expand Up @@ -132,8 +147,8 @@ enum Symbol {
Space,
}

impl std::fmt::Display for Symbol {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
impl fmt::Display for Symbol {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let utf8 = match self {
Self::Vertical => "\u{2502}", // │
Self::VerticalRight => "\u{251c}", // ├
Expand All @@ -144,36 +159,37 @@ impl std::fmt::Display for Symbol {
Self::CurveRight => "\u{2570}", // ╰
Self::Space => " ",
};
write!(f, "{}", utf8)
write!(f, "{utf8}")
}
}

impl<E: Display, A: Display> std::fmt::Display for Expectation<E, A> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let cr = Symbol::CurveRight;
let hl = Symbol::HorizontalLeft;
write!(
f,
"{}\n{cr}{hl}{}",
KeyValue("expected", &self.expected),
KeyValue("actual", &self.actual)
)
impl<E: Display, A: Display> fmt::Display for Expectation<E, A> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let curve_right = Symbol::CurveRight;
let horizontal_left = Symbol::HorizontalLeft;
let expected = KeyValue("expected", &self.expected);
let actual = KeyValue("actual", &self.actual);
// "expected": expected
// ╰╴"actual": actual
write!(f, "{expected}\n{curve_right}{horizontal_left}{actual}")
}
}
impl<F: Display, T: Display> std::fmt::Display for FromTo<F, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let cr = Symbol::CurveRight;
let hl = Symbol::HorizontalLeft;
impl<F: Display, T: Display> fmt::Display for FromTo<F, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let curve_right = Symbol::CurveRight;
let horizontal_left = Symbol::HorizontalLeft;
let from = KeyValue("from", &self.0);
let to = KeyValue("to", &self.1);
write!(f, "{from}\n{cr}{hl}{to}",)
// "from": from
// ╰╴"to": to
write!(f, "{from}\n{curve_right}{horizontal_left}{to}")
}
}

#[derive(Debug)]
pub struct DisplayDuration(pub Duration);
impl std::fmt::Display for DisplayDuration {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
impl fmt::Display for DisplayDuration {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", hms_string(self.0))
}
}
Expand Down Expand Up @@ -221,11 +237,11 @@ pub fn hms_string(duration: Duration) -> String {

// this is meant to explicitly indicate
// that the underlying `A` is being
// used as an index key for getter methods
// used as an index key for getter methods in a collection
// such as `HashMap` keys and `Vec` indices
#[derive(Debug, thiserror::Error)]
#[error("Index[{0}]")]
pub struct Index<I: std::fmt::Display>(pub I);
#[error("idx [{0}: {}]", std::any::type_name::<I>())]
pub struct Index<I: fmt::Display>(pub I);

#[cfg(test)]
mod test {
Expand Down
4 changes: 2 additions & 2 deletions src/context.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{path::Path, time::Duration};
use std::{any, path::Path, time::Duration};

use error_stack::Context;

Expand Down Expand Up @@ -163,7 +163,7 @@ impl InvalidInput {

#[track_caller]
pub fn type_name<T: ?Sized>() -> Report<Self> {
let type_name = std::any::type_name::<T>();
let type_name = any::type_name::<T>();
Report::new(Self).attach_printable(format!("type: {type_name}"))
}

Expand Down
Loading

0 comments on commit 78e88cb

Please sign in to comment.