-
Notifications
You must be signed in to change notification settings - Fork 226
Add truncate and retain(_mut) to Deque #617
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
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good.
I'd love to have tests covering all possible branches in the truncate
method though.
src/deque.rs
Outdated
// Stage 1: Check if all values can be retained. | ||
while cur < len { | ||
// Safety: `cur` must be under the deque's total length as per the loop condition | ||
if !f(unsafe { self.get_unchecked_mut(cur) }) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why deviate from std
's implementation and use unsafe here? I expect the bound check introduced in the safe path to be optimized out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair! My reasoning came from the fact that Deque doesn't impl ops::IndexMut
(and most things in heapless seem to not, I'm unsure how intentional of a choice that is still). I like to avoid unwrap
s in unsafe
blocks for a few reasons; expect
is fine, but I also felt it was unnecessarily explicit? I mean, std::VecDeque
's IndexMut
impl comes out to be the same as what I have now changed it to, a get_mut()
with an except()
.
So maybe another PR adding those ops
impls would be in order? Unless this was an explicit choice to not allow indexing like that, I'm still new to heapless as a whole 😅.
src/deque.rs
Outdated
// Based on alloc's own VecDeque test | ||
// | ||
// https://github.com/rust-lang/rust/blob/fa3155a644dd62e865825087b403646be01d4cef/library/alloc/src/collections/vec_deque/tests.rs#L1086 | ||
// | ||
// Tests that each element's destructor is called when being truncated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please test the following cases:
- Truncating an empty deque
- Truncating an continuous deque
- leaving it unchanged
- leaving it empty
- leaving it half-empty
- Truncating a discontinuous deque
- leaving it unchanged
- leaving it discontinuous but dropping some elements
- leaving it continuous (i.e. all the back is dropped)
- reducing the front slice
- not touching the front slice
- leaving it empty
Essentially ensure that all branches of the truncate
function are exercized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added more tests, thanks for the suggestions! I was surprised there wasn't more in the std, maybe I just didn't look deep enough.
Let me know if any should be adjusted.
Might open another PR for Index(Mut) to closer fit the std impl...
Howdy!
As I was working on simplifying a crate's logic to fit in a
no_std
context, I found thatDeque
didn't have some of the methods I was using fromalloc
's implementation.So I took the time to port them over! Apologies if the comments in
truncate
are a bit much, it was mostly to help me wrap my head around how the data structure itself used its private variables.If you spot an error in my logic or if I missed something, please let me know!