Peek trait for peekable iterators · Issue #176 · rust-lang/libs-team (original) (raw)

Proposal

Problem statement

Some iterator types can support peeking à la Peekable. Sometimes, peeking is required for such an iterator, but methods specific to the original iterator’s type must be called as well. In these cases, creating a Peekable does not allow doing the latter.

Motivation, use-cases

The following code for ps9 is meant to parse a ‘decoration’ object at the start of a word, returning the parsed object as well as the remainder of the string.

impl Decoration { /// Parses a [Decoration] at the beginning of the string, /// returning it and the remainder of the input. /// /// This operation always succeeds as it can always parse an /// empty decoration at the beginning. /// /// # Examples /// /// /// let word = "*#feris"; /// let (decoration, remainder) = Decoration::parse(word); /// assert_eq!(decoration.premarker, PreMarker::Carþ); /// assert!(decoration.has_nef); /// assert!(!decoration.has_sen); /// assert_eq!(remainder, "feris"); /// pub fn parse(s: &str) -> (Decoration, &str) { let mut s = s.chars().peekable(); let has_nef = s.next_if_eq(&'*').is_some(); let premarker_char = s.next_if(|c| "#+×@".contains(c)); let premarker = match premarker_char { Some('#') => PreMarker::Carþ, Some('+') => match s.next_if_eq(&'') { Some(_) => PreMarker::Njor, None => PreMarker::Tor, }, Some('×') => PreMarker::Njor, Some('@') => PreMarker::Es, _ => PreMarker::None, }; let has_sen = s.next_if_eq(&'&').is_some(); ( Decoration { premarker, has_nef, has_sen, }, // ERROR: no method named as_str found for struct Peekable in the current scope // method not found in Peekable<Chars<'_>> s.as_str(), ) } }

Solution sketches

We could add a Peek: Iterator trait that would provide the same methods as Peekable. This trait would be implemented by Peekable as well as any other iterator that can support peeking operations, such as std::str::Chars, std::slice::Iter, and std::ops::Range.

This trait could be added to all types that are Iterator + Clone, but this would incur unnecessary overhead for types such as std::vec::IntoIter which can peek at O(1) time but needs O(n) time to clone.

What happens now?

This issue is part of the libs-api team API change proposal process. Once this issue is filed the libs-api team will review open proposals in its weekly meeting. You should receive feedback within a week or two.