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,
    }
}