Skip to content

Commit ae72278

Browse files
taiki-ecramertj
authored andcommitted
Add io::Window::set
1 parent 46560aa commit ae72278

File tree

2 files changed

+50
-31
lines changed

2 files changed

+50
-31
lines changed

futures-util/src/io/window.rs

Lines changed: 24 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::ops;
1+
use std::ops::{Bound, Range, RangeBounds};
22

33
/// A owned window around an underlying buffer.
44
///
@@ -20,7 +20,7 @@ use std::ops;
2020
#[derive(Debug)]
2121
pub struct Window<T> {
2222
inner: T,
23-
range: ops::Range<usize>,
23+
range: Range<usize>,
2424
}
2525

2626
impl<T: AsRef<[u8]>> Window<T> {
@@ -29,8 +29,8 @@ impl<T: AsRef<[u8]>> Window<T> {
2929
///
3030
/// Further methods can be called on the returned `Window<T>` to alter the
3131
/// window into the data provided.
32-
pub fn new(t: T) -> Window<T> {
33-
Window {
32+
pub fn new(t: T) -> Self {
33+
Self {
3434
range: 0..t.as_ref().len(),
3535
inner: t,
3636
}
@@ -65,43 +65,36 @@ impl<T: AsRef<[u8]>> Window<T> {
6565
self.range.end
6666
}
6767

68-
/// Changes the starting index of this window to the index specified.
68+
/// Changes the range of this window to the range specified.
6969
///
7070
/// Returns the windows back to chain multiple calls to this method.
7171
///
7272
/// # Panics
7373
///
74-
/// This method will panic if `start` is out of bounds for the underlying
75-
/// slice or if it comes after the `end` configured in this window.
76-
pub fn set_start(&mut self, start: usize) -> &mut Window<T> {
77-
assert!(start <= self.inner.as_ref().len());
78-
assert!(start <= self.range.end);
79-
self.range.start = start;
80-
self
81-
}
82-
83-
/// Changes the end index of this window to the index specified.
84-
///
85-
/// Returns the windows back to chain multiple calls to this method.
74+
/// This method will panic if `range` is out of bounds for the underlying
75+
/// slice or if [`start_bound()`] of `range` comes after the [`end_bound()`].
8676
///
87-
/// # Panics
88-
///
89-
/// This method will panic if `end` is out of bounds for the underlying
90-
/// slice or if it comes before the `start` configured in this window.
91-
pub fn set_end(&mut self, end: usize) -> &mut Window<T> {
77+
/// [`start_bound()`]: std::ops::RangeBounds::start_bound
78+
/// [`end_bound()`]: std::ops::RangeBounds::end_bound
79+
pub fn set<R: RangeBounds<usize>>(&mut self, range: R) -> &mut Self {
80+
let start = match range.start_bound() {
81+
Bound::Included(n) => *n,
82+
Bound::Excluded(n) => *n + 1,
83+
Bound::Unbounded => 0,
84+
};
85+
let end = match range.end_bound() {
86+
Bound::Included(n) => *n + 1,
87+
Bound::Excluded(n) => *n,
88+
Bound::Unbounded => self.inner.as_ref().len(),
89+
};
90+
9291
assert!(end <= self.inner.as_ref().len());
93-
assert!(self.range.start <= end);
92+
assert!(start <= end);
93+
94+
self.range.start = start;
9495
self.range.end = end;
9596
self
9697
}
97-
98-
// TODO: how about a generic set() method along the lines of:
99-
//
100-
// buffer.set(..3)
101-
// .set(0..2)
102-
// .set(4..)
103-
//
104-
// etc.
10598
}
10699

107100
impl<T: AsRef<[u8]>> AsRef<[u8]> for Window<T> {

futures/tests/io_window.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use futures::io::Window;
2+
3+
#[test]
4+
fn set() {
5+
let mut buffer = Window::new(&[1, 2, 3]);
6+
buffer.set(..3)
7+
.set(3..3)
8+
.set(3..=2) // == 3..3
9+
.set(0..2);
10+
11+
assert_eq!(buffer.as_ref(), &[1, 2]);
12+
}
13+
14+
#[test]
15+
#[should_panic]
16+
fn set_panic_out_of_bounds() {
17+
let mut buffer = Window::new(&[1, 2, 3]);
18+
buffer.set(2..4);
19+
}
20+
21+
#[test]
22+
#[should_panic]
23+
fn set_panic_start_is_greater_than_end() {
24+
let mut buffer = Window::new(&[1, 2, 3]);
25+
buffer.set(3..2);
26+
}

0 commit comments

Comments
 (0)