Hi, I'm learning rust, and I got stuck with the borrow checker. I start to get a hang on the simpler coding, but in this case when I try to use serde-reflection to create a JSON output explaining "registered" structs I get into problems with the lifetime of the template method T type. It's puzzling as the type really should not need to have any lifetime as I'm not going to pass the instance.
Anyone that happens to know a bit more about the serde-reflection Tracer and how to manage the 'de lifetime in the trace_type method signature?
extern crate serde_json;
use serde_json::json;
use serde_reflection::{Samples, Tracer, TracerConfig};
pub struct TypeRegistry {
registry: Vec<types::Type>,
samples: Samples
}
impl TypeRegistry {
pub fn new() -> TypeRegistry {
TypeRegistry {
registry: vec![],
samples: Samples::new()
}
}
pub fn add<'de, T: serde::Deserialize<'de>>(&mut self) {
let mut tracer = Tracer::new(TracerConfig::default());
tracer.trace_type::<T>(&self.samples);
let registry = tracer.registry().unwrap();
// TODO: add code to serialize into types::Type structure for Array/Object/Enum
}
pub fn to_json_string(&mut self) -> String {
serde_json::to_string(&self.registry).unwrap()
}
}
mod types {
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, Debug)]
pub enum Type {
Array(Array),
Object(Object),
Enum(Enum)
}
// Rest of the structs goes here
}
This is the errors I'm getting:
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/type_registry.rs:20:32
|
20 | tracer.trace_type::<T>(&self.samples);
| ^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 18:5...
--> src/type_registry.rs:18:5
|
18 | pub fn add<'de, T: serde::Deserialize<'de>>(&mut self) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/type_registry.rs:20:32
|
20 | tracer.trace_type::<T>(&self.samples);
| ^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'de` as defined on the method body at 18:16...
--> src/type_registry.rs:18:16
|
18 | pub fn add<'de, T: serde::Deserialize<'de>>(&mut self) {
| ^^^
note: ...so that the types are compatible
--> src/type_registry.rs:20:16
|
20 | tracer.trace_type::<T>(&self.samples);
| ^^^^^^^^^^
= note: expected `serde::Deserialize<'_>`
found `serde::Deserialize<'de>`
error: aborting due to previous error; 3 warnings emitted
When I was using the same trace_type method outside of the struct implementation and with a direct type (without the T template) it works just fine, but I can't seem to find a way to pass the type to the method.
Is there some other better approach to implement a "registry" for some selected struct types so that I can generate a JSON structure describing the types? I was going to use it with JavaScript in a browser to de-serialize binary representations of the structs and I wanted to go even smaller than MessagePack and so on by passing the schemas separately, I also did not want to go into separate languages like Protocol Buffers. My representation is going to look similar to this:
[
{
"alias": "Entities",
"kind": "Array",
"of": "Entity"
},
{
"alias": "Entity",
"kind": "Object",
"properties": [
{
"name": "position",
"alias": "Vector3"
},
{
"name": "rotation",
"alias": "Vector3"
},
{
"name": "scale",
"alias": "Vector3"
}
]
}
]