use std::{borrow::Cow, fmt::Debug};
use crate::status_tracker::StatusTracker;
#[macro_export]
#[doc(hidden)]
macro_rules! log_item {
($label:expr, $description:expr, $function:expr) => {{
$crate::status_tracker::LogItem {
kind: $crate::status_tracker::LogKind::Informational,
label: $label.into(),
crate_name: env!("CARGO_PKG_NAME").into(),
crate_version: env!("CARGO_PKG_VERSION").into(),
file: file!().into(),
function: $function.into(),
line: line!(),
description: $description.into(),
..Default::default()
}
}};
}
#[doc(hidden)]
#[macro_export]
macro_rules! log_current_item {
($description:expr, $function:expr) => {{
$crate::status_tracker::LogItem {
kind: $crate::status_tracker::LogKind::Informational,
label: "".to_owned().into(), crate_name: env!("CARGO_PKG_NAME").into(),
crate_version: env!("CARGO_PKG_VERSION").into(),
file: file!().into(),
function: $function.into(),
line: line!(),
description: $description.into(),
..Default::default()
}
}};
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct LogItem {
pub kind: LogKind,
pub label: Cow<'static, str>,
pub description: Cow<'static, str>,
pub crate_name: Cow<'static, str>,
pub crate_version: Cow<'static, str>,
pub file: Cow<'static, str>,
pub function: Cow<'static, str>,
pub line: u32,
pub err_val: Option<Cow<'static, str>>,
pub validation_status: Option<Cow<'static, str>>,
pub ingredient_uri: Option<Cow<'static, str>>,
}
impl Default for LogItem {
fn default() -> Self {
LogItem {
kind: LogKind::Success,
label: Cow::Borrowed(""),
description: Cow::Borrowed(""),
crate_name: env!("CARGO_PKG_NAME").into(),
crate_version: env!("CARGO_PKG_VERSION").into(),
file: Cow::Borrowed(""),
function: Cow::Borrowed(""),
line: 0,
err_val: None,
validation_status: None,
ingredient_uri: None,
}
}
}
impl LogItem {
#[must_use]
pub fn validation_status(self, status: &'static str) -> Self {
LogItem {
validation_status: Some(status.into()),
..self
}
}
pub fn set_ingredient_uri<S: Into<String>>(self, uri: S) -> Self {
LogItem {
ingredient_uri: Some(uri.into().into()),
..self
}
}
pub fn success(mut self, tracker: &mut StatusTracker) {
self.kind = LogKind::Success;
tracker.add_non_error(self);
}
pub fn informational(mut self, tracker: &mut StatusTracker) {
self.kind = LogKind::Informational;
tracker.add_non_error(self);
}
pub fn failure<E: Debug>(mut self, tracker: &mut StatusTracker, err: E) -> Result<E, E> {
self.kind = LogKind::Failure;
self.err_val = Some(format!("{err:?}").into());
tracker.add_error(self, err)
}
pub fn failure_no_throw<E: Debug>(mut self, tracker: &mut StatusTracker, err: E) {
self.kind = LogKind::Failure;
self.err_val = Some(format!("{err:?}").into());
tracker.add_non_error(self);
}
pub fn failure_as_err<E: Debug>(mut self, tracker: &mut StatusTracker, err: E) -> E {
self.kind = LogKind::Failure;
self.err_val = Some(format!("{err:?}").into());
match tracker.add_error(self, err) {
Ok(e) => e,
Err(e) => e,
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum LogKind {
Success,
Informational,
Failure,
}
#[cfg(test)]
mod tests {
#![allow(clippy::expect_used)]
#![allow(clippy::unwrap_used)]
use std::borrow::Cow;
use crate::status_tracker::{LogItem, LogKind, StatusTracker};
#[test]
fn r#macro() {
let log = log_item!("test1", "test item 1", "test func");
assert_eq!(
log,
LogItem {
kind: LogKind::Informational,
label: Cow::Borrowed("test1"),
description: Cow::Borrowed("test item 1"),
crate_name: env!("CARGO_PKG_NAME").into(),
crate_version: env!("CARGO_PKG_VERSION").into(),
file: Cow::Borrowed(file!()),
function: Cow::Borrowed("test func"),
line: log.line,
err_val: None,
validation_status: None,
..Default::default()
}
);
assert!(log.line > 2);
}
#[test]
fn macro_from_string() {
let desc = "test item 1".to_string();
let log = log_item!("test1", desc, "test func");
assert_eq!(
log,
LogItem {
kind: crate::status_tracker::LogKind::Informational,
label: Cow::Borrowed("test1"),
description: Cow::Owned("test item 1".to_string()),
crate_name: env!("CARGO_PKG_NAME").into(),
crate_version: env!("CARGO_PKG_VERSION").into(),
file: Cow::Borrowed(file!()),
function: Cow::Borrowed("test func"),
line: log.line,
err_val: None,
validation_status: None,
..Default::default()
}
);
assert!(log.line > 2);
}
#[test]
fn success() {
let mut tracker = StatusTracker::default();
log_item!("test1", "test item 1", "test func").success(&mut tracker);
let log_item = tracker.logged_items().first().unwrap();
assert_eq!(
log_item,
&LogItem {
kind: LogKind::Success,
label: Cow::Borrowed("test1"),
description: Cow::Borrowed("test item 1"),
crate_name: env!("CARGO_PKG_NAME").into(),
crate_version: env!("CARGO_PKG_VERSION").into(),
file: Cow::Borrowed(file!()),
function: Cow::Borrowed("test func"),
line: log_item.line,
err_val: None,
validation_status: None,
ingredient_uri: None,
}
);
}
#[test]
fn informational() {
let mut tracker = StatusTracker::default();
log_item!("test1", "test item 1", "test func").informational(&mut tracker);
let log_item = tracker.logged_items().first().unwrap();
assert_eq!(
log_item,
&LogItem {
kind: LogKind::Informational,
label: Cow::Borrowed("test1"),
description: Cow::Borrowed("test item 1"),
crate_name: env!("CARGO_PKG_NAME").into(),
crate_version: env!("CARGO_PKG_VERSION").into(),
file: Cow::Borrowed(file!()),
function: Cow::Borrowed("test func"),
line: log_item.line,
err_val: None,
validation_status: None,
..Default::default()
}
);
}
#[test]
fn failure() {
let mut tracker = StatusTracker::default();
log_item!("test1", "test item 1", "test func")
.failure(&mut tracker, "sample error message")
.unwrap();
let log_item = tracker.logged_items().first().unwrap();
assert_eq!(
log_item,
&LogItem {
kind: LogKind::Failure,
label: Cow::Borrowed("test1"),
description: Cow::Borrowed("test item 1"),
crate_name: env!("CARGO_PKG_NAME").into(),
crate_version: env!("CARGO_PKG_VERSION").into(),
file: Cow::Borrowed(file!()),
function: Cow::Borrowed("test func"),
line: log_item.line,
err_val: Some(Cow::Borrowed("\"sample error message\"")),
validation_status: None,
..Default::default()
}
);
}
#[test]
fn failure_no_throw() {
let mut tracker = StatusTracker::default();
log_item!("test1", "test item 1", "test func")
.failure_no_throw(&mut tracker, "sample error message");
let log_item = tracker.logged_items().first().unwrap();
assert_eq!(
log_item,
&LogItem {
kind: LogKind::Failure,
label: Cow::Borrowed("test1"),
description: Cow::Borrowed("test item 1"),
crate_name: env!("CARGO_PKG_NAME").into(),
crate_version: env!("CARGO_PKG_VERSION").into(),
file: Cow::Borrowed(file!()),
function: Cow::Borrowed("test func"),
line: log_item.line,
err_val: Some(Cow::Borrowed("\"sample error message\"")),
..Default::default()
}
);
}
#[test]
fn validation_status() {
let log_item =
log_item!("test1", "test item 1", "test func").validation_status("claim.missing");
assert_eq!(
log_item,
LogItem {
kind: LogKind::Informational,
label: Cow::Borrowed("test1"),
description: Cow::Borrowed("test item 1"),
crate_name: env!("CARGO_PKG_NAME").into(),
crate_version: env!("CARGO_PKG_VERSION").into(),
file: Cow::Borrowed(file!()),
function: Cow::Borrowed("test func"),
line: log_item.line,
err_val: None,
validation_status: Some(Cow::Borrowed("claim.missing")),
..Default::default()
}
);
}
#[test]
fn impl_clone() {
let li1 = log_item!("test1", "test item 1", "test func");
let li2 = li1.clone();
assert_eq!(li1, li2);
}
}