Reputation: 982
I summarised my Rust code as followed:
struct Answer<N> {
ans: N
}
trait Trait {
fn func1<N: AsRef<[u8]>>(&self, param1: &[N]) -> Answer<N>;
}
struct MyStruct {}
impl Trait for MyStruct {
fn func1<N: AsRef<[u8]>>(&self, param1: &[N]) -> Answer<N> {
// This way we prevent bounding additional `Clone` trait on N,
// and not do `let ans = param1[0].clone()`
let ans_ref: &[u8] = param1[0].as_ref();
let mut ans: Vec<u8> = vec![0; ans_ref.len()];
ans[..].clone_from_slice(ans_ref);
Answer { ans }
}
}
fn main() {}
It returns error:
error[E0308]: mismatched types
--> src/main.rs:20:18
|
12 | fn func1<N: AsRef<[u8]>>(&self, param1: &[N]) -> Answer<N> {
| - this type parameter
...
20 | Answer { ans }
| ^^^ expected type parameter `N`, found struct `Vec`
|
= note: expected type parameter `N`
found struct `Vec<u8>`
My question is if I do have Vec<u8>
after some processing inside func1
, is there any way to "typecast" Vec<u8>
back to N: AsRef<[u8]>
, as Vec<u8>
implements AsRef<[u8]>
?
Thanks.
Upvotes: 0
Views: 505
Reputation: 982
@wayofthepie, @Stargateur (saw your suggestion in the rust playground) thanks for both the suggestions; and @wayofthepie thanks for understanding my question.
Eventually my colleague also offers an alternative solution which I think is simpler.
struct Answer<N> {
ans: N,
}
trait Trait {
fn func1<N: AsRef<[u8]> + From<Vec<u8>>>(param1: &[N]) -> Answer<N>;
}
struct MyStruct {}
impl Trait for MyStruct {
fn func1<N: AsRef<[u8]> + From<Vec<u8>>>(param1: &[N]) -> Answer<N> {
// some computation here and get the desired ans in vector of byte.
let ans: Vec<u8> = b"abc".to_vec();
Answer { ans: ans.into() }
}
}
fn main() {}
Adding a From<Vec<u8>>
trait bound here. Eventually ans
inside Answer needs to be in the type of N
, not Vec<u8>
, so we need to convert it to N
.
Upvotes: 0
Reputation: 596
In your example you are saying "I want param1 to be a slice of N
". Someone can pass &[String::from("whatever")]
to func1
and then N
will be of type String
. Your return type is Answer<N>
so in this case N
should be a String
but you are trying to return a Vec<u8>
. The caller is able to choose the type of N
so you can't just return any other type. So to answer your direct question, it's not possible to do this.
In this case to make it work you can change Answer
's ans
field to be Box<dyn AsRef<[u8]>>
, for example:
struct Answer {
ans: Box<dyn AsRef<[u8]>>,
}
trait Trait {
fn func1<N: AsRef<[u8]>>(&self, param1: &[N]) -> Answer;
}
struct MyStruct {}
impl Trait for MyStruct {
fn func1<N: AsRef<[u8]>>(&self, param1: &[N]) -> Answer {
// This way we prevent bounding additional `Clone` trait on N,
// and not do `let ans = param1[0].clone()`
let ans_ref: &[u8] = param1[0].as_ref();
let mut ans: Vec<u8> = vec![0; ans_ref.len()];
ans[..].clone_from_slice(ans_ref);
Answer { ans: Box::new(ans) }
}
}
fn main() {
// we can pass a Vec of String, as String has an AsRef<[u8]> impl
let params = vec![String::from("test")];
let my_struct = MyStruct {};
my_struct.func1(¶ms);
// we can also pass a Vec of Vec
let params = vec![vec![1, 2, 3, 4]];
let my_struct = MyStruct {};
my_struct.func1(¶ms);
}
Upvotes: 1