I have the following code that works, together with 3 comments that show what struct+impl I'd like to have instead - EventJSON:
pub fn gen(&self, ith: i64) -> Out {
//let mut ev = EventJSON::new(self.num_features);
let mut serializer = serde_json::ser::Serializer::new(Vec::new());
let mut map = serializer.serialize_map(Some(self.num_features)).unwrap();
for f in 0..self.num_features {
let name = self.feature_names.get(f).unwrap();
//ev.insert(name, &ith.to_string());
map.serialize_entry(name, &ith.to_string())
.expect("Can't serialize feature {}.");
}
map.end().expect("Serialization failed.");
//ev.serialize()
String::from_utf8(serializer.into_inner()).expect("Invalid UTF-8.")
}
However, if I try to put such code inside a struct and corresponding impl block I get errors with lifetimes & borrowing in the new()
method:
struct EventJSON {
serializer: Option<serde_json::ser::Serializer<Vec<u8>>>,
// Should be a SerializeMap, but that's not exposed in the API, using this type given by VS Code:
map: Option<serde_json::ser::Compound<'static, Vec<u8>, serde_json::ser::CompactFormatter>>,
}
impl EventJSON {
// Can't figure out how to make this compile!
// I need to have a struct with the map and serializer, for subsequent
// insert() calls, and finally, serialize().
pub fn new(size: usize) -> EventJSON {
let mut serializer = serde_json::ser::Serializer::new(Vec::new());
// This borrows, and at the same time says serializer doesn't live long enough!?
let mut map = serializer.serialize_map(Some(size)).unwrap();
EventJSON {
serializer: Some(serializer), // But I place serializer at the output. Why doesn't it live enough?!
map: Some(map),
}
}
// No compiler errors here.
pub fn insert(&mut self, k: &str, v: &str) {
if let Some(map) = &mut self.map {
map.serialize_entry(k, v);
} else {
panic!("Already serialized! Unusable object!");
}
}
// And no compiler errors here.
pub fn serialize(&mut self) -> String {
if let Some(serializer) = self.serializer.take() {
String::from_utf8(serializer.into_inner()).expect("Invalid UTF-8.")
} else {
panic!("Already serialized! Unusable object!");
}
}
}
however I get these errors:
error[E0597]: `serializer` does not live long enough
--> src/lib.rs:17:23
|
17 | let mut map = serializer.serialize_map(Some(size)).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| borrowed value does not live long enough
| argument requires that `serializer` is borrowed for `'static`
...
23 | }
| - `serializer` dropped here while still borrowed
error[E0505]: cannot move out of `serializer` because it is borrowed
--> src/lib.rs:20:30
|
17 | let mut map = serializer.serialize_map(Some(size)).unwrap();
| ------------------------------------
| |
| borrow of `serializer` occurs here
| argument requires that `serializer` is borrowed for `'static`
...
20 | serializer: Some(serializer),
| ^^^^^^^^^^ move out of `serializer` occurs here
how can one go around the borrow-checker to make that EventJSON::new()
work? I spent a lot of time and am clueless.
Here's the full code if it helps learn-rust/rest-injector @ github. If you do cargo run
you should get these same errors.