diff options
| author | Thalia Archibald <thalia@archibald.dev> | 2025-04-12 06:18:53 -0700 | 
|---|---|---|
| committer | Thalia Archibald <thalia@archibald.dev> | 2025-05-01 15:18:15 -0700 | 
| commit | 28deaa6e0e7993f963b3bb44bb235c7682ce0cf3 (patch) | |
| tree | 8001060a0da0b273e6729e2bc16924d3b38aea54 /library/std/src/env.rs | |
| parent | 0c33fe2c3d3eecadd17a84b110bb067288a64f1c (diff) | |
| download | rust-28deaa6e0e7993f963b3bb44bb235c7682ce0cf3.tar.gz rust-28deaa6e0e7993f963b3bb44bb235c7682ce0cf3.zip | |
Delegate to inner `vec::IntoIter` from `env::ArgsOs`
Delegate from `std::env::ArgsOs` to the methods of the inner platform-specific iterators, when it would be more efficient than just using the default methods of its own impl. Most platforms use `vec::IntoIter` as the inner type, so prioritize delegating to the methods it provides. `std::env::Args` is implemented atop `std::env::ArgsOs` and performs UTF-8 validation with a panic for invalid data. This is a visible effect which users certainly rely on, so we can't skip any arguments. Any further iterator methods would skip some elements, so no change is needed for that type. Add `#[inline]` for any methods which simply wrap the inner iterator.
Diffstat (limited to 'library/std/src/env.rs')
| -rw-r--r-- | library/std/src/env.rs | 73 | 
1 files changed, 72 insertions, 1 deletions
| diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 1593969e114..ce2dc795220 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -12,9 +12,11 @@ use crate::error::Error; use crate::ffi::{OsStr, OsString}; +use crate::num::NonZero; +use crate::ops::Try; use crate::path::{Path, PathBuf}; use crate::sys::{env as env_imp, os as os_imp}; -use crate::{fmt, io, sys}; +use crate::{array, fmt, io, sys}; /// Returns the current working directory as a [`PathBuf`]. /// @@ -872,19 +874,36 @@ impl !Sync for Args {} #[stable(feature = "env", since = "1.0.0")] impl Iterator for Args { type Item = String; + fn next(&mut self) -> Option<String> { self.inner.next().map(|s| s.into_string().unwrap()) } + + #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() } + + // Methods which skip args cannot simply delegate to the inner iterator, + // because `env::args` states that we will "panic during iteration if any + // argument to the process is not valid Unicode". + // + // This offers two possible interpretations: + // - a skipped argument is never encountered "during iteration" + // - even a skipped argument is encountered "during iteration" + // + // As a panic can be observed, we err towards validating even skipped + // arguments for now, though this is not explicitly promised by the API. } #[stable(feature = "env", since = "1.0.0")] impl ExactSizeIterator for Args { + #[inline] fn len(&self) -> usize { self.inner.len() } + + #[inline] fn is_empty(&self) -> bool { self.inner.is_empty() } @@ -914,19 +933,65 @@ impl !Sync for ArgsOs {} #[stable(feature = "env", since = "1.0.0")] impl Iterator for ArgsOs { type Item = OsString; + + #[inline] fn next(&mut self) -> Option<OsString> { self.inner.next() } + + #[inline] + fn next_chunk<const N: usize>( + &mut self, + ) -> Result<[OsString; N], array::IntoIter<OsString, N>> { + self.inner.next_chunk() + } + + #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() } + + #[inline] + fn count(self) -> usize { + self.inner.len() + } + + #[inline] + fn last(self) -> Option<OsString> { + self.inner.last() + } + + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> { + self.inner.advance_by(n) + } + + #[inline] + fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R + where + F: FnMut(B, Self::Item) -> R, + R: Try<Output = B>, + { + self.inner.try_fold(init, f) + } + + #[inline] + fn fold<B, F>(self, init: B, f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + self.inner.fold(init, f) + } } #[stable(feature = "env", since = "1.0.0")] impl ExactSizeIterator for ArgsOs { + #[inline] fn len(&self) -> usize { self.inner.len() } + + #[inline] fn is_empty(&self) -> bool { self.inner.is_empty() } @@ -934,9 +999,15 @@ impl ExactSizeIterator for ArgsOs { #[stable(feature = "env_iterators", since = "1.12.0")] impl DoubleEndedIterator for ArgsOs { + #[inline] fn next_back(&mut self) -> Option<OsString> { self.inner.next_back() } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> { + self.inner.advance_back_by(n) + } } #[stable(feature = "std_debug", since = "1.16.0")] | 
