Since they're both iterators yielding the same item type, you can ask the compiler to use dynamic dispatch:
fn parse_identifier(
mut test_string: impl Iterator<Item = char> + DoubleEndedIterator,
reverse: bool,
) -> Option<String> {
let mut rev_iter;
let test_string: &mut dyn Iterator<Item = char> = if reverse {
rev_iter = test_string.rev();
&mut rev_iter
} else {
&mut test_string
};
for c in test_string {
// Do some parsing logic also slightly impacted by whether reverse is set
}
Some(String::new()) // New String built in the for loop
}
Edit: Removed unnecessary Option