use core::fmt::Debug;
use crate::{env::internal::EnvBase, Env, Val};
#[macro_export]
macro_rules! log {
($env:expr, $fmt:literal $(,)?) => {
if cfg!(debug_assertions) {
$env.logs().add($fmt, &[]);
}
};
($env:expr, $fmt:literal, $($args:expr),* $(,)?) => {
if cfg!(debug_assertions) {
$env.logs().add($fmt, &[
$(
<_ as $crate::IntoVal<Env, $crate::Val>>::into_val(&$args, $env)
),*
]);
}
};
}
#[derive(Clone)]
pub struct Logs(Env);
impl Debug for Logs {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "Logs")
}
}
impl Logs {
#[inline(always)]
pub(crate) fn env(&self) -> &Env {
&self.0
}
#[inline(always)]
pub(crate) fn new(env: &Env) -> Logs {
Logs(env.clone())
}
#[deprecated(note = "use [Logs::add]")]
#[inline(always)]
pub fn log(&self, msg: &'static str, args: &[Val]) {
self.add(msg, args);
}
#[inline(always)]
pub fn add(&self, msg: &'static str, args: &[Val]) {
if cfg!(debug_assertions) {
let env = self.env();
env.log_from_slice(msg, args).unwrap();
#[cfg(any(test, feature = "testutils"))]
{
use crate::testutils::Logs;
std::println!("{}", self.all().last().unwrap());
}
}
}
}
#[cfg(any(test, feature = "testutils"))]
use crate::testutils;
#[cfg(any(test, feature = "testutils"))]
#[cfg_attr(feature = "docs", doc(cfg(feature = "testutils")))]
impl testutils::Logs for Logs {
fn all(&self) -> std::vec::Vec<String> {
use crate::xdr::{
ContractEventBody, ContractEventType, ScSymbol, ScVal, ScVec, StringM, VecM,
};
let env = self.env();
let log_sym = ScSymbol(StringM::try_from("log").unwrap());
let log_topics = ScVec(VecM::try_from(vec![ScVal::Symbol(log_sym)]).unwrap());
env.host()
.get_diagnostic_events()
.unwrap()
.0
.into_iter()
.filter_map(|e| match (&e.event.type_, &e.event.body) {
(ContractEventType::Diagnostic, ContractEventBody::V0(ce))
if &ce.topics == &log_topics.0 =>
{
Some(format!("{}", &e))
}
_ => None,
})
.collect::<std::vec::Vec<_>>()
}
fn print(&self) {
std::println!("{}", self.all().join("\n"))
}
}