in starlark/src/values/types/string/fast_string.rs [174:205]
fn convert_str_indices_slow(s: &str, start: NoneOr<i32>, end: NoneOr<i32>) -> Option<StrIndices> {
// Slow version when we need to compute full string length
// because at least one of the indices is negative.
debug_assert!(
matches!(start, NoneOr::Other(start) if start < 0)
|| matches!(end, NoneOr::Other(end) if end < 0)
);
// If both indices are negative, we should have ruled `start > end` case before.
debug_assert!(
matches!((start, end), (NoneOr::Other(start), NoneOr::Other(end))
if start >= 0 || end >= 0 || (start <= end))
|| matches!(start, NoneOr::None)
|| matches!(end, NoneOr::None)
);
let len = len(s);
let (start, end) = convert_indices(len.0 as i32, start, end);
if start > end {
return None;
}
let (start, end) = (CharIndex(start), CharIndex(end));
debug_assert!(end <= len);
let s = if len.0 == s.len() {
// ASCII fast path: if char len is equal to byte len,
// we know the string is ASCII.
unsafe { s.get_unchecked(start.0..end.0) }
} else {
let (_, s) = split_at(s, start).unwrap();
let (s, _) = split_at(s, end - start).unwrap();
s
};
Some(StrIndices { start, haystack: s })
}