Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor split_at/split_to #663

Merged
merged 8 commits into from
Feb 23, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 24 additions & 26 deletions src/bytes_mut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,8 +317,10 @@ impl BytesMut {
);
unsafe {
let mut other = self.shallow_clone();
other.set_start(at);
self.set_end(at);
// SAFETY: We've checked that `at` <= `self.capacity()` above.
other.advance_unchecked(at);
self.cap = at;
self.len = cmp::min(self.len, at);
other
}
}
Expand Down Expand Up @@ -391,8 +393,11 @@ impl BytesMut {

unsafe {
let mut other = self.shallow_clone();
other.set_end(at);
self.set_start(at);
// SAFETY: We've checked that `at` <= `self.len()` and we know that `self.len()` <=
// `self.capacity()`.
self.advance_unchecked(at);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very minor nitpick, but this is unsafe code so I think it might be worth applying. In split_off, you call advance_unchecked first then update cap and len. You reverse it here. Would you mind keeping them the same?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, thanks for pointing it out! Made things a little more consistent in b971743. Let me know if that isn't what you meant.

other.cap = at;
other.len = at;
other
}
}
Expand Down Expand Up @@ -851,14 +856,19 @@ impl BytesMut {
unsafe { slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len) }
}

unsafe fn set_start(&mut self, start: usize) {
/// Advance the buffer without bounds checking.
///
/// # SAFETY
///
/// The caller must ensure that `count` <= `self.cap`.
unsafe fn advance_unchecked(&mut self, count: usize) {
// Setting the start to 0 is a no-op, so return early if this is the
// case.
if start == 0 {
if count == 0 {
return;
}

debug_assert!(start <= self.cap, "internal: set_start out of bounds");
debug_assert!(count <= self.cap, "internal: set_start out of bounds");

let kind = self.kind();

Expand All @@ -867,7 +877,7 @@ impl BytesMut {
// complicated. First, we have to track how far ahead the
// "start" of the byte buffer from the beginning of the vec. We
// also have to ensure that we don't exceed the maximum shift.
let pos = self.get_vec_pos() + start;
let pos = self.get_vec_pos() + count;

if pos <= MAX_VEC_POS {
self.set_vec_pos(pos);
Expand All @@ -883,23 +893,9 @@ impl BytesMut {
// Updating the start of the view is setting `ptr` to point to the
// new start and updating the `len` field to reflect the new length
// of the view.
self.ptr = vptr(self.ptr.as_ptr().add(start));

if self.len >= start {
self.len -= start;
} else {
self.len = 0;
}

self.cap -= start;
}

unsafe fn set_end(&mut self, end: usize) {
debug_assert_eq!(self.kind(), KIND_ARC);
assert!(end <= self.cap, "set_end out of bounds");

self.cap = end;
self.len = cmp::min(self.len, end);
self.ptr = vptr(self.ptr.as_ptr().add(count));
self.len = self.len.checked_sub(count).unwrap_or(0);
self.cap -= count;
}

fn try_unsplit(&mut self, other: BytesMut) -> Result<(), BytesMut> {
Expand Down Expand Up @@ -1069,7 +1065,9 @@ impl Buf for BytesMut {
self.remaining(),
);
unsafe {
self.set_start(cnt);
// SAFETY: We've checked that `cnt` <= `self.remaining()` and we know that
// `self.remaining()` <= `self.cap`.
self.advance_unchecked(cnt);
}
}

Expand Down