I am trying to write a trait which works with a database and represents something which can be stored. To do this, the trait inherits from others, which includes the serde::Deserialize
trait.
trait Storable<'de>: Serialize + Deserialize<'de> {
fn global_id() -> &'static [u8];
fn instance_id(&self) -> Vec<u8>;
}
struct Example {
a: u8,
b: u8
}
impl<'de> Storable<'de> for Example {
fn global_id() -> &'static [u8] { b"p" }
fn instance_id(&self) -> Vec<u8> { vec![self.a, self.b] }
}
Next, I am trying to write this data using a generic function:
pub fn put<'de, S: Storable>(&mut self, obj: &'de S) -> Result<(), String> {
...
let value = bincode::serialize(obj, bincode::Infinite);
...
db.put(key, value).map_err(|e| e.to_string())
}
However, I am getting the following error:
error[E0106]: missing lifetime specifier
--> src/database.rs:180:24
|
180 | pub fn put<'de, S: Storable>(&mut self, obj: &'de S) -> Result<(), String> {
| ^^^^^^^^ expected lifetime parameter
Minimal example on the playground.
How would I resolve this, possibly avoid it altogether?
You have the
'de
lifetime in the wrong place -- you need it to specify the argument toStorable
, not the lifetime of the referenceobj
.Instead of
use
Playground.
The lifetime of
obj
doesn't actually matter here, because you're not returning any values derived from it. All you need to prove is thatS
implementsStorable<'de>
for some lifetime'de
.If you want to eliminate the
'de
altogether, you should useDeserializeOwned
, as the other answer describes.You have defined
Storable
with a generic parameter, in this case a lifetime. That means that the generic parameter has to be propagated throughout the entire application:You can also decide to make the generic specific. That can be done with a concrete type or lifetime (e.g.
'static
), or by putting it behind a trait object.Serde also has a comprehensive page about deserializer lifetimes. It mentions that you can choose to use
DeserializeOwned
as well.You can use the same concept as
DeserializeOwned
for your own trait as well: