Reputation: 226
I have a struct that involves some data stored in a slice. I would like to let the user decide whether that slice is a reference or owned, stored on the stack or the heap, etc, all I care about is that it's some sort of slice somewhere.
pub struct A<T: WhatGoesHere?>(pub T);
A(vec![1, 2, 3]); // Mutable on heap
A([1, 2, 3]); // Mutable on stack
A(&[1, 2, 3]); // Immutable
At first I tried the deref trait, T: Deref<Target=[u32]>
, and for impl's that require mutability I would bound by DerefMut
. That works for the vec, but it doesn't like the other two.
Then I read about the Borrow
trait, T: Borrow<[u32]>
. Seemed like a good fit and I could bound on BorrowMut
for mutability. This one likes the vec and the array, but the slice can't be borrowed as an array. I thought maybe I should be using Borrow<&[u32]>
but I can't figure out the lifetimes.
Finally, I tried T: AsRef<[u32]>
. This works for all 3! But for mutability AsMut
doesn't require AsRef
(why?) so I have to bound on AsRef<[u32]> + AsMut<[u32]>
. That feels weird and I have to trust that those two references are to the same slice and the user didn't do something weird. It doesn't quite feel like it's the right thing to do.
What's the right bound for T
? If AsRef
is indeed the right thing should I be worried about AsMut
referencing a different slice or am I being too paranoid?
Upvotes: 2
Views: 565
Reputation: 755
To answer your question directly: AsRef
and AsMut
are the reasonable choice and you don't even need to bind to both for the case of AsMut
.
However, depending on what you want to achieve with this slice, you might even want to consider using Read
, Write
, or their async equivalents (AsyncRead
, AsyncWrite
).
Upvotes: 1