Merge pull request #962 from integer32llc/rangebounds

Use stdlib RangeBounds
This commit is contained in:
Eric Huss 2019-06-20 20:01:52 -07:00 committed by GitHub
commit 7c33ac800c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 13 additions and 51 deletions

View File

@ -9,7 +9,7 @@ use pulldown_cmark::{html, CowStr, Event, Options, Parser, Tag};
use std::borrow::Cow; use std::borrow::Cow;
pub use self::string::{take_lines, RangeArgument}; pub use self::string::take_lines;
/// Replaces multiple consecutive whitespace characters with a single space character. /// Replaces multiple consecutive whitespace characters with a single space character.
pub fn collapse_whitespace(text: &str) -> Cow<'_, str> { pub fn collapse_whitespace(text: &str) -> Cow<'_, str> {

View File

@ -1,57 +1,19 @@
use itertools::Itertools; use itertools::Itertools;
use std::ops::{Range, RangeFrom, RangeFull, RangeTo}; use std::ops::Bound::{Excluded, Included, Unbounded};
use std::ops::RangeBounds;
// This trait is already contained in the standard lib, however it is unstable.
// TODO: Remove when the `collections_range` feature stabilises
// (https://github.com/rust-lang/rust/issues/30877)
pub trait RangeArgument<T: ?Sized> {
fn start(&self) -> Option<&T>;
fn end(&self) -> Option<&T>;
}
impl<T: ?Sized> RangeArgument<T> for RangeFull {
fn start(&self) -> Option<&T> {
None
}
fn end(&self) -> Option<&T> {
None
}
}
impl<T> RangeArgument<T> for RangeFrom<T> {
fn start(&self) -> Option<&T> {
Some(&self.start)
}
fn end(&self) -> Option<&T> {
None
}
}
impl<T> RangeArgument<T> for RangeTo<T> {
fn start(&self) -> Option<&T> {
None
}
fn end(&self) -> Option<&T> {
Some(&self.end)
}
}
impl<T> RangeArgument<T> for Range<T> {
fn start(&self) -> Option<&T> {
Some(&self.start)
}
fn end(&self) -> Option<&T> {
Some(&self.end)
}
}
/// Take a range of lines from a string. /// Take a range of lines from a string.
pub fn take_lines<R: RangeArgument<usize>>(s: &str, range: R) -> String { pub fn take_lines<R: RangeBounds<usize>>(s: &str, range: R) -> String {
let start = *range.start().unwrap_or(&0); let start = match range.start_bound() {
Excluded(&n) => n + 1,
Included(&n) => n,
Unbounded => 0,
};
let mut lines = s.lines().skip(start); let mut lines = s.lines().skip(start);
match range.end() { match range.end_bound() {
Some(&end) => lines.take(end.saturating_sub(start)).join("\n"), Excluded(end) => lines.take(end.saturating_sub(start)).join("\n"),
None => lines.join("\n"), Included(end) => lines.take((end + 1).saturating_sub(start)).join("\n"),
Unbounded => lines.join("\n"),
} }
} }