Then I have two structs that implement this trait; the first struct needs a simple reference to 'value', on the contrary, the other one requires a mutable reference and I am not able to implement it.
For example, my two structs could be:
struct SimpleRef{}
impl MyTrait for SimpleRef {
type REF = String;
fn do_something(value: &Self::REF) -> () {
//use value
}
}
struct MutateRef{}
impl MyTrait for MutateRef {
type REF = String; // HERE I NEED TO DECLARE THAT THE TYPE REF IS MUTABLE.
// I tried with AsRef, AsMut, BorrowMut without luck
fn do_something(value: &Self::REF) -> () {
// MUTATE value
}
}
Is there a way to define the type REF in MutateRef to get the desired behaviour? So I can call the SimpleRef methods with a '&' and when I use MutateRef I have to pass '& mut' instead?
thank you very much!
Your second solution is exactly what I was looking for; anyway, to be able to compile your code I was forced to add an explicit lifetime to the structs:
trait MyTrait {
type Data;
type Ref: Deref<Target=Data>;
fn do_something(value: Self::Ref);
}
struct MyStruct<'a> {}
impl <'a> MyTrait for MyStruct<'a> {
type Data = [u8];
type Ref = &'a Self::Date;
fn do_something(value: Self::Ref) {}
}
struct MyStructMutable<'a> {}
impl <'a> MyTrait for MyStructMutable<'a> {
type Data = [u8];
type Ref = &'a mut Self::Date;
fn do_something(value: Self::Ref) {}
}
Am I doing it correctly?
I love your solution but I am still not able to understand why and how it works
Oh right, I forgot about the lifetime attached the reference. In any case, you want to attach the lifetime to the trait, not the struct. Your example would transform into:
use std::ops::Deref;
trait MyTrait<'a> {
type Data: ?Sized;
type Ref: Deref<Target=Self::Data> + 'a;
fn do_something(value: Self::Ref);
}
struct MyStruct;
impl<'a> MyTrait<'a> for MyStruct {
type Data = [u8];
type Ref = &'a Self::Data;
fn do_something(value: Self::Ref) {}
}
struct MyStructMutable;
impl<'a> MyTrait<'a> for MyStructMutable {
type Data = [u8];
type Ref = &'a mut Self::Data;
fn do_something(value: Self::Ref) {}
}
A few major changes:
type Data is now ?Sized because [u8] is not Sized
MyTrait now has a lifetime attached
MyStruct and MyStructMutable now don't have a trait attached because it would have nowhere to be used in the struct, considering they're unit structs.