macrofied-toolbox 0.4.2

This library provides an ergonomic experience of adding debugging messages to rust's Result<T,E> and Option<T> patterns
Documentation
#[cfg(feature = "trace")]
use std::fmt::{self, Display, Formatter};

use proc_macro2::TokenStream;
#[cfg(feature = "trace")]
use quote::ToTokens;
use syn::{Expr, Lit};

pub struct Message {
    pub args: Option<Vec<Expr>>,
    pub captured: Option<Capture>,
    pub fmt: Lit,
}

#[cfg(feature = "trace")]
impl Display for Message {
    fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
        let args = if let Some(args) = &self.args {
            format!(
                "{:?}",
                args.iter().map(|v| format!("{}", v.to_token_stream())).collect::<Vec<String>>()
            )
        } else {
            "None".to_string()
        };
        let captured = if let Some(captured) = &self.captured {
            format!("{}", captured)
        } else {
            "None".to_string()
        };

        write!(
            fmt, "{{ args: {}, captured: {}, fmt: {} }}",
            args, captured, self.fmt.to_token_stream()
        )
    }
}

impl Message {
    pub fn build_message(&self) -> TokenStream {
        let mut tokens = TokenStream::new();

        let fmt = &self.fmt;

        tokens.extend(quote! { #fmt });

        if let Some(args) = &self.args {
            for arg in args {
                tokens.extend(quote! { , #arg });
            }
        }

        tokens
    }
}

#[derive(Clone)]
pub struct Capture {
    pub identifier: String,
    pub mutable: bool,
    pub reference: bool,
}

impl<T: Into<String>> From<T> for Capture {
    fn from(identifier: T) -> Self {
        Self {
            identifier: identifier.into(),
            mutable: false,
            reference: false
        }
    }
}

#[cfg(feature = "trace")]
impl Display for Capture {
    fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
        write!(
            fmt, "{{ identifier: {:?}, mutable: {}, reference: {} }}",
            self.identifier, self.mutable, self.reference
        )
    }
}

pub struct OnExpr {
    pub captured: Option<Capture>,
    pub expr: Expr,
}

#[cfg(feature = "trace")]
impl Display for OnExpr {
    fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
        let captured = if let Some(captured) = &self.captured {
            format!("{}", captured)
        } else {
            "None".to_string()
        };

        write!(
            fmt, "{{ captured: {}, expr: \"{}\" }}", captured, self.expr.to_token_stream()
        )
    }
}

pub struct OnFail {
    pub expr: Option<OnExpr>,
    pub message: Option<Message>,
}

#[cfg(feature = "trace")]
impl Display for OnFail {
    fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
        let expr = if let Some(expr) = &self.expr {
            format!("{}", expr)
        } else {
            "None".to_string()
        };
        let message = if let Some(message) = &self.message {
            format!("{}", message)
        } else {
            "None".to_string()
        };

        write!(fmt, "{{ expr: {}, message: {} }}", expr, message)
    }
}

pub enum OnSuccess {
    Expr(OnExpr),
    Message(Message),
}

#[cfg(feature = "trace")]
impl Display for OnSuccess {
    fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
        match self {
            Self::Expr(expr) =>
                write!(fmt, "{}", expr),
            Self::Message(message) =>
                write!(fmt, "{}", message)
        }
    }
}

pub struct WhenExpr {
    pub expr: Expr,
    pub tried: bool,
    pub ok_when: bool
}

#[cfg(feature = "trace")]
impl Display for WhenExpr {
    fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
        write!(
            fmt, "{{ expr: \"{}\", ok_when: {}, tried: {} }}",
            self.expr.to_token_stream(), self.ok_when, self.tried
        )
    }
}