#![allow(unsafe_code)]
#[macro_export]
macro_rules! msg {
($msg:literal) => {{
const _: () = $crate::assert_literal_has_no_format_placeholder($msg);
$crate::rlo_log($msg)
}};
($msg:expr) => {
$crate::rlo_log($msg)
};
($($arg:tt)*) => ($crate::rlo_log(&format!($($arg)*)));
}
pub const fn assert_literal_has_no_format_placeholder(message: &str) {
let bytes = message.as_bytes();
let mut index = 0;
while index < bytes.len() {
if bytes[index] == b'{' || bytes[index] == b'}' {
panic!(
"this `msg!` literal contains `{{` or `}}`, but the single-literal form is \
allocation-free and does not run `format!`, so the braces would be logged \
verbatim. Pass the values as arguments instead: `msg!(\"fee={{}}\", fee)`. \
For a literal brace, use the argument form as well."
);
}
index += 1;
}
}
#[cfg(target_os = "solana")]
pub mod syscalls;
#[inline]
pub fn rlo_log(message: &str) {
#[cfg(target_os = "solana")]
unsafe {
syscalls::rlo_log_(message.as_ptr(), message.len() as u64);
}
#[cfg(not(target_os = "solana"))]
println!("{message}");
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn guard_accepts_literals_without_format_placeholders() {
const _: () = assert_literal_has_no_format_placeholder("");
const _: () = assert_literal_has_no_format_placeholder("verifying multisig");
const _: () = assert_literal_has_no_format_placeholder("reconnecting \u{2014} retrying");
const _: () = assert_literal_has_no_format_placeholder("percent % and backslash \\ pass");
}
#[test]
fn fast_path_and_formatting_path_both_log() {
let err = "not enough signers";
let owned = String::from("owned");
msg!("verifying multisig");
msg!("multisig failed: {}", err);
msg!(&owned);
msg!("reconnecting \u{2014} retrying");
}
}