2018-01-06 05:03:30 +08:00
|
|
|
use itertools::Itertools;
|
2019-06-21 09:53:24 +08:00
|
|
|
use std::ops::Bound::{Excluded, Included, Unbounded};
|
|
|
|
use std::ops::RangeBounds;
|
2018-01-06 05:03:30 +08:00
|
|
|
|
|
|
|
/// Take a range of lines from a string.
|
2019-06-21 09:53:24 +08:00
|
|
|
pub fn take_lines<R: RangeBounds<usize>>(s: &str, range: R) -> String {
|
|
|
|
let start = match range.start_bound() {
|
|
|
|
Excluded(&n) => n + 1,
|
|
|
|
Included(&n) => n,
|
|
|
|
Unbounded => 0,
|
|
|
|
};
|
2018-01-06 05:03:30 +08:00
|
|
|
let mut lines = s.lines().skip(start);
|
2019-06-21 09:53:24 +08:00
|
|
|
match range.end_bound() {
|
|
|
|
Excluded(end) => lines.take(end.saturating_sub(start)).join("\n"),
|
|
|
|
Included(end) => lines.take((end + 1).saturating_sub(start)).join("\n"),
|
|
|
|
Unbounded => lines.join("\n"),
|
2018-01-06 05:03:30 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::take_lines;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn take_lines_test() {
|
|
|
|
let s = "Lorem\nipsum\ndolor\nsit\namet";
|
2018-01-31 18:57:47 +08:00
|
|
|
assert_eq!(take_lines(s, 1..3), "ipsum\ndolor");
|
2018-01-06 05:03:30 +08:00
|
|
|
assert_eq!(take_lines(s, 3..), "sit\namet");
|
|
|
|
assert_eq!(take_lines(s, ..3), "Lorem\nipsum\ndolor");
|
|
|
|
assert_eq!(take_lines(s, ..), s);
|
2018-01-31 18:57:47 +08:00
|
|
|
// corner cases
|
|
|
|
assert_eq!(take_lines(s, 4..3), "");
|
|
|
|
assert_eq!(take_lines(s, ..100), s);
|
2018-01-06 05:03:30 +08:00
|
|
|
}
|
|
|
|
}
|