summaryrefslogtreecommitdiffstats
path: root/vendor/anstream
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 18:31:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 18:31:44 +0000
commitc23a457e72abe608715ac76f076f47dc42af07a5 (patch)
tree2772049aaf84b5c9d0ed12ec8d86812f7a7904b6 /vendor/anstream
parentReleasing progress-linux version 1.73.0+dfsg1-1~progress7.99u1. (diff)
downloadrustc-c23a457e72abe608715ac76f076f47dc42af07a5.tar.xz
rustc-c23a457e72abe608715ac76f076f47dc42af07a5.zip
Merging upstream version 1.74.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/anstream')
-rw-r--r--vendor/anstream/.cargo-checksum.json2
-rw-r--r--vendor/anstream/Cargo.toml18
-rw-r--r--vendor/anstream/benches/stream.rs15
-rw-r--r--vendor/anstream/benches/strip.rs2
-rw-r--r--vendor/anstream/src/auto.rs100
-rw-r--r--vendor/anstream/src/buffer.rs46
-rw-r--r--vendor/anstream/src/fmt.rs54
-rw-r--r--vendor/anstream/src/lib.rs8
-rw-r--r--vendor/anstream/src/lockable.rs48
-rw-r--r--vendor/anstream/src/macros.rs128
-rw-r--r--vendor/anstream/src/raw.rs46
-rw-r--r--vendor/anstream/src/stream.rs261
-rw-r--r--vendor/anstream/src/strip.rs107
-rw-r--r--vendor/anstream/src/wincon.rs162
14 files changed, 687 insertions, 310 deletions
diff --git a/vendor/anstream/.cargo-checksum.json b/vendor/anstream/.cargo-checksum.json
index 3824cf9a4..a4d939b43 100644
--- a/vendor/anstream/.cargo-checksum.json
+++ b/vendor/anstream/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"48f9c457447fc49837fbbb9e76351fb4c685654fff37fa48b04c93fdc10a02c3","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"6efb0476a1cc085077ed49357026d8c173bf33017278ef440f222fb9cbcb66e6","README.md":"b230c2257d0c7a49b9bd97f2fa73abedcdc055757b5cedd2b0eb1a7a448ff461","benches/stream.rs":"94226af8a048d5db3d6a2e756ed0a1e3ca44a4927a7648ac673d6c3c621cda35","benches/strip.rs":"0569a82722cec5f2bbbf027ab279b7d946f9be7f2a8e698eb992e01c3d33898a","benches/wincon.rs":"680e86933c008b242a3286c5149c33d3c086426eb99fe134b6e79f7578f96663","src/adapter/mod.rs":"baf4237ea0b18df63609e49d93572ca27c2202a4cbec0220adb5a7e815c7d8ed","src/adapter/strip.rs":"010972f96708c56da9bced98287f134ce43a4f6459c22c1697abdc4fd6f82d00","src/adapter/wincon.rs":"9869aa553c253c49bebc0830628225cd294df8e84837b3952529173b06b24b85","src/auto.rs":"18796e0449ca0dff4a535e580e7176abab78227c6a1cd63f2c83b8f4ceceaab9","src/buffer.rs":"89712eb5c75ccfd4d4d757be394f2631844d7f0227afe0af4f5c3ff1567b750e","src/lib.rs":"059cdc8f9759c33f483a7997b7bd8c74c74a83911f2a0a70fa9aa3deaca277d8","src/lockable.rs":"09ffb8a7362c0812da9960234be6cf8290814453be94f6476be64e3804d6ce47","src/macros.rs":"9b8e1c5b0639c019fa2a84cc825e52fcd0749af4876a9ecf3a750f68469986aa","src/raw.rs":"beb6038242ca46aa21f09a55d8956422cdf6f1596fa97bb3ddf79ab67ac0c8f2","src/strip.rs":"d8469758e9992109b70c8b21b44794eb7341d29034fb0a9bd746c1174e7484f9","src/wincon.rs":"d27007d3b3453dbe18b49cdc088e8aabec2203149cb1f3e7aa4fcee28071d58b"},"package":"0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163"} \ No newline at end of file
+{"files":{"Cargo.toml":"5bd2428bd62a91e0f3be5e64d2df8facd8873ddad6ed3eb2335ec7292f09c7ae","LICENSE-APACHE":"c6596eb7be8581c18be736c846fb9173b69eccf6ef94c5135893ec56bd92ba08","LICENSE-MIT":"6efb0476a1cc085077ed49357026d8c173bf33017278ef440f222fb9cbcb66e6","README.md":"b230c2257d0c7a49b9bd97f2fa73abedcdc055757b5cedd2b0eb1a7a448ff461","benches/stream.rs":"7e666c4f4b79ddb5237361ed25264a966ee241192fbb2c1baea3006e3e0326b4","benches/strip.rs":"9603bd5ca1ae4661c2ccab50315dbfdec0c661ac2624262172bbd8f5d0bd87c9","benches/wincon.rs":"680e86933c008b242a3286c5149c33d3c086426eb99fe134b6e79f7578f96663","src/adapter/mod.rs":"baf4237ea0b18df63609e49d93572ca27c2202a4cbec0220adb5a7e815c7d8ed","src/adapter/strip.rs":"010972f96708c56da9bced98287f134ce43a4f6459c22c1697abdc4fd6f82d00","src/adapter/wincon.rs":"9869aa553c253c49bebc0830628225cd294df8e84837b3952529173b06b24b85","src/auto.rs":"36dafc3aabaff080198f901268d2aa5453cc4b1cd7b93277edf90cad6354cb72","src/buffer.rs":"83e7088b50dd3e2941c06a417d9eef75fda45311a2912ba94f480ec98d6f0183","src/fmt.rs":"cc11b005c4559843bd908a57958a13c8d0922fae6aff5261f3583c90e60da73c","src/lib.rs":"649b86b187835e0e33baaaf2242c5f331b7dff133fae8fc419c52b7add797c57","src/macros.rs":"a26ababe32a39732d0aade9674f6e5e267bd26c6ea06603ff9e61e80681195e0","src/stream.rs":"cbe8f61fba4c3c60934339c8bda5d1ff43320f57cdc4ed409aa173945a941b3d","src/strip.rs":"56e6516283b6c0dfa72a8e0e6679da8424295f50a3e56c44281e76de6aa0344b","src/wincon.rs":"fe5aff7bfd80b14c9a6b07143079d59b81831293ad766b845e46fad2e1459c9a"},"package":"83d7b3983a025adeb201ef26a5564ebd1641ea9851f6282aee4940f745a3c07c"} \ No newline at end of file
diff --git a/vendor/anstream/Cargo.toml b/vendor/anstream/Cargo.toml
index 75d78e26e..d60caca19 100644
--- a/vendor/anstream/Cargo.toml
+++ b/vendor/anstream/Cargo.toml
@@ -11,9 +11,9 @@
[package]
edition = "2021"
-rust-version = "1.64.0"
+rust-version = "1.70.0"
name = "anstream"
-version = "0.3.2"
+version = "0.6.3"
include = [
"build.rs",
"src/**/*",
@@ -109,37 +109,33 @@ optional = true
version = "1.0.0"
optional = true
-[dependencies.is-terminal]
-version = "0.4.4"
-optional = true
-
[dependencies.utf8parse]
version = "0.2.1"
[dev-dependencies.criterion]
-version = "0.4.0"
+version = "0.5.1"
[dev-dependencies.owo-colors]
version = "3.5.0"
[dev-dependencies.proptest]
-version = "1.1.0"
+version = "1.2.0"
[dev-dependencies.strip-ansi-escapes]
-version = "0.1.1"
+version = "0.2.0"
[features]
auto = [
"dep:anstyle-query",
"dep:colorchoice",
- "dep:is-terminal",
]
default = [
"auto",
"wincon",
]
+test = []
wincon = ["dep:anstyle-wincon"]
[target."cfg(windows)".dependencies.anstyle-wincon]
-version = "1.0.1"
+version = "3.0.1"
optional = true
diff --git a/vendor/anstream/benches/stream.rs b/vendor/anstream/benches/stream.rs
index 55c20b896..f89aacf5f 100644
--- a/vendor/anstream/benches/stream.rs
+++ b/vendor/anstream/benches/stream.rs
@@ -15,7 +15,7 @@ fn stream(c: &mut Criterion) {
let mut group = c.benchmark_group(name);
group.bench_function("nop", |b| {
b.iter(|| {
- let buffer = anstream::Buffer::with_capacity(content.len());
+ let buffer = Vec::with_capacity(content.len());
let mut stream = buffer;
stream.write_all(content).unwrap();
@@ -25,7 +25,7 @@ fn stream(c: &mut Criterion) {
});
group.bench_function("StripStream", |b| {
b.iter(|| {
- let buffer = anstream::Buffer::with_capacity(content.len());
+ let buffer = Vec::with_capacity(content.len());
let mut stream = anstream::StripStream::new(buffer);
stream.write_all(content).unwrap();
@@ -36,9 +36,8 @@ fn stream(c: &mut Criterion) {
#[cfg(all(windows, feature = "wincon"))]
group.bench_function("WinconStream", |b| {
b.iter(|| {
- let buffer = anstream::Buffer::with_capacity(content.len());
- let mut stream =
- anstream::WinconStream::new(anstyle_wincon::Console::new(buffer).unwrap());
+ let buffer = Vec::with_capacity(content.len());
+ let mut stream = anstream::WinconStream::new(buffer);
stream.write_all(content).unwrap();
@@ -47,7 +46,7 @@ fn stream(c: &mut Criterion) {
});
group.bench_function("AutoStream::always_ansi", |b| {
b.iter(|| {
- let buffer = anstream::Buffer::with_capacity(content.len());
+ let buffer = Vec::with_capacity(content.len());
let mut stream = anstream::AutoStream::always_ansi(buffer);
stream.write_all(content).unwrap();
@@ -57,7 +56,7 @@ fn stream(c: &mut Criterion) {
});
group.bench_function("AutoStream::always", |b| {
b.iter(|| {
- let buffer = anstream::Buffer::with_capacity(content.len());
+ let buffer = Vec::with_capacity(content.len());
let mut stream = anstream::AutoStream::always(buffer);
stream.write_all(content).unwrap();
@@ -67,7 +66,7 @@ fn stream(c: &mut Criterion) {
});
group.bench_function("AutoStream::never", |b| {
b.iter(|| {
- let buffer = anstream::Buffer::with_capacity(content.len());
+ let buffer = Vec::with_capacity(content.len());
let mut stream = anstream::AutoStream::never(buffer);
stream.write_all(content).unwrap();
diff --git a/vendor/anstream/benches/strip.rs b/vendor/anstream/benches/strip.rs
index af204bf96..9ed6178c4 100644
--- a/vendor/anstream/benches/strip.rs
+++ b/vendor/anstream/benches/strip.rs
@@ -63,7 +63,7 @@ fn strip(c: &mut Criterion) {
});
group.bench_function("strip_ansi_escapes", |b| {
b.iter(|| {
- let stripped = strip_ansi_escapes::strip(content).unwrap();
+ let stripped = strip_ansi_escapes::strip(content);
black_box(stripped)
})
diff --git a/vendor/anstream/src/auto.rs b/vendor/anstream/src/auto.rs
index b252c05cb..2b9d361cd 100644
--- a/vendor/anstream/src/auto.rs
+++ b/vendor/anstream/src/auto.rs
@@ -1,7 +1,7 @@
+use crate::stream::AsLockedWrite;
+use crate::stream::RawStream;
#[cfg(feature = "auto")]
use crate::ColorChoice;
-use crate::Lockable;
-use crate::RawStream;
use crate::StripStream;
#[cfg(all(windows, feature = "wincon"))]
use crate::WinconStream;
@@ -101,9 +101,8 @@ where
fn wincon(raw: S) -> Result<Self, S> {
#[cfg(all(windows, feature = "wincon"))]
{
- let console = anstyle_wincon::Console::new(raw)?;
Ok(Self {
- inner: StreamInner::Wincon(WinconStream::new(console)),
+ inner: StreamInner::Wincon(WinconStream::new(raw)),
})
}
#[cfg(not(all(windows, feature = "wincon")))]
@@ -119,18 +118,30 @@ where
StreamInner::PassThrough(w) => w,
StreamInner::Strip(w) => w.into_inner(),
#[cfg(all(windows, feature = "wincon"))]
- StreamInner::Wincon(w) => w.into_inner().into_inner(),
+ StreamInner::Wincon(w) => w.into_inner(),
}
}
#[inline]
- #[cfg(feature = "auto")]
pub fn is_terminal(&self) -> bool {
match &self.inner {
StreamInner::PassThrough(w) => w.is_terminal(),
StreamInner::Strip(w) => w.is_terminal(),
#[cfg(all(windows, feature = "wincon"))]
- StreamInner::Wincon(w) => true,
+ StreamInner::Wincon(_) => true, // its only ever a terminal
+ }
+ }
+
+ /// Prefer [`AutoStream::choice`]
+ ///
+ /// This doesn't report what is requested but what is currently active.
+ #[inline]
+ pub fn current_choice(&self) -> ColorChoice {
+ match &self.inner {
+ StreamInner::PassThrough(_) => ColorChoice::AlwaysAnsi,
+ StreamInner::Strip(_) => ColorChoice::Never,
+ #[cfg(all(windows, feature = "wincon"))]
+ StreamInner::Wincon(_) => ColorChoice::Always,
}
}
}
@@ -160,29 +171,32 @@ fn choice(raw: &dyn RawStream) -> ColorChoice {
}
}
-#[cfg(feature = "auto")]
-impl<S> is_terminal::IsTerminal for AutoStream<S>
-where
- S: RawStream,
-{
+impl AutoStream<std::io::Stdout> {
+ /// Get exclusive access to the `AutoStream`
+ ///
+ /// Why?
+ /// - Faster performance when writing in a loop
+ /// - Avoid other threads interleaving output with the current thread
#[inline]
- fn is_terminal(&self) -> bool {
- self.is_terminal()
+ pub fn lock(self) -> AutoStream<std::io::StdoutLock<'static>> {
+ let inner = match self.inner {
+ StreamInner::PassThrough(w) => StreamInner::PassThrough(w.lock()),
+ StreamInner::Strip(w) => StreamInner::Strip(w.lock()),
+ #[cfg(all(windows, feature = "wincon"))]
+ StreamInner::Wincon(w) => StreamInner::Wincon(w.lock()),
+ };
+ AutoStream { inner }
}
}
-impl<S> AutoStream<S>
-where
- S: Lockable + RawStream,
- <S as Lockable>::Locked: RawStream,
-{
+impl AutoStream<std::io::Stderr> {
/// Get exclusive access to the `AutoStream`
///
/// Why?
/// - Faster performance when writing in a loop
/// - Avoid other threads interleaving output with the current thread
#[inline]
- pub fn lock(self) -> <Self as Lockable>::Locked {
+ pub fn lock(self) -> AutoStream<std::io::StderrLock<'static>> {
let inner = match self.inner {
StreamInner::PassThrough(w) => StreamInner::PassThrough(w.lock()),
StreamInner::Strip(w) => StreamInner::Strip(w.lock()),
@@ -195,54 +209,54 @@ where
impl<S> std::io::Write for AutoStream<S>
where
- S: RawStream,
+ S: RawStream + AsLockedWrite,
{
+ // Must forward all calls to ensure locking happens appropriately
#[inline]
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
match &mut self.inner {
- StreamInner::PassThrough(w) => w.write(buf),
+ StreamInner::PassThrough(w) => w.as_locked_write().write(buf),
StreamInner::Strip(w) => w.write(buf),
#[cfg(all(windows, feature = "wincon"))]
StreamInner::Wincon(w) => w.write(buf),
}
}
-
+ #[inline]
+ fn write_vectored(&mut self, bufs: &[std::io::IoSlice<'_>]) -> std::io::Result<usize> {
+ match &mut self.inner {
+ StreamInner::PassThrough(w) => w.as_locked_write().write_vectored(bufs),
+ StreamInner::Strip(w) => w.write_vectored(bufs),
+ #[cfg(all(windows, feature = "wincon"))]
+ StreamInner::Wincon(w) => w.write_vectored(bufs),
+ }
+ }
+ // is_write_vectored: nightly only
#[inline]
fn flush(&mut self) -> std::io::Result<()> {
match &mut self.inner {
- StreamInner::PassThrough(w) => w.flush(),
+ StreamInner::PassThrough(w) => w.as_locked_write().flush(),
StreamInner::Strip(w) => w.flush(),
#[cfg(all(windows, feature = "wincon"))]
StreamInner::Wincon(w) => w.flush(),
}
}
-
- // Provide explicit implementations of trait methods
- // - To reduce bookkeeping
- // - Avoid acquiring / releasing locks in a loop
-
#[inline]
fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> {
match &mut self.inner {
- StreamInner::PassThrough(w) => w.write_all(buf),
+ StreamInner::PassThrough(w) => w.as_locked_write().write_all(buf),
StreamInner::Strip(w) => w.write_all(buf),
#[cfg(all(windows, feature = "wincon"))]
StreamInner::Wincon(w) => w.write_all(buf),
}
}
-
- // Not bothering with `write_fmt` as it just calls `write_all`
-}
-
-impl<S> Lockable for AutoStream<S>
-where
- S: Lockable + RawStream,
- <S as Lockable>::Locked: RawStream,
-{
- type Locked = AutoStream<<S as Lockable>::Locked>;
-
+ // write_all_vectored: nightly only
#[inline]
- fn lock(self) -> Self::Locked {
- self.lock()
+ fn write_fmt(&mut self, args: std::fmt::Arguments<'_>) -> std::io::Result<()> {
+ match &mut self.inner {
+ StreamInner::PassThrough(w) => w.as_locked_write().write_fmt(args),
+ StreamInner::Strip(w) => w.write_fmt(args),
+ #[cfg(all(windows, feature = "wincon"))]
+ StreamInner::Wincon(w) => w.write_fmt(args),
+ }
}
}
diff --git a/vendor/anstream/src/buffer.rs b/vendor/anstream/src/buffer.rs
index 1ba0bffdb..9846bb7c8 100644
--- a/vendor/anstream/src/buffer.rs
+++ b/vendor/anstream/src/buffer.rs
@@ -1,5 +1,9 @@
-/// In-memory [`RawStream`][crate::RawStream]
+#![allow(deprecated)]
+
+/// In-memory [`RawStream`][crate::stream::RawStream]
#[derive(Clone, Default, Debug, PartialEq, Eq)]
+#[deprecated(since = "0.6.2", note = "Use Vec")]
+#[doc(hidden)]
pub struct Buffer(Vec<u8>);
impl Buffer {
@@ -26,14 +30,6 @@ impl AsRef<[u8]> for Buffer {
}
}
-#[cfg(feature = "auto")]
-impl is_terminal::IsTerminal for Buffer {
- #[inline]
- fn is_terminal(&self) -> bool {
- false
- }
-}
-
impl std::io::Write for Buffer {
#[inline]
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
@@ -49,28 +45,24 @@ impl std::io::Write for Buffer {
#[cfg(all(windows, feature = "wincon"))]
impl anstyle_wincon::WinconStream for Buffer {
- fn set_colors(
+ fn write_colored(
&mut self,
fg: Option<anstyle::AnsiColor>,
bg: Option<anstyle::AnsiColor>,
- ) -> std::io::Result<()> {
- use std::io::Write as _;
-
- if let Some(fg) = fg {
- write!(self, "{}", fg.render_fg())?;
- }
- if let Some(bg) = bg {
- write!(self, "{}", bg.render_bg())?;
- }
- if fg.is_none() && bg.is_none() {
- write!(self, "{}", anstyle::Reset.render())?;
- }
- Ok(())
+ data: &[u8],
+ ) -> std::io::Result<usize> {
+ self.0.write_colored(fg, bg, data)
}
+}
- fn get_colors(
- &self,
- ) -> std::io::Result<(Option<anstyle::AnsiColor>, Option<anstyle::AnsiColor>)> {
- Ok((None, None))
+#[cfg(all(windows, feature = "wincon"))]
+impl anstyle_wincon::WinconStream for &'_ mut Buffer {
+ fn write_colored(
+ &mut self,
+ fg: Option<anstyle::AnsiColor>,
+ bg: Option<anstyle::AnsiColor>,
+ data: &[u8],
+ ) -> std::io::Result<usize> {
+ (**self).write_colored(fg, bg, data)
}
}
diff --git a/vendor/anstream/src/fmt.rs b/vendor/anstream/src/fmt.rs
new file mode 100644
index 000000000..e673c26dd
--- /dev/null
+++ b/vendor/anstream/src/fmt.rs
@@ -0,0 +1,54 @@
+/// A shim which allows a [`std::io::Write`] to be implemented in terms of a [`std::fmt::Write`]
+///
+/// This saves off I/O errors. instead of discarding them
+pub(crate) struct Adapter<W>
+where
+ W: FnMut(&[u8]) -> std::io::Result<()>,
+{
+ writer: W,
+ error: std::io::Result<()>,
+}
+
+impl<W> Adapter<W>
+where
+ W: FnMut(&[u8]) -> std::io::Result<()>,
+{
+ pub(crate) fn new(writer: W) -> Self {
+ Adapter {
+ writer,
+ error: Ok(()),
+ }
+ }
+
+ pub(crate) fn write_fmt(mut self, fmt: std::fmt::Arguments<'_>) -> std::io::Result<()> {
+ match std::fmt::write(&mut self, fmt) {
+ Ok(()) => Ok(()),
+ Err(..) => {
+ // check if the error came from the underlying `Write` or not
+ if self.error.is_err() {
+ self.error
+ } else {
+ Err(std::io::Error::new(
+ std::io::ErrorKind::Other,
+ "formatter error",
+ ))
+ }
+ }
+ }
+ }
+}
+
+impl<W> std::fmt::Write for Adapter<W>
+where
+ W: FnMut(&[u8]) -> std::io::Result<()>,
+{
+ fn write_str(&mut self, s: &str) -> std::fmt::Result {
+ match (self.writer)(s.as_bytes()) {
+ Ok(()) => Ok(()),
+ Err(e) => {
+ self.error = Err(e);
+ Err(std::fmt::Error)
+ }
+ }
+ }
+}
diff --git a/vendor/anstream/src/lib.rs b/vendor/anstream/src/lib.rs
index 582fa5221..972113903 100644
--- a/vendor/anstream/src/lib.rs
+++ b/vendor/anstream/src/lib.rs
@@ -35,23 +35,23 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
pub mod adapter;
+pub mod stream;
+
mod buffer;
#[macro_use]
mod macros;
mod auto;
-mod lockable;
-mod raw;
+mod fmt;
mod strip;
#[cfg(all(windows, feature = "wincon"))]
mod wincon;
pub use auto::AutoStream;
-pub use lockable::Lockable;
-pub use raw::RawStream;
pub use strip::StripStream;
#[cfg(all(windows, feature = "wincon"))]
pub use wincon::WinconStream;
+#[allow(deprecated)]
pub use buffer::Buffer;
/// Create an ANSI escape code compatible stdout
diff --git a/vendor/anstream/src/lockable.rs b/vendor/anstream/src/lockable.rs
deleted file mode 100644
index fcf20e317..000000000
--- a/vendor/anstream/src/lockable.rs
+++ /dev/null
@@ -1,48 +0,0 @@
-#[cfg(all(windows, feature = "wincon"))]
-use crate::RawStream;
-
-/// Explicitly lock a [`std::io::Write`]able
-pub trait Lockable {
- type Locked;
-
- /// Get exclusive access to the `AutoStream`
- ///
- /// Why?
- /// - Faster performance when writing in a loop
- /// - Avoid other threads interleaving output with the current thread
- fn lock(self) -> Self::Locked;
-}
-
-impl Lockable for std::io::Stdout {
- type Locked = std::io::StdoutLock<'static>;
-
- #[inline]
- fn lock(self) -> Self::Locked {
- #[allow(clippy::needless_borrow)] // Its needed to avoid recursion
- (&self).lock()
- }
-}
-
-impl Lockable for std::io::Stderr {
- type Locked = std::io::StderrLock<'static>;
-
- #[inline]
- fn lock(self) -> Self::Locked {
- #[allow(clippy::needless_borrow)] // Its needed to avoid recursion
- (&self).lock()
- }
-}
-
-#[cfg(all(windows, feature = "wincon"))]
-impl<S> Lockable for anstyle_wincon::Console<S>
-where
- S: RawStream + Lockable,
- <S as Lockable>::Locked: RawStream,
-{
- type Locked = anstyle_wincon::Console<<S as Lockable>::Locked>;
-
- #[inline]
- fn lock(self) -> Self::Locked {
- self.map(|s| s.lock())
- }
-}
diff --git a/vendor/anstream/src/macros.rs b/vendor/anstream/src/macros.rs
index ea9095944..bd1accb06 100644
--- a/vendor/anstream/src/macros.rs
+++ b/vendor/anstream/src/macros.rs
@@ -22,6 +22,10 @@
/// 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.
@@ -56,14 +60,29 @@
#[macro_export]
macro_rules! print {
($($arg:tt)*) => {{
- use std::io::Write as _;
+ 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}");
+ 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(_) => {}
}
- Err(_) | Ok(_) => {}
}
}};
}
@@ -91,6 +110,10 @@ macro_rules! print {
/// 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.
@@ -118,14 +141,29 @@ macro_rules! println {
$crate::print!("\n")
};
($($arg:tt)*) => {{
- use std::io::Write as _;
+ 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}");
+ 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(_) => {}
}
- Err(_) | Ok(_) => {}
}
}};
}
@@ -139,6 +177,10 @@ macro_rules! println {
/// 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.
@@ -159,14 +201,29 @@ macro_rules! println {
#[macro_export]
macro_rules! eprint {
($($arg:tt)*) => {{
- use std::io::Write as _;
+ 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}");
+ 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(_) => {}
}
- Err(_) | Ok(_) => {}
}
}};
}
@@ -180,6 +237,10 @@ macro_rules! eprint {
/// 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.
@@ -203,14 +264,29 @@ macro_rules! eprintln {
$crate::eprint!("\n")
};
($($arg:tt)*) => {{
- use std::io::Write as _;
+ 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}");
+ 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(_) => {}
}
- Err(_) | Ok(_) => {}
}
}};
}
@@ -301,13 +377,13 @@ macro_rules! panic {
let panic_stream = std::io::stderr();
let choice = $crate::AutoStream::choice(&panic_stream);
- let buffer = $crate::Buffer::new();
+ 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.as_bytes()).into_owned();
+ let buffer = String::from_utf8_lossy(&buffer).into_owned();
::std::panic!("{}", buffer)
}};
}
diff --git a/vendor/anstream/src/raw.rs b/vendor/anstream/src/raw.rs
deleted file mode 100644
index ecf7c6850..000000000
--- a/vendor/anstream/src/raw.rs
+++ /dev/null
@@ -1,46 +0,0 @@
-/// Required functionality for underlying [`std::io::Write`] for adaptation
-#[cfg(not(any(feature = "auto", all(windows, feature = "wincon"))))]
-pub trait RawStream: std::io::Write + private::Sealed {}
-
-/// Required functionality for underlying [`std::io::Write`] for adaptation
-#[cfg(all(feature = "auto", not(all(windows, feature = "wincon"))))]
-pub trait RawStream: std::io::Write + is_terminal::IsTerminal + private::Sealed {}
-
-/// Required functionality for underlying [`std::io::Write`] for adaptation
-#[cfg(all(not(feature = "auto"), all(windows, feature = "wincon")))]
-pub trait RawStream: std::io::Write + anstyle_wincon::WinconStream + private::Sealed {}
-
-/// Required functionality for underlying [`std::io::Write`] for adaptation
-#[cfg(all(feature = "auto", all(windows, feature = "wincon")))]
-pub trait RawStream:
- std::io::Write + is_terminal::IsTerminal + anstyle_wincon::WinconStream + private::Sealed
-{
-}
-
-impl RawStream for std::io::Stdout {}
-
-impl RawStream for std::io::StdoutLock<'static> {}
-
-impl RawStream for std::io::Stderr {}
-
-impl RawStream for std::io::StderrLock<'static> {}
-
-impl RawStream for std::fs::File {}
-
-impl RawStream for crate::Buffer {}
-
-mod private {
- pub trait Sealed {}
-
- impl Sealed for std::io::Stdout {}
-
- impl Sealed for std::io::StdoutLock<'static> {}
-
- impl Sealed for std::io::Stderr {}
-
- impl Sealed for std::io::StderrLock<'static> {}
-
- impl Sealed for std::fs::File {}
-
- impl Sealed for crate::Buffer {}
-}
diff --git a/vendor/anstream/src/stream.rs b/vendor/anstream/src/stream.rs
new file mode 100644
index 000000000..e2f7e68d9
--- /dev/null
+++ b/vendor/anstream/src/stream.rs
@@ -0,0 +1,261 @@
+//! Higher-level traits to describe writeable streams
+
+/// Required functionality for underlying [`std::io::Write`] for adaptation
+#[cfg(not(all(windows, feature = "wincon")))]
+pub trait RawStream: std::io::Write + IsTerminal + private::Sealed {}
+
+/// Required functionality for underlying [`std::io::Write`] for adaptation
+#[cfg(all(windows, feature = "wincon"))]
+pub trait RawStream:
+ std::io::Write + IsTerminal + anstyle_wincon::WinconStream + private::Sealed
+{
+}
+
+impl RawStream for std::io::Stdout {}
+
+impl RawStream for std::io::StdoutLock<'_> {}
+
+impl RawStream for &'_ mut std::io::StdoutLock<'_> {}
+
+impl RawStream for std::io::Stderr {}
+
+impl RawStream for std::io::StderrLock<'_> {}
+
+impl RawStream for &'_ mut std::io::StderrLock<'_> {}
+
+impl RawStream for Box<dyn std::io::Write> {}
+
+impl RawStream for &'_ mut Box<dyn std::io::Write> {}
+
+impl RawStream for Vec<u8> {}
+
+impl RawStream for &'_ mut Vec<u8> {}
+
+impl RawStream for std::fs::File {}
+
+impl RawStream for &'_ mut std::fs::File {}
+
+#[allow(deprecated)]
+impl RawStream for crate::Buffer {}
+
+#[allow(deprecated)]
+impl RawStream for &'_ mut crate::Buffer {}
+
+pub trait IsTerminal: private::Sealed {
+ fn is_terminal(&self) -> bool;
+}
+
+impl IsTerminal for std::io::Stdout {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ std::io::IsTerminal::is_terminal(self)
+ }
+}
+
+impl IsTerminal for std::io::StdoutLock<'_> {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ std::io::IsTerminal::is_terminal(self)
+ }
+}
+
+impl IsTerminal for &'_ mut std::io::StdoutLock<'_> {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ (**self).is_terminal()
+ }
+}
+
+impl IsTerminal for std::io::Stderr {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ std::io::IsTerminal::is_terminal(self)
+ }
+}
+
+impl IsTerminal for std::io::StderrLock<'_> {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ std::io::IsTerminal::is_terminal(self)
+ }
+}
+
+impl IsTerminal for &'_ mut std::io::StderrLock<'_> {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ (**self).is_terminal()
+ }
+}
+
+impl IsTerminal for Box<dyn std::io::Write> {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ false
+ }
+}
+
+impl IsTerminal for &'_ mut Box<dyn std::io::Write> {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ false
+ }
+}
+
+impl IsTerminal for Vec<u8> {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ false
+ }
+}
+
+impl IsTerminal for &'_ mut Vec<u8> {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ false
+ }
+}
+
+impl IsTerminal for std::fs::File {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ std::io::IsTerminal::is_terminal(self)
+ }
+}
+
+impl IsTerminal for &'_ mut std::fs::File {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ (**self).is_terminal()
+ }
+}
+
+#[allow(deprecated)]
+impl IsTerminal for crate::Buffer {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ false
+ }
+}
+
+#[allow(deprecated)]
+impl IsTerminal for &'_ mut crate::Buffer {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ (**self).is_terminal()
+ }
+}
+
+pub trait AsLockedWrite: private::Sealed {
+ type Write<'w>: RawStream + 'w
+ where
+ Self: 'w;
+
+ fn as_locked_write(&mut self) -> Self::Write<'_>;
+}
+
+impl AsLockedWrite for std::io::Stdout {
+ type Write<'w> = std::io::StdoutLock<'w>;
+
+ #[inline]
+ fn as_locked_write(&mut self) -> Self::Write<'_> {
+ self.lock()
+ }
+}
+
+impl AsLockedWrite for std::io::StdoutLock<'static> {
+ type Write<'w> = &'w mut Self;
+
+ #[inline]
+ fn as_locked_write(&mut self) -> Self::Write<'_> {
+ self
+ }
+}
+
+impl AsLockedWrite for std::io::Stderr {
+ type Write<'w> = std::io::StderrLock<'w>;
+
+ #[inline]
+ fn as_locked_write(&mut self) -> Self::Write<'_> {
+ self.lock()
+ }
+}
+
+impl AsLockedWrite for std::io::StderrLock<'static> {
+ type Write<'w> = &'w mut Self;
+
+ #[inline]
+ fn as_locked_write(&mut self) -> Self::Write<'_> {
+ self
+ }
+}
+
+impl AsLockedWrite for Box<dyn std::io::Write> {
+ type Write<'w> = &'w mut Self;
+
+ #[inline]
+ fn as_locked_write(&mut self) -> Self::Write<'_> {
+ self
+ }
+}
+
+impl AsLockedWrite for Vec<u8> {
+ type Write<'w> = &'w mut Self;
+
+ #[inline]
+ fn as_locked_write(&mut self) -> Self::Write<'_> {
+ self
+ }
+}
+
+impl AsLockedWrite for std::fs::File {
+ type Write<'w> = &'w mut Self;
+
+ #[inline]
+ fn as_locked_write(&mut self) -> Self::Write<'_> {
+ self
+ }
+}
+
+#[allow(deprecated)]
+impl AsLockedWrite for crate::Buffer {
+ type Write<'w> = &'w mut Self;
+
+ #[inline]
+ fn as_locked_write(&mut self) -> Self::Write<'_> {
+ self
+ }
+}
+
+mod private {
+ pub trait Sealed {}
+
+ impl Sealed for std::io::Stdout {}
+
+ impl Sealed for std::io::StdoutLock<'_> {}
+
+ impl Sealed for &'_ mut std::io::StdoutLock<'_> {}
+
+ impl Sealed for std::io::Stderr {}
+
+ impl Sealed for std::io::StderrLock<'_> {}
+
+ impl Sealed for &'_ mut std::io::StderrLock<'_> {}
+
+ impl Sealed for Box<dyn std::io::Write> {}
+
+ impl Sealed for &'_ mut Box<dyn std::io::Write> {}
+
+ impl Sealed for Vec<u8> {}
+
+ impl Sealed for &'_ mut Vec<u8> {}
+
+ impl Sealed for std::fs::File {}
+
+ impl Sealed for &'_ mut std::fs::File {}
+
+ #[allow(deprecated)]
+ impl Sealed for crate::Buffer {}
+
+ #[allow(deprecated)]
+ impl Sealed for &'_ mut crate::Buffer {}
+}
diff --git a/vendor/anstream/src/strip.rs b/vendor/anstream/src/strip.rs
index 0dd017497..d7fda04a7 100644
--- a/vendor/anstream/src/strip.rs
+++ b/vendor/anstream/src/strip.rs
@@ -1,10 +1,13 @@
use crate::adapter::StripBytes;
-use crate::Lockable;
-use crate::RawStream;
+use crate::stream::AsLockedWrite;
+use crate::stream::RawStream;
/// Only pass printable data to the inner `Write`
#[derive(Debug)]
-pub struct StripStream<S> {
+pub struct StripStream<S>
+where
+ S: RawStream,
+{
raw: S,
state: StripBytes,
}
@@ -29,47 +32,73 @@ where
}
#[inline]
- #[cfg(feature = "auto")]
pub fn is_terminal(&self) -> bool {
self.raw.is_terminal()
}
}
-#[cfg(feature = "auto")]
-impl<S> is_terminal::IsTerminal for StripStream<S>
-where
- S: RawStream,
-{
+impl StripStream<std::io::Stdout> {
+ /// Get exclusive access to the `StripStream`
+ ///
+ /// Why?
+ /// - Faster performance when writing in a loop
+ /// - Avoid other threads interleaving output with the current thread
+ #[inline]
+ pub fn lock(self) -> StripStream<std::io::StdoutLock<'static>> {
+ StripStream {
+ raw: self.raw.lock(),
+ state: self.state,
+ }
+ }
+}
+
+impl StripStream<std::io::Stderr> {
+ /// Get exclusive access to the `StripStream`
+ ///
+ /// Why?
+ /// - Faster performance when writing in a loop
+ /// - Avoid other threads interleaving output with the current thread
#[inline]
- fn is_terminal(&self) -> bool {
- self.is_terminal()
+ pub fn lock(self) -> StripStream<std::io::StderrLock<'static>> {
+ StripStream {
+ raw: self.raw.lock(),
+ state: self.state,
+ }
}
}
impl<S> std::io::Write for StripStream<S>
where
- S: RawStream,
+ S: RawStream + AsLockedWrite,
{
+ // Must forward all calls to ensure locking happens appropriately
#[inline]
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
- write(&mut self.raw, &mut self.state, buf)
+ write(&mut self.raw.as_locked_write(), &mut self.state, buf)
}
-
+ #[inline]
+ fn write_vectored(&mut self, bufs: &[std::io::IoSlice<'_>]) -> std::io::Result<usize> {
+ let buf = bufs
+ .iter()
+ .find(|b| !b.is_empty())
+ .map(|b| &**b)
+ .unwrap_or(&[][..]);
+ self.write(buf)
+ }
+ // is_write_vectored: nightly only
#[inline]
fn flush(&mut self) -> std::io::Result<()> {
- self.raw.flush()
+ self.raw.as_locked_write().flush()
}
-
- // Provide explicit implementations of trait methods
- // - To reduce bookkeeping
- // - Avoid acquiring / releasing locks in a loop
-
#[inline]
fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> {
- write_all(&mut self.raw, &mut self.state, buf)
+ write_all(&mut self.raw.as_locked_write(), &mut self.state, buf)
+ }
+ // write_all_vectored: nightly only
+ #[inline]
+ fn write_fmt(&mut self, args: std::fmt::Arguments<'_>) -> std::io::Result<()> {
+ write_fmt(&mut self.raw.as_locked_write(), &mut self.state, args)
}
-
- // Not bothering with `write_fmt` as it just calls `write_all`
}
fn write(
@@ -105,6 +134,15 @@ fn write_all(
Ok(())
}
+fn write_fmt(
+ raw: &mut dyn std::io::Write,
+ state: &mut StripBytes,
+ args: std::fmt::Arguments<'_>,
+) -> std::io::Result<()> {
+ let write_all = |buf: &[u8]| write_all(raw, state, buf);
+ crate::fmt::Adapter::new(write_all).write_fmt(args)
+}
+
#[inline]
fn offset_to(total: &[u8], subslice: &[u8]) -> usize {
let total = total.as_ptr();
@@ -117,21 +155,6 @@ fn offset_to(total: &[u8], subslice: &[u8]) -> usize {
subslice as usize - total as usize
}
-impl<S> Lockable for StripStream<S>
-where
- S: Lockable,
-{
- type Locked = StripStream<<S as Lockable>::Locked>;
-
- #[inline]
- fn lock(self) -> Self::Locked {
- Self::Locked {
- raw: self.raw.lock(),
- state: self.state,
- }
- }
-}
-
#[cfg(test)]
mod test {
use super::*;
@@ -142,7 +165,7 @@ mod test {
#[test]
#[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
fn write_all_no_escapes(s in "\\PC*") {
- let buffer = crate::Buffer::new();
+ let buffer = Vec::new();
let mut stream = StripStream::new(buffer);
stream.write_all(s.as_bytes()).unwrap();
let buffer = stream.into_inner();
@@ -153,7 +176,7 @@ mod test {
#[test]
#[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
fn write_byte_no_escapes(s in "\\PC*") {
- let buffer = crate::Buffer::new();
+ let buffer = Vec::new();
let mut stream = StripStream::new(buffer);
for byte in s.as_bytes() {
stream.write_all(&[*byte]).unwrap();
@@ -166,7 +189,7 @@ mod test {
#[test]
#[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
fn write_all_random(s in any::<Vec<u8>>()) {
- let buffer = crate::Buffer::new();
+ let buffer = Vec::new();
let mut stream = StripStream::new(buffer);
stream.write_all(s.as_slice()).unwrap();
let buffer = stream.into_inner();
@@ -180,7 +203,7 @@ mod test {
#[test]
#[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
fn write_byte_random(s in any::<Vec<u8>>()) {
- let buffer = crate::Buffer::new();
+ let buffer = Vec::new();
let mut stream = StripStream::new(buffer);
for byte in s.as_slice() {
stream.write_all(&[*byte]).unwrap();
diff --git a/vendor/anstream/src/wincon.rs b/vendor/anstream/src/wincon.rs
index 6627bbb59..a5aa5e747 100644
--- a/vendor/anstream/src/wincon.rs
+++ b/vendor/anstream/src/wincon.rs
@@ -1,6 +1,6 @@
use crate::adapter::WinconBytes;
-use crate::Lockable;
-use crate::RawStream;
+use crate::stream::AsLockedWrite;
+use crate::stream::RawStream;
/// Only pass printable data to the inner `Write`
#[cfg(feature = "wincon")] // here mostly for documentation purposes
@@ -9,7 +9,7 @@ pub struct WinconStream<S>
where
S: RawStream,
{
- console: anstyle_wincon::Console<S>,
+ raw: S,
// `WinconBytes` is especially large compared to other variants of `AutoStream`, so boxing it
// here so `AutoStream` doesn't have to discard one allocation and create another one when
// calling `AutoStream::lock`
@@ -22,76 +22,132 @@ where
{
/// Only pass printable data to the inner `Write`
#[inline]
- pub fn new(console: anstyle_wincon::Console<S>) -> Self {
+ pub fn new(raw: S) -> Self {
Self {
- console,
- state: Box::default(),
+ raw,
+ state: Default::default(),
}
}
/// Get the wrapped [`RawStream`]
#[inline]
- pub fn into_inner(self) -> anstyle_wincon::Console<S> {
- self.console
+ pub fn into_inner(self) -> S {
+ self.raw
}
#[inline]
- #[cfg(feature = "auto")]
pub fn is_terminal(&self) -> bool {
- // HACK: We can't get the console's stream to check but if there is a console, it likely is
- // a terminal
- true
+ self.raw.is_terminal()
}
}
-#[cfg(feature = "auto")]
-impl<S> is_terminal::IsTerminal for WinconStream<S>
-where
- S: RawStream,
-{
+impl WinconStream<std::io::Stdout> {
+ /// Get exclusive access to the `WinconStream`
+ ///
+ /// Why?
+ /// - Faster performance when writing in a loop
+ /// - Avoid other threads interleaving output with the current thread
+ #[inline]
+ pub fn lock(self) -> WinconStream<std::io::StdoutLock<'static>> {
+ WinconStream {
+ raw: self.raw.lock(),
+ state: self.state,
+ }
+ }
+}
+
+impl WinconStream<std::io::Stderr> {
+ /// Get exclusive access to the `WinconStream`
+ ///
+ /// Why?
+ /// - Faster performance when writing in a loop
+ /// - Avoid other threads interleaving output with the current thread
#[inline]
- fn is_terminal(&self) -> bool {
- self.is_terminal()
+ pub fn lock(self) -> WinconStream<std::io::StderrLock<'static>> {
+ WinconStream {
+ raw: self.raw.lock(),
+ state: self.state,
+ }
}
}
impl<S> std::io::Write for WinconStream<S>
where
- S: RawStream,
+ S: RawStream + AsLockedWrite,
{
+ // Must forward all calls to ensure locking happens appropriately
+ #[inline]
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
- for (style, printable) in self.state.extract_next(buf) {
- let fg = style.get_fg_color().and_then(cap_wincon_color);
- let bg = style.get_bg_color().and_then(cap_wincon_color);
- let written = self.console.write(fg, bg, printable.as_bytes())?;
- let possible = printable.len();
- if possible != written {
- // HACK: Unsupported atm
- break;
- }
- }
- Ok(buf.len())
+ write(&mut self.raw.as_locked_write(), &mut self.state, buf)
}
#[inline]
+ fn write_vectored(&mut self, bufs: &[std::io::IoSlice<'_>]) -> std::io::Result<usize> {
+ let buf = bufs
+ .iter()
+ .find(|b| !b.is_empty())
+ .map(|b| &**b)
+ .unwrap_or(&[][..]);
+ self.write(buf)
+ }
+ // is_write_vectored: nightly only
+ #[inline]
fn flush(&mut self) -> std::io::Result<()> {
- self.console.flush()
+ self.raw.as_locked_write().flush()
+ }
+ #[inline]
+ fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> {
+ write_all(&mut self.raw.as_locked_write(), &mut self.state, buf)
+ }
+ // write_all_vectored: nightly only
+ #[inline]
+ fn write_fmt(&mut self, args: std::fmt::Arguments<'_>) -> std::io::Result<()> {
+ write_fmt(&mut self.raw.as_locked_write(), &mut self.state, args)
}
}
-impl<S> Lockable for WinconStream<S>
-where
- S: RawStream + Lockable,
- <S as Lockable>::Locked: RawStream,
-{
- type Locked = WinconStream<<S as Lockable>::Locked>;
+fn write(raw: &mut dyn RawStream, state: &mut WinconBytes, buf: &[u8]) -> std::io::Result<usize> {
+ for (style, printable) in state.extract_next(buf) {
+ let fg = style.get_fg_color().and_then(cap_wincon_color);
+ let bg = style.get_bg_color().and_then(cap_wincon_color);
+ let written = raw.write_colored(fg, bg, printable.as_bytes())?;
+ let possible = printable.len();
+ if possible != written {
+ // HACK: Unsupported atm
+ break;
+ }
+ }
+ Ok(buf.len())
+}
- #[inline]
- fn lock(self) -> Self::Locked {
- Self::Locked {
- console: self.console.lock(),
- state: self.state,
+fn write_all(raw: &mut dyn RawStream, state: &mut WinconBytes, buf: &[u8]) -> std::io::Result<()> {
+ for (style, printable) in state.extract_next(buf) {
+ let mut buf = printable.as_bytes();
+ let fg = style.get_fg_color().and_then(cap_wincon_color);
+ let bg = style.get_bg_color().and_then(cap_wincon_color);
+ while !buf.is_empty() {
+ match raw.write_colored(fg, bg, buf) {
+ Ok(0) => {
+ return Err(std::io::Error::new(
+ std::io::ErrorKind::WriteZero,
+ "failed to write whole buffer",
+ ));
+ }
+ Ok(n) => buf = &buf[n..],
+ Err(ref e) if e.kind() == std::io::ErrorKind::Interrupted => {}
+ Err(e) => return Err(e),
+ }
}
}
+ Ok(())
+}
+
+fn write_fmt(
+ raw: &mut dyn RawStream,
+ state: &mut WinconBytes,
+ args: std::fmt::Arguments<'_>,
+) -> std::io::Result<()> {
+ let write_all = |buf: &[u8]| write_all(raw, state, buf);
+ crate::fmt::Adapter::new(write_all).write_fmt(args)
}
fn cap_wincon_color(color: anstyle::Color) -> Option<anstyle::AnsiColor> {
@@ -112,10 +168,10 @@ mod test {
#[test]
#[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
fn write_all_no_escapes(s in "\\PC*") {
- let buffer = crate::Buffer::new();
- let mut stream = WinconStream::new(anstyle_wincon::Console::new(buffer).unwrap());
+ let buffer = Vec::new();
+ let mut stream = WinconStream::new(buffer);
stream.write_all(s.as_bytes()).unwrap();
- let buffer = stream.into_inner().into_inner();
+ let buffer = stream.into_inner();
let actual = std::str::from_utf8(buffer.as_ref()).unwrap();
assert_eq!(s, actual);
}
@@ -123,12 +179,12 @@ mod test {
#[test]
#[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
fn write_byte_no_escapes(s in "\\PC*") {
- let buffer = crate::Buffer::new();
- let mut stream = WinconStream::new(anstyle_wincon::Console::new(buffer).unwrap());
+ let buffer = Vec::new();
+ let mut stream = WinconStream::new(buffer);
for byte in s.as_bytes() {
stream.write_all(&[*byte]).unwrap();
}
- let buffer = stream.into_inner().into_inner();
+ let buffer = stream.into_inner();
let actual = std::str::from_utf8(buffer.as_ref()).unwrap();
assert_eq!(s, actual);
}
@@ -136,16 +192,16 @@ mod test {
#[test]
#[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
fn write_all_random(s in any::<Vec<u8>>()) {
- let buffer = crate::Buffer::new();
- let mut stream = WinconStream::new(anstyle_wincon::Console::new(buffer).unwrap());
+ let buffer = Vec::new();
+ let mut stream = WinconStream::new(buffer);
stream.write_all(s.as_slice()).unwrap();
}
#[test]
#[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
fn write_byte_random(s in any::<Vec<u8>>()) {
- let buffer = crate::Buffer::new();
- let mut stream = WinconStream::new(anstyle_wincon::Console::new(buffer).unwrap());
+ let buffer = Vec::new();
+ let mut stream = WinconStream::new(buffer);
for byte in s.as_slice() {
stream.write_all(&[*byte]).unwrap();
}