Macro custom_print::define_macros [−][src]
macro_rules! define_macros { ( { $( $template:ident $(as $name:ident)? ),* $(,)? }, $($args:tt)* ) => { ... }; }
Expand description
Defines multiple print
-like and dbg
-like macros.
The first argument braced in curly braces and contains
comma-seperated macro template names and optionally their custom macro names.
See the define_macro
declaration for the list of available templates.
The rest tokens specified in $($args)*
are used as input for define_writer
macro.
Depending on the specified templates, the macro uses
define_print
, define_println
, define_dbg
, define_flush
,
define_try_print
, define_try_println
, define_try_dbg
or define_try_flush
for each generated macro.
If you need to define a single print
-like or dbg
-like macro, use define_macro
.
Macro ambiguity
When using std-prelude, std macros cannot be replaced in textual scope using this macro.
This is a consequence of the ambiguous precedence between
a macro-expanded macro and a macro from the outer scope.
Use alternative names like cprint
, ceprint
, cprintln
, ceprintln
, cdbg
,
and then override std macros using proxy macro or use declaration.
Overriding with a proxy macro is a better way because it overrides macros in textual scope and accordingly in all submodules:
custom_print::define_macros!({ cprint, cprintln }, once: crate::write); macro_rules! print { ($($args:tt)*) => { cprint!($($args)*); } } macro_rules! println { ($($args:tt)*) => { cprintln!($($args)*); } } mod submodule { /* println is already defined in all submodules */ }
Alternatively, use can rebind macro from the textual scope to the path-based scope, but then it will be necessary not to forget to import macro into submodules scope:
custom_print::define_macros!({ cprint, cprintln }, once: crate::write); use cprint as print; use cprintln as println; mod submodule { use crate::{print, println}; /* ... */ }
Examples
An example with a simple string writer:
use core::fmt::Write; let mut string = String::new(); custom_print::define_macros!({ cprint, cprintln }, &mut string); assert_eq!(cprintln!("first"), ()); assert_eq!(string, "first\n"); assert_eq!(cprint!("second"), ()); assert_eq!(string, "first\nsecond");
An example with an extern functions that takes a UTF-8 chars pointer and byte length
and works in no_std
context:
#![no_std] extern crate std; custom_print::define_macros!({ print, println }, concat, extern "C" fn console_log(_: *const u8, _: usize)); custom_print::define_macros!({ eprint, eprintln, dbg }, concat, extern "C" fn console_warn(_: *const u8, _: usize)); fn main() { println!("println"); print!("print"); eprintln!("eprintln"); eprint!("eprint"); dbg!("dbg"); }
An example with a closure that takes an str
reference in no_std
and no_alloc
:
#![no_std] custom_print::define_macros!({ print, println }, fmt, |_value: &str| { /* ... */ }); fn main() { println!("println"); print!("print"); }
An example with a function that takes a c_char
pointer and overriding
std::print
and std::println
functions:
fn write(_value: *const std::os::raw::c_char) { /* ... */ } custom_print::define_macros!({ cprint, cprintln }, concat, crate::write); macro_rules! print { ($($args:tt)*) => { cprint!($($args)*); } } macro_rules! println { ($($args:tt)*) => { cprintln!($($args)*); } } fn main() { println!("println"); print!("print"); }
An example with LineWriter
and flushing.
use std::io::{self, LineWriter, Write}; use std::sync::Mutex; let written: Mutex<Vec<u8>> = Mutex::default(); #[derive(Clone, Debug)] struct CustomWriter<'a>(&'a Mutex<Vec<u8>>); impl Write for CustomWriter<'_> { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { let mut written = self.0.lock().unwrap(); written.extend_from_slice(buf); Ok(buf.len()) } fn flush(&mut self) -> io::Result<()> { Ok(()) } } let custom_writer = CustomWriter(&written); let mut line_writer = LineWriter::new(custom_writer); custom_print::define_macros!({cprint, flush}, line_writer); assert_eq!(cprint!("first,"), ()); assert_eq!(*written.lock().unwrap(), b""); assert_eq!(cprint!("second\nthird,"), ()); assert_eq!(*written.lock().unwrap(), b"first,second\n"); assert_eq!(flush!(), ()); assert_eq!(*written.lock().unwrap(), b"first,second\nthird,");