diff --git a/src/attachment.rs b/src/attachment.rs
index b1fdb77..cdb48a8 100644
--- a/src/attachment.rs
+++ b/src/attachment.rs
@@ -1,4 +1,4 @@
-use std::time::Duration;
+use std::{any, fmt, time::Duration};
use tracing::error;
@@ -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 Display for A where A: std::fmt::Display + std::fmt::Debug + Send + Sync + 'static {}
+impl 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 Debug for A where A: std::fmt::Debug + Send + Sync + 'static {}
+impl 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(pub A);
+
+impl fmt::Display for Dbg {
+ 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(pub K, pub V);
-impl KeyValue {
- pub fn dbg(key: impl Debug, value: impl Debug) -> Self {
- Self(format!("{key:?}"), format!("{value:?}"))
+impl fmt::Display for KeyValue {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{}: {}", self.0, self.1)
+ }
+}
+
+impl KeyValue> {
+ pub fn dbg(key: K, value: V) -> Self {
+ Self(key, Dbg(value))
}
}
@@ -48,8 +63,8 @@ pub struct Field {
status: S,
}
-impl std::fmt::Display for Field {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+impl fmt::Display for Field {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}: {}", self.id, self.status)
}
}
@@ -67,22 +82,22 @@ pub struct Type(&'static str);
impl Type {
// const fn when type_name is const fn in stable
pub fn of() -> Self {
- Self(std::any::type_name::())
+ Self(any::type_name::())
}
pub fn of_val(_val: &T) -> Self {
- Self(std::any::type_name::())
+ Self(any::type_name::())
}
}
-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()
}
}
@@ -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}", // ├
@@ -144,36 +159,37 @@ impl std::fmt::Display for Symbol {
Self::CurveRight => "\u{2570}", // ╰
Self::Space => " ",
};
- write!(f, "{}", utf8)
+ write!(f, "{utf8}")
}
}
-impl std::fmt::Display for Expectation {
- 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 fmt::Display for Expectation {
+ 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 std::fmt::Display for FromTo {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- let cr = Symbol::CurveRight;
- let hl = Symbol::HorizontalLeft;
+impl fmt::Display for FromTo {
+ 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))
}
}
@@ -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(pub I);
+#[error("idx [{0}: {}]", std::any::type_name::())]
+pub struct Index(pub I);
#[cfg(test)]
mod test {
diff --git a/src/context.rs b/src/context.rs
index 76d06e5..e466494 100644
--- a/src/context.rs
+++ b/src/context.rs
@@ -1,4 +1,4 @@
-use std::{path::Path, time::Duration};
+use std::{any, path::Path, time::Duration};
use error_stack::Context;
@@ -163,7 +163,7 @@ impl InvalidInput {
#[track_caller]
pub fn type_name() -> Report {
- let type_name = std::any::type_name::();
+ let type_name = any::type_name::();
Report::new(Self).attach_printable(format!("type: {type_name}"))
}
diff --git a/src/lib.rs b/src/lib.rs
index 4054687..78dfe30 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -12,7 +12,7 @@ pub mod grpc;
pub use attachment::{Expectation, Field, Index, KeyValue, Type};
-use attachment::{Debug, Display};
+use attachment::{Dbg, Debug, Display};
pub use context::*;
// TODO we'll have to do a builder pattern here at
@@ -35,27 +35,47 @@ pub trait Reportable
where
Self: Sized + Context,
{
- fn report(ctx: C) -> Report;
+ fn value() -> Self;
+ fn report(ctx: C) -> Report {
+ Report::new(ctx).change_context(Self::value())
+ }
// TODO
// fn report_dyn_err(err: impl std::error::Error + 'static + Send + Sync)
// -> Report;
+ #[track_caller]
fn attach(value: A) -> Report
where
- A: Display;
+ A: Display,
+ {
+ Report::new(Self::value()).attach_printable(value)
+ }
+ #[track_caller]
fn attach_dbg(value: A) -> Report
where
- A: Debug;
+ A: Debug,
+ {
+ Self::attach(Dbg(value))
+ }
+ #[track_caller]
fn with_kv(key: K, value: V) -> Report
where
K: Display,
- V: Display;
+ V: Display,
+ {
+ Self::attach(KeyValue(key, value))
+ }
+ #[track_caller]
fn with_kv_dbg(key: K, value: V) -> Report
where
- K: Debug,
- V: Debug;
- fn with_field_status(key: &'static str, status: S) -> Report;
-
- fn value() -> Self;
+ K: Display,
+ V: Debug,
+ {
+ Self::attach(KeyValue::dbg(key, value))
+ }
+ #[track_caller]
+ fn with_field_status(key: &'static str, status: S) -> Report {
+ Self::attach(Field::new(key, status))
+ }
#[track_caller]
fn expected_actual(expected: A, actual: A) -> Report {
@@ -102,22 +122,6 @@ impl ReportAs for Result {
}
}
-impl ReportAs for &'static str {
- #[inline]
- #[track_caller]
- fn report_as(self) -> Result> {
- Err(Report::new(C::value()).attach_printable(self))
- }
-}
-
-impl ReportAs for String {
- #[inline]
- #[track_caller]
- fn report_as(self) -> Result> {
- Err(Report::new(C::value()).attach_printable(self))
- }
-}
-
pub trait IntoContext {
fn into_ctx(self) -> Report;
}
@@ -191,49 +195,6 @@ macro_rules! reportable {
$crate::Report::new(ctx).change_context(Self)
}
- #[track_caller]
- fn attach(value: A) -> $crate::Report
- where
- A: $crate::attachment::Display,
- {
- $crate::Report::new(Self).attach_printable(value)
- }
-
- #[track_caller]
- fn attach_dbg(value: A) -> $crate::Report
- where
- A: $crate::attachment::Debug,
- {
- $crate::Report::new(Self).attach_printable(format!("{value:?}"))
- }
-
- #[track_caller]
- fn with_kv(key: K, value: V) -> $crate::Report
- where
- K: $crate::attachment::Display,
- V: $crate::attachment::Display,
- {
- use $crate::AttachExt;
- $crate::Report::new(Self).attach_kv(key, value)
- }
- #[track_caller]
- fn with_kv_dbg(key: K, value: V) -> $crate::Report
- where
- K: $crate::attachment::Debug,
- V: $crate::attachment::Debug,
- {
- use $crate::AttachExt;
- $crate::Report::new(Self).attach_kv_dbg(key, value)
- }
- #[track_caller]
- fn with_field_status(key: &'static str, status: S) -> $crate::Report
- where
- S: $crate::attachment::Display,
- {
- $crate::Report::new(Self)
- .attach_printable($crate::attachment::Field::new(key, status))
- }
-
fn value() -> Self {
$context
}
@@ -248,7 +209,7 @@ pub trait AttachExt {
V: Display;
fn attach_kv_dbg(self, key: K, value: V) -> Self
where
- K: Debug,
+ K: Display,
V: Debug;
fn attach_field_status(self, name: &'static str, status: S) -> Self
@@ -281,7 +242,7 @@ impl AttachExt for Report {
#[track_caller]
fn attach_kv_dbg(self, key: K, value: V) -> Self
where
- K: Debug,
+ K: Display,
V: Debug,
{
self.attach_printable(KeyValue::dbg(key, value))
@@ -302,7 +263,7 @@ impl AttachExt for Report {
where
A: Debug,
{
- self.attach_printable(format!("{value:?}"))
+ self.attach_printable(Dbg(value))
}
}
@@ -324,7 +285,7 @@ impl AttachExt for Result> {
#[track_caller]
fn attach_kv_dbg(self, key: K, value: V) -> Self
where
- K: Debug,
+ K: Display,
V: Debug,
{
match self {
@@ -353,82 +314,7 @@ impl AttachExt for Result> {
{
match self {
Ok(ok) => Ok(ok),
- Err(report) => Err(report.attach_printable(format!("{value:?}"))),
- }
- }
-}
-
-pub trait ResultAttachExt: ResultExt {
- fn attach_kv(self, key: K, value: V) -> Result>
- where
- K: Display,
- V: Display;
- fn attach_kv_dbg(self, key: K, value: V) -> Result>
- where
- K: Debug,
- V: Debug;
-
- fn attach_field_status(
- self,
- name: &'static str,
- status: S,
- ) -> Result>
- where
- S: Display;
- fn attach_dbg(self, value: A) -> Result>
- where
- A: Debug;
-}
-
-impl ResultAttachExt for Result
-where
- C: Context,
-{
- #[inline]
- #[track_caller]
- fn attach_kv(self, key: K, value: V) -> Result>
- where
- K: Display,
- V: Display,
- {
- match self {
- Ok(ok) => Ok(ok),
- Err(e) => Err(Report::from(e).attach_printable(KeyValue(key, value))),
- }
- }
- #[inline]
- #[track_caller]
- fn attach_kv_dbg(self, key: K, value: V) -> Result>
- where
- K: Debug,
- V: Debug,
- {
- match self {
- Ok(ok) => Ok(ok),
- Err(e) => Err(Report::from(e).attach_printable(KeyValue::dbg(key, value))),
- }
- }
-
- #[inline]
- #[track_caller]
- fn attach_field_status(self, name: &'static str, status: S) -> Result>
- where
- S: Display,
- {
- match self {
- Ok(ok) => Ok(ok),
- Err(e) => Err(Report::from(e).attach_printable(Field::new(name, status))),
- }
- }
- #[inline]
- #[track_caller]
- fn attach_dbg(self, value: A) -> Result>
- where
- A: Debug,
- {
- match self {
- Ok(ok) => Ok(ok),
- Err(e) => Err(Report::from(e).attach_printable(format!("{value:?}"))),
+ Err(report) => Err(report.attach_printable(Dbg(value))),
}
}
}
@@ -463,7 +349,7 @@ where
#[track_caller]
fn log_err(self) {
if let Err(e) = self {
- error!(err = ?e);
+ error!(message = ?e);
}
}
@@ -479,7 +365,7 @@ where
}
#[inline]
#[track_caller]
- fn and_log(self, level: Level) -> Result {
+ fn and_log(self, level: Level) -> Self {
if let Err(err) = &self {
match level {
Level::TRACE => trace!(?err),
@@ -494,16 +380,16 @@ where
#[inline]
#[track_caller]
- fn and_log_err(self) -> Result {
+ fn and_log_err(self) -> Self {
if let Err(e) = &self {
- error!(err = ?e);
+ error!(message = ?e);
}
self
}
#[inline]
#[track_caller]
- fn and_attached_err(self, attachment: A) -> Result
+ fn and_attached_err(self, attachment: A) -> Self
where
A: fmt::Debug + Send + Sync + 'static,
{
@@ -515,7 +401,7 @@ where
#[inline]
#[track_caller]
- fn on_err(self, op: impl FnOnce()) -> Result {
+ fn on_err(self, op: impl FnOnce()) -> Self {
op();
self
}
@@ -558,7 +444,7 @@ pub trait FromReport {
/// USAGE:
/// * `impl From $(as $context:path)*> for OurError::Report(OurReportError)`
/// - Implements `From where E: ToReport<_>` for errors that implement [`ToReport`]
-/// * impl From>> for OurError::Report(TransactionError)
+/// * `impl From>> for OurError::Report(TransactionError)`
/// - Implements `From>` for `Report`
/// * `impl From for OurError::Report(TransactionError)`
/// - Implements `From` for `Report`
@@ -747,26 +633,42 @@ where
}
impl ToReport for Report {
- fn to_report(self) -> Report {
+ fn to_report(self) -> Self {
self
}
}
/// Used to produce [`NotFound`] reports from an [`Option`]
-pub trait OptionReport {
- type Some;
- fn expect_or(self) -> Result>;
- fn expect_kv(self, key: K, value: V) -> Result>
+pub trait OptionReport
+where
+ Self: Sized,
+{
+ fn expect_or(self) -> Result>;
+ fn expect_kv(self, key: K, value: V) -> Result>
where
K: Display,
V: Display;
- fn expect_field(self, field: &'static str) -> Result>;
- fn expect_by(self, key: K) -> Result>;
-}
+ fn expect_field(self, field: &'static str) -> Result>;
-impl OptionReport for Option {
- type Some = T;
+ #[inline]
+ #[track_caller]
+ fn expect_kv_dbg(self, key: K, value: V) -> Result>
+ where
+ K: Display,
+ V: Debug,
+ {
+ self.expect_kv(key, Dbg(value))
+ }
+ #[inline]
+ #[track_caller]
+ fn expect_by(self, key: K) -> Result> {
+ self.expect_kv(Index(key), ty!(T))
+ }
+}
+
+impl OptionReport for Option {
+ #[inline]
#[track_caller]
fn expect_or(self) -> Result> {
// TODO #[track_caller] on closure
@@ -778,6 +680,7 @@ impl OptionReport for Option {
}
}
+ #[inline]
#[track_caller]
fn expect_kv(self, key: K, value: V) -> Result>
where
@@ -790,6 +693,7 @@ impl OptionReport for Option {
}
}
+ #[inline]
#[track_caller]
fn expect_field(self, field: &'static str) -> Result> {
match self {
@@ -797,14 +701,6 @@ impl OptionReport for Option {
None => Err(NotFound::with_field(field)),
}
}
-
- #[track_caller]
- fn expect_by(self, key: K) -> Result> {
- match self {
- Some(v) => Ok(v),
- None => Err(NotFound::with_kv(Index(key), attachment::Type::of::())),
- }
- }
}
#[macro_export]
@@ -1083,4 +979,11 @@ mod test {
}
assert_err!(compare(my_number, other_number));
}
+
+ #[test]
+ fn expect_by() {
+ let arr = ["a", "b"];
+ let get_oob = arr.get(2).expect_by(2);
+ assert_err!(get_oob);
+ }
}