use std::ops::ControlFlow; /// Finds the first occurrence of either `a` or `b` in `s`. /// /// Returns the index of the first occurrence of either `a` or `b` in `s`, /// as well as a boolean indicating whether the first occurrence was `a`. /// (If it was `b`, the boolean is `false`.) fn find_one_of(s: &str, a: &str, b: &str) -> Option<(usize, bool)> { let control_flow = s.bytes() .enumerate() .try_fold((a.as_bytes(), b.as_bytes()), |(xs, ys), (i, c)| { match (xs, ys) { ([], _) => ControlFlow::Break((i - a.len(), true)), (_, []) => ControlFlow::Break((i - b.len(), false)), ([x, xs @ ..], [y, ys @ ..]) => match (*x == c, *y == c) { (true, true) => ControlFlow::Continue((xs, ys)), (true, false) => ControlFlow::Continue((xs, b.as_bytes())), (false, true) => ControlFlow::Continue((a.as_bytes(), ys)), (false, false) => ControlFlow::Continue((a.as_bytes(), b.as_bytes())), }, } }); match control_flow { ControlFlow::Break((i, a)) => Some((i, a)), ControlFlow::Continue(([], _)) => Some((s.len() - a.len(), true)), ControlFlow::Continue((_, [])) => Some((s.len() - b.len(), false)), ControlFlow::Continue(_) => None, } }