2017-10-09 5 views
4

Ich versuche ein Merkmal zu schreiben, das mit einer Datenbank arbeitet und etwas darstellt, das gespeichert werden kann. Zu diesem Zweck erbt das Merkmal von anderen, die das Merkmal serde::Deserialize enthält.Wie erstellen Sie eine generische Funktion in Rust mit einer Eigenschaft, die eine Lebensdauer erfordert?

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] } 
} 

Als nächstes Ich versuche, diese Daten unter Verwendung eines generischen Funktion zu schreiben:

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()) 
} 

Allerdings bin ich die folgende Fehlermeldung erhalten:

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.

Wie würde ich das lösen, möglicherweise alles vermeiden?

Antwort

3

Sie haben Storable mit einem generischen Parameter definiert, in diesem Fall eine Lebensdauer. Das bedeutet, dass der generische Parameter in der gesamten Anwendung propagiert werden muss:

Sie können auch entscheiden, die generische spezifische zu machen. Dies kann mit einem konkreten Typ oder einer Lebensdauer (z. B. 'static) oder durch Hinterlegen eines Merkmalsobjekts geschehen.

Serde hat auch a comprehensive page about deserializer lifetimes. Es erwähnt, dass Sie DeserializeOwned auch verwenden können.

trait Storable: Serialize + DeserializeOwned { /* ... */ } 

Sie können das gleiche Konzept wie DeserializeOwned für die eigene Eigenschaft als auch verwenden:

trait StorableOwned: for<'de> Storable<'de> { } 

fn put<'de, S: StorableOwned>(obj: &'de S) -> Result<(), String> { 
4

Sie haben die 'de Lebensdauer an der falschen Stelle - Sie benötigen es, um das Argument Storable, nicht die Lebensdauer der Referenz obj angeben.

Statt

fn to_json<'de, S: Storable>(obj: &'de S) -> String { 

Verwendung

fn to_json<'de, S: Storable<'de>>(obj: &S) -> String { 

Playground.

Die Lebensdauer von obj spielt hier keine Rolle, da Sie keine davon abgeleiteten Werte zurückgeben. Alles, was Sie beweisen müssen, ist, dass SStorable<'de> für einige Lebenszeit implementiert 'de.

Wenn Sie die 'de insgesamt beseitigen möchten, sollten Sie DeserializeOwned verwenden, wie the other answer beschreibt.

Verwandte Themen