Skip to content

Instantly share code, notes, and snippets.

@vidhanio
Last active October 8, 2023 00:32
Show Gist options
  • Save vidhanio/0ef8ff6a1648c7d65acedadc21d7321c to your computer and use it in GitHub Desktop.
Save vidhanio/0ef8ff6a1648c7d65acedadc21d7321c to your computer and use it in GitHub Desktop.
find the first occurrence of either of two substrings.
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,
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment