Skip to content

Commit

Permalink
feat: Add rest of log levels
Browse files Browse the repository at this point in the history
  • Loading branch information
mcmah309 committed Dec 28, 2024
1 parent 70bf582 commit bb158a0
Show file tree
Hide file tree
Showing 3 changed files with 679 additions and 18 deletions.
204 changes: 203 additions & 1 deletion err_trail/src/defmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use defmt::Format;

mod sealed {
/// A sealed trait to prevent external implementations.
pub trait Sealed {}
}

Expand All @@ -13,18 +14,39 @@ pub trait ErrContextDefmt<T, E>: sealed::Sealed {
fn error_context(self, context: impl Format) -> Result<T, E>;
/// If [Err], log context as "warn".
fn warn_context(self, context: impl Format) -> Result<T, E>;
/// If [Err], log context as "info".
fn info_context(self, context: impl Format) -> Result<T, E>;
/// If [Err], log context as "debug".
fn debug_context(self, context: impl Format) -> Result<T, E>;
/// If [Err], log context as "trace".
fn trace_context(self, context: impl Format) -> Result<T, E>;

/// If [Err], lazily log result of [f] as "error".
fn with_error_context<F: FnOnce(&E) -> D, D: Format>(self, f: F) -> Result<T, E>;
/// If [Err], lazily log result of [f] as "warn".
fn with_warn_context<F: FnOnce(&E) -> D, D: Format>(self, f: F) -> Result<T, E>;
/// If [Err], lazily log result of [f] as "info".
fn with_info_context<F: FnOnce(&E) -> D, D: Format>(self, f: F) -> Result<T, E>;
/// If [Err], lazily log result of [f] as "debug".
fn with_debug_context<F: FnOnce(&E) -> D, D: Format>(self, f: F) -> Result<T, E>;
/// If [Err], lazily log result of [f] as "trace".
fn with_trace_context<F: FnOnce(&E) -> D, D: Format>(self, f: F) -> Result<T, E>;

/// Consumes the [Err] of a Result. If [Err], lazily logging the result of [f] as an "error".
/// Represents a bad state in which the current process cannot continue.
fn consume_with_error<F: FnOnce(&E) -> D, D: Format>(self, f: F) -> Option<T>;
/// Consumes the [Err] of a Result. If [Err], lazily logging the result of [f] as an "warn".
/// Represents a bad state in which the current process can continue.
fn consume_with_warn<F: FnOnce(&E) -> D, D: Format>(self, f: F) -> Option<T>;
/// Consumes the [Err] of a Result. If [Err], lazily logging the result of [f] as an "info".
/// Represents an information message.
fn consume_with_info<F: FnOnce(&E) -> D, D: Format>(self, f: F) -> Option<T>;
/// Consumes the [Err] of a Result. If [Err], lazily logging the result of [f] as a "debug".
/// Represents a debug message.
fn consume_with_debug<F: FnOnce(&E) -> D, D: Format>(self, f: F) -> Option<T>;
/// Consumes the [Err] of a Result. If [Err], lazily logging the result of [f] as a "trace".
/// Represents a trace message.
fn consume_with_trace<F: FnOnce(&E) -> D, D: Format>(self, f: F) -> Option<T>;
}

/// For consuming a [Result]'s [Err] in [Format] when [Err] is encountered.
Expand All @@ -34,6 +56,12 @@ pub trait ErrContextDisplayDefmt<T, E: Format>: sealed::Sealed {
fn consume_as_error(self) -> Option<T>;
/// Consume [Err] of a [Result]. Log as "warn".
fn consume_as_warn(self) -> Option<T>;
/// Consume [Err] of a [Result]. Log as "info".
fn consume_as_info(self) -> Option<T>;
/// Consume [Err] of a [Result]. Log as "debug".
fn consume_as_debug(self) -> Option<T>;
/// Consume [Err] of a [Result]. Log as "trace".
fn consume_as_trace(self) -> Option<T>;
}

/// For logging an [Option] when [None] is encountered.
Expand All @@ -43,11 +71,23 @@ pub trait NoneContextDefmt<T>: sealed::Sealed {
fn error_context(self, context: impl Format) -> Option<T>;
/// If [None], log context as "warn".
fn warn_context(self, context: impl Format) -> Option<T>;
/// If [None], log context as "info".
fn info_context(self, context: impl Format) -> Option<T>;
/// If [None], log context as "debug".
fn debug_context(self, context: impl Format) -> Option<T>;
/// If [None], log context as "trace".
fn trace_context(self, context: impl Format) -> Option<T>;

/// If [None], lazily log result of [f] as "error".
fn with_error_context<F: FnOnce() -> D, D: Format>(self, f: F) -> Option<T>;
/// If [None], lazily log result of [f] as "warn".
fn with_warn_context<F: FnOnce() -> D, D: Format>(self, f: F) -> Option<T>;
/// If [None], lazily log result of [f] as "info".
fn with_info_context<F: FnOnce() -> D, D: Format>(self, f: F) -> Option<T>;
/// If [None], lazily log result of [f] as "debug".
fn with_debug_context<F: FnOnce() -> D, D: Format>(self, f: F) -> Option<T>;
/// If [None], lazily log result of [f] as "trace".
fn with_trace_context<F: FnOnce() -> D, D: Format>(self, f: F) -> Option<T>;
}

//************************************************************************//
Expand All @@ -70,6 +110,30 @@ impl<T, E> ErrContextDefmt<T, E> for Result<T, E> {
self
}

#[inline]
fn info_context(self, context: impl Format) -> Result<T, E> {
if self.is_err() {
defmt::info!("{}", context);
}
self
}

#[inline]
fn debug_context(self, context: impl Format) -> Result<T, E> {
if self.is_err() {
defmt::debug!("{}", context);
}
self
}

#[inline]
fn trace_context(self, context: impl Format) -> Result<T, E> {
if self.is_err() {
defmt::trace!("{}", context);
}
self
}

#[inline]
fn with_error_context<F: FnOnce(&E) -> D, D: Format>(self, f: F) -> Result<T, E> {
if let Err(err) = &self {
Expand All @@ -86,6 +150,30 @@ impl<T, E> ErrContextDefmt<T, E> for Result<T, E> {
self
}

#[inline]
fn with_info_context<F: FnOnce(&E) -> D, D: Format>(self, f: F) -> Result<T, E> {
if let Err(err) = &self {
defmt::info!("{}", f(err));
}
self
}

#[inline]
fn with_debug_context<F: FnOnce(&E) -> D, D: Format>(self, f: F) -> Result<T, E> {
if let Err(err) = &self {
defmt::debug!("{}", f(err));
}
self
}

#[inline]
fn with_trace_context<F: FnOnce(&E) -> D, D: Format>(self, f: F) -> Result<T, E> {
if let Err(err) = &self {
defmt::trace!("{}", f(err));
}
self
}

#[inline]
fn consume_with_error<F: FnOnce(&E) -> D, D: Format>(self, f: F) -> Option<T> {
match self {
Expand All @@ -107,6 +195,39 @@ impl<T, E> ErrContextDefmt<T, E> for Result<T, E> {
}
}
}

#[inline]
fn consume_with_info<F: FnOnce(&E) -> D, D: Format>(self, f: F) -> Option<T> {
match self {
Ok(value) => Some(value),
Err(err) => {
defmt::info!("{}", f(&err));
None
}
}
}

#[inline]
fn consume_with_debug<F: FnOnce(&E) -> D, D: Format>(self, f: F) -> Option<T> {
match self {
Ok(value) => Some(value),
Err(err) => {
defmt::debug!("{}", f(&err));
None
}
}
}

#[inline]
fn consume_with_trace<F: FnOnce(&E) -> D, D: Format>(self, f: F) -> Option<T> {
match self {
Ok(value) => Some(value),
Err(err) => {
defmt::trace!("{}", f(&err));
None
}
}
}
}

impl<T, E: Format> ErrContextDisplayDefmt<T, E> for Result<T, E> {
Expand All @@ -131,6 +252,39 @@ impl<T, E: Format> ErrContextDisplayDefmt<T, E> for Result<T, E> {
}
}
}

#[inline]
fn consume_as_info(self) -> Option<T> {
match self {
Ok(ok) => Some(ok),
Err(err) => {
defmt::info!("{}", err);
None
}
}
}

#[inline]
fn consume_as_debug(self) -> Option<T> {
match self {
Ok(ok) => Some(ok),
Err(err) => {
defmt::debug!("{}", err);
None
}
}
}

#[inline]
fn consume_as_trace(self) -> Option<T> {
match self {
Ok(ok) => Some(ok),
Err(err) => {
defmt::trace!("{}", err);
None
}
}
}
}

//************************************************************************//
Expand All @@ -153,6 +307,30 @@ impl<T> NoneContextDefmt<T> for Option<T> {
self
}

#[inline]
fn info_context(self, context: impl Format) -> Option<T> {
if self.is_none() {
defmt::info!("{}", context);
}
self
}

#[inline]
fn debug_context(self, context: impl Format) -> Option<T> {
if self.is_none() {
defmt::debug!("{}", context);
}
self
}

#[inline]
fn trace_context(self, context: impl Format) -> Option<T> {
if self.is_none() {
defmt::trace!("{}", context);
}
self
}

#[inline]
fn with_error_context<F: FnOnce() -> D, D: Format>(self, f: F) -> Option<T> {
if self.is_none() {
Expand All @@ -168,4 +346,28 @@ impl<T> NoneContextDefmt<T> for Option<T> {
}
self
}
}

#[inline]
fn with_info_context<F: FnOnce() -> D, D: Format>(self, f: F) -> Option<T> {
if self.is_none() {
defmt::info!("{}", f());
}
self
}

#[inline]
fn with_debug_context<F: FnOnce() -> D, D: Format>(self, f: F) -> Option<T> {
if self.is_none() {
defmt::debug!("{}", f());
}
self
}

#[inline]
fn with_trace_context<F: FnOnce() -> D, D: Format>(self, f: F) -> Option<T> {
if self.is_none() {
defmt::trace!("{}", f());
}
self
}
}
Loading

0 comments on commit bb158a0

Please sign in to comment.