-
Notifications
You must be signed in to change notification settings - Fork 115
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
impl Into<Vec<u8>> for EasyBuf (cf. #120) #162
Conversation
Hm, I'm not sure if project owners will require this, but I'd prefer this method be non-allocating if possible (i.e. if underlying buffer is not referenced anywhere). You should be able to achieve that using |
Hm, on the other hand it also requires checking |
Yep, that was my reasoning. If performance/memory is an issue, it's best to stick with EasyBuf. AFAICT, it could only be non-allocating only works iff there are no other references AND start == 0 AND end == 0. This might also make performance more unpredictable. |
Perhaps this could be implemented via |
Thanks for the feedback and pointers. I added assertions to verify if the code is indeed allocating/non-allocating. I would appreciate an evaluation if comparing the pointers is safe/correct/good practice in this context. |
@manuel-woelker even if it isn't useful here for some reason, you should learn the repace hack or it might be easier to get the idea by looking at swap. I.e. replacing (or swapping) a vector with an empty one is cheap and can be used to move the vector off the mutable pointer. |
@manuel-woelker oh I think somethingn like this would work: mem::replace(&mut *self.get_mut(), Vec::new()) |
@tailhook @alexcrichton Thanks for the neat trick! So when rustc says "cannot move out of borrowed content", you actually can, as long as you "put something back". I had to truncate the Vec to length, since Compare: #[test]
fn easybuf_get_mut_sliced() {
let vec: Vec<u8> = (0u8..10u8).collect();
let mut buf: EasyBuf = vec.into();
buf.split_off(3);
println!("Length: {}", buf.len()); // Length: 3
{
buf.get_mut(); // Not doing anything with this
}
println!("Length: {}", buf.len()); // Length: 10 !!!
}
#[test]
fn easybuf_get_mut_sliced_allocating() {
let vec: Vec<u8> = (0u8..10u8).collect();
let mut buf: EasyBuf = vec.into();
buf.split_off(3);
// Clone to make shared
let clone = buf.clone();
println!("Shared Length: {}", buf.len()); // Shared Length: 3
{
buf.get_mut(); // Not doing anything with this
}
println!("Shared Length: {}", buf.len()); // Shared Length: 3
} |
@manuel-woelker oh I think you've discovered a bug in The snippet I believe should work, but a bug today means it doesn't. For example this fails today (but it should pass) let vec: Vec<u8> = (0u8..10u8).collect();
let mut buf: EasyBuf = vec.into();
buf.split_off(9);
buf.drain_to(3);
assert_eq!(*buf.get_mut(), [3, 4, 5, 6, 7, 8]); (adapted from your own test case) I believe, though, that this can be fixed with a call to Once that's fixed I think you should be able to use the |
@alexcrichton Okay, got it working, and added tests for Also, is there a practical way to make all EasyBuf tests run for both a shared and an exclusive instance? |
You could hold onto one of the return values of split_off and drain_to but it may be overkill for this situation. In any case yeah want to squash and I'll merge? |
dfeeb61
to
676917e
Compare
676917e
to
b4cd223
Compare
Ok, I rebased and split the PR into the bugfix and the original impl for Thanks for the mentoring, much appreciated! |
Thanks! |
Feedback welcome!