Swift has the ability to create an iterator out of a sequence by calling the makeIterator method provided by the Sequence protocol.
To my knowledge there is no way of getting a peek of the next element in the sequence without advancing the iterator. But since this was exactly what I needed, I had to come up with my own solution. I started by creating a new peekable iterator struct that would take in an already existing iterator. Below is an example for an Array<Int>.Iterator.
This would be sufficient to use, but at some point I had a function that took an IteratorProtocol as input. The internal iterator I was using (Array<Int>.Iterator in the example above) did implement the IteratorProtocol so my first instinct was to make the property public and pass it to the function. But exposing the internals because I needed to pass them to a function felt wrong. A much better way was to make the peekable iterator conform to IteratorProtocol instead.
At some point I implemented a second peekable iterator over a different iterator type and realised that the implementation did not change apart from the element and iterator type. This meant I could have one generic peekable iterator and use that for both types instead.
As a bonus I also added a PeekableProtocol that contained the peek method definition and made the PeekableIterator conform to it.
To make it easier to create a peekable iterator from an existing iterator I added an extension that would allow me to call peekable() on any iterator and return a new PeekableIterator instance.
However, I removed this extension as soon as I realised that PeekableIterator also implements IteratorProtocol, which meant I could call peekable on a PeekableIterator itself.
A less confusing way was to provide an extension over a Sequence instead, since that protocol requires a makeIterator method implementation.