diff options
Diffstat (limited to 'vendor/anstream/src/macros.rs')
-rw-r--r-- | vendor/anstream/src/macros.rs | 389 |
1 files changed, 389 insertions, 0 deletions
diff --git a/vendor/anstream/src/macros.rs b/vendor/anstream/src/macros.rs new file mode 100644 index 0000000..bd1accb --- /dev/null +++ b/vendor/anstream/src/macros.rs @@ -0,0 +1,389 @@ +/// Prints to [`stdout`][crate::stdout]. +/// +/// Equivalent to the [`println!`] macro except that a newline is not printed at +/// the end of the message. +/// +/// Note that stdout is frequently line-buffered by default so it may be +/// necessary to use [`std::io::Write::flush()`] to ensure the output is emitted +/// immediately. +/// +/// **NOTE:** The `print!` macro will lock the standard output on each call. If you call +/// `print!` within a hot loop, this behavior may be the bottleneck of the loop. +/// To avoid this, lock stdout with [`AutoStream::lock`][crate::AutoStream::lock]: +/// ``` +/// # #[cfg(feature = "auto")] { +/// use std::io::Write as _; +/// +/// let mut lock = anstream::stdout().lock(); +/// write!(lock, "hello world").unwrap(); +/// # } +/// ``` +/// +/// Use `print!` only for the primary output of your program. Use +/// [`eprint!`] instead to print error and progress messages. +/// +/// **NOTE:** Not all `print!` calls will be captured in tests like [`std::print!`] +/// - Capturing will automatically be activated in test binaries +/// - Otherwise, only when the `test` feature is enabled +/// +/// # Panics +/// +/// Panics if writing to `stdout` fails for any reason **except** broken pipe. +/// +/// Writing to non-blocking stdout can cause an error, which will lead +/// this macro to panic. +/// +/// # Examples +/// +/// ``` +/// # #[cfg(feature = "auto")] { +/// use std::io::Write as _; +/// use anstream::print; +/// use anstream::stdout; +/// +/// print!("this "); +/// print!("will "); +/// print!("be "); +/// print!("on "); +/// print!("the "); +/// print!("same "); +/// print!("line "); +/// +/// stdout().flush().unwrap(); +/// +/// print!("this string has a newline, why not choose println! instead?\n"); +/// +/// stdout().flush().unwrap(); +/// # } +/// ``` +#[cfg(feature = "auto")] +#[macro_export] +macro_rules! print { + ($($arg:tt)*) => {{ + if cfg!(any(feature = "test", test)) { + use std::io::Write as _; + + let stdio = std::io::stdout(); + let choice = $crate::AutoStream::choice(&stdio); + let buffer = Vec::new(); + let mut stream = $crate::AutoStream::new(buffer, choice); + // Ignore errors rather than panic + let _ = ::std::write!(&mut stream, $($arg)*); + let buffer = stream.into_inner(); + // Should be UTF-8 but not wanting to panic + let buffer = String::from_utf8_lossy(&buffer); + ::std::print!("{}", buffer) + } else { + use std::io::Write as _; + + let mut stream = $crate::stdout(); + match ::std::write!(&mut stream, $($arg)*) { + Err(e) if e.kind() != ::std::io::ErrorKind::BrokenPipe => { + ::std::panic!("failed printing to stdout: {e}"); + } + Err(_) | Ok(_) => {} + } + } + }}; +} + +/// Prints to [`stdout`][crate::stdout], with a newline. +/// +/// On all platforms, the newline is the LINE FEED character (`\n`/`U+000A`) alone +/// (no additional CARRIAGE RETURN (`\r`/`U+000D`)). +/// +/// This macro uses the same syntax as [`format!`], but writes to the standard output instead. +/// See [`std::fmt`] for more information. +/// +/// **NOTE:** The `println!` macro will lock the standard output on each call. If you call +/// `println!` within a hot loop, this behavior may be the bottleneck of the loop. +/// To avoid this, lock stdout with [`AutoStream::lock`][crate::AutoStream::lock]: +/// ``` +/// # #[cfg(feature = "auto")] { +/// use std::io::Write as _; +/// +/// let mut lock = anstream::stdout().lock(); +/// writeln!(lock, "hello world").unwrap(); +/// # } +/// ``` +/// +/// Use `println!` only for the primary output of your program. Use +/// [`eprintln!`] instead to print error and progress messages. +/// +/// **NOTE:** Not all `println!` calls will be captured in tests like [`std::println!`] +/// - Capturing will automatically be activated in test binaries +/// - Otherwise, only when the `test` feature is enabled +/// +/// # Panics +/// +/// Panics if writing to `stdout` fails for any reason **except** broken pipe. +/// +/// Writing to non-blocking stdout can cause an error, which will lead +/// this macro to panic. +/// +/// # Examples +/// +/// ``` +/// # #[cfg(feature = "auto")] { +/// use anstream::println; +/// +/// println!(); // prints just a newline +/// println!("hello there!"); +/// println!("format {} arguments", "some"); +/// let local_variable = "some"; +/// println!("format {local_variable} arguments"); +/// # } +/// ``` +#[cfg(feature = "auto")] +#[macro_export] +macro_rules! println { + () => { + $crate::print!("\n") + }; + ($($arg:tt)*) => {{ + if cfg!(any(feature = "test", test)) { + use std::io::Write as _; + + let stdio = std::io::stdout(); + let choice = $crate::AutoStream::choice(&stdio); + let buffer = Vec::new(); + let mut stream = $crate::AutoStream::new(buffer, choice); + // Ignore errors rather than panic + let _ = ::std::write!(&mut stream, $($arg)*); + let buffer = stream.into_inner(); + // Should be UTF-8 but not wanting to panic + let buffer = String::from_utf8_lossy(&buffer); + ::std::println!("{}", buffer) + } else { + use std::io::Write as _; + + let mut stream = $crate::stdout(); + match ::std::writeln!(&mut stream, $($arg)*) { + Err(e) if e.kind() != ::std::io::ErrorKind::BrokenPipe => { + ::std::panic!("failed printing to stdout: {e}"); + } + Err(_) | Ok(_) => {} + } + } + }}; +} + +/// Prints to [`stderr`][crate::stderr]. +/// +/// Equivalent to the [`print!`] macro, except that output goes to +/// `stderr` instead of `stdout`. See [`print!`] for +/// example usage. +/// +/// Use `eprint!` only for error and progress messages. Use `print!` +/// instead for the primary output of your program. +/// +/// **NOTE:** Not all `eprint!` calls will be captured in tests like [`std::eprint!`] +/// - Capturing will automatically be activated in test binaries +/// - Otherwise, only when the `test` feature is enabled +/// +/// # Panics +/// +/// Panics if writing to `stderr` fails for any reason **except** broken pipe. +/// +/// Writing to non-blocking stdout can cause an error, which will lead +/// this macro to panic. +/// +/// # Examples +/// +/// ``` +/// # #[cfg(feature = "auto")] { +/// use anstream::eprint; +/// +/// eprint!("Error: Could not complete task"); +/// # } +/// ``` +#[cfg(feature = "auto")] +#[macro_export] +macro_rules! eprint { + ($($arg:tt)*) => {{ + if cfg!(any(feature = "test", test)) { + use std::io::Write as _; + + let stdio = std::io::stderr(); + let choice = $crate::AutoStream::choice(&stdio); + let buffer = Vec::new(); + let mut stream = $crate::AutoStream::new(buffer, choice); + // Ignore errors rather than panic + let _ = ::std::write!(&mut stream, $($arg)*); + let buffer = stream.into_inner(); + // Should be UTF-8 but not wanting to panic + let buffer = String::from_utf8_lossy(&buffer); + ::std::eprint!("{}", buffer) + } else { + use std::io::Write as _; + + let mut stream = $crate::stderr(); + match ::std::write!(&mut stream, $($arg)*) { + Err(e) if e.kind() != ::std::io::ErrorKind::BrokenPipe => { + ::std::panic!("failed printing to stdout: {e}"); + } + Err(_) | Ok(_) => {} + } + } + }}; +} + +/// Prints to [`stderr`][crate::stderr], with a newline. +/// +/// Equivalent to the [`println!`] macro, except that output goes to +/// `stderr` instead of `stdout`. See [`println!`] for +/// example usage. +/// +/// Use `eprintln!` only for error and progress messages. Use `println!` +/// instead for the primary output of your program. +/// +/// **NOTE:** Not all `eprintln!` calls will be captured in tests like [`std::eprintln!`] +/// - Capturing will automatically be activated in test binaries +/// - Otherwise, only when the `test` feature is enabled +/// +/// # Panics +/// +/// Panics if writing to `stderr` fails for any reason **except** broken pipe. +/// +/// Writing to non-blocking stdout can cause an error, which will lead +/// this macro to panic. +/// +/// # Examples +/// +/// ``` +/// # #[cfg(feature = "auto")] { +/// use anstream::eprintln; +/// +/// eprintln!("Error: Could not complete task"); +/// # } +/// ``` +#[cfg(feature = "auto")] +#[macro_export] +macro_rules! eprintln { + () => { + $crate::eprint!("\n") + }; + ($($arg:tt)*) => {{ + if cfg!(any(feature = "test", test)) { + use std::io::Write as _; + + let stdio = std::io::stderr(); + let choice = $crate::AutoStream::choice(&stdio); + let buffer = Vec::new(); + let mut stream = $crate::AutoStream::new(buffer, choice); + // Ignore errors rather than panic + let _ = ::std::write!(&mut stream, $($arg)*); + let buffer = stream.into_inner(); + // Should be UTF-8 but not wanting to panic + let buffer = String::from_utf8_lossy(&buffer); + ::std::eprintln!("{}", buffer) + } else { + use std::io::Write as _; + + let mut stream = $crate::stderr(); + match ::std::writeln!(&mut stream, $($arg)*) { + Err(e) if e.kind() != ::std::io::ErrorKind::BrokenPipe => { + ::std::panic!("failed printing to stdout: {e}"); + } + Err(_) | Ok(_) => {} + } + } + }}; +} + +/// Panics the current thread. +/// +/// This allows a program to terminate immediately and provide feedback +/// to the caller of the program. +/// +/// This macro is the perfect way to assert conditions in example code and in +/// tests. `panic!` is closely tied with the `unwrap` method of both +/// [`Option`][ounwrap] and [`Result`][runwrap] enums. Both implementations call +/// `panic!` when they are set to [`None`] or [`Err`] variants. +/// +/// When using `panic!()` you can specify a string payload, that is built using +/// the [`format!`] syntax. That payload is used when injecting the panic into +/// the calling Rust thread, causing the thread to panic entirely. +/// +/// The behavior of the default `std` hook, i.e. the code that runs directly +/// after the panic is invoked, is to print the message payload to +/// `stderr` along with the file/line/column information of the `panic!()` +/// call. You can override the panic hook using [`std::panic::set_hook()`]. +/// Inside the hook a panic can be accessed as a `&dyn Any + Send`, +/// which contains either a `&str` or `String` for regular `panic!()` invocations. +/// To panic with a value of another other type, [`panic_any`] can be used. +/// +/// See also the macro [`compile_error!`], for raising errors during compilation. +/// +/// # When to use `panic!` vs `Result` +/// +/// The Rust language provides two complementary systems for constructing / +/// representing, reporting, propagating, reacting to, and discarding errors. These +/// responsibilities are collectively known as "error handling." `panic!` and +/// `Result` are similar in that they are each the primary interface of their +/// respective error handling systems; however, the meaning these interfaces attach +/// to their errors and the responsibilities they fulfill within their respective +/// error handling systems differ. +/// +/// The `panic!` macro is used to construct errors that represent a bug that has +/// been detected in your program. With `panic!` you provide a message that +/// describes the bug and the language then constructs an error with that message, +/// reports it, and propagates it for you. +/// +/// `Result` on the other hand is used to wrap other types that represent either +/// the successful result of some computation, `Ok(T)`, or error types that +/// represent an anticipated runtime failure mode of that computation, `Err(E)`. +/// `Result` is used alongside user defined types which represent the various +/// anticipated runtime failure modes that the associated computation could +/// encounter. `Result` must be propagated manually, often with the the help of the +/// `?` operator and `Try` trait, and they must be reported manually, often with +/// the help of the `Error` trait. +/// +/// For more detailed information about error handling check out the [book] or the +/// [`std::result`] module docs. +/// +/// [ounwrap]: Option::unwrap +/// [runwrap]: Result::unwrap +/// [`std::panic::set_hook()`]: ../std/panic/fn.set_hook.html +/// [`panic_any`]: ../std/panic/fn.panic_any.html +/// [`Box`]: ../std/boxed/struct.Box.html +/// [`Any`]: crate::any::Any +/// [`format!`]: ../std/macro.format.html +/// [book]: ../book/ch09-00-error-handling.html +/// [`std::result`]: ../std/result/index.html +/// +/// # Current implementation +/// +/// If the main thread panics it will terminate all your threads and end your +/// program with code `101`. +/// +/// # Examples +/// +/// ```should_panic +/// # #![allow(unreachable_code)] +/// use anstream::panic; +/// panic!(); +/// panic!("this is a terrible mistake!"); +/// panic!("this is a {} {message}", "fancy", message = "message"); +/// ``` +#[cfg(feature = "auto")] +#[macro_export] +macro_rules! panic { + () => { + ::std::panic!() + }; + ($($arg:tt)*) => {{ + use std::io::Write as _; + + let panic_stream = std::io::stderr(); + let choice = $crate::AutoStream::choice(&panic_stream); + let buffer = Vec::new(); + let mut stream = $crate::AutoStream::new(buffer, choice); + // Ignore errors rather than panic + let _ = ::std::write!(&mut stream, $($arg)*); + let buffer = stream.into_inner(); + // Should be UTF-8 but not wanting to panic + let buffer = String::from_utf8_lossy(&buffer).into_owned(); + ::std::panic!("{}", buffer) + }}; +} |