I have another serde question. Is there a mechanism within serde to allow some kind of custom context data to be made available to serializers and deserializers through the serde state? Preferably mutable, in the case of deserializers.
The below code shows what I'm trying to do, but it uses hideous things like mutable statics and unsafe. There's gotta be a better way...
Is there a sanctioned way to embed a custom type into a Serializer?
I found this thread advising a parallel set of structs. This would work and it's definitely better than the static / unsafe approach. But it's a lot of typing.
Thank you all for the nudges in the right direction.
extern crate serde;
extern crate serde_json;
use crate::serde_json::json;
pub struct Context {
name_table : Option<Vec<String>>
}
struct IndexType(usize);
impl serde::ser::Serialize for IndexType {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: serde::ser::Serializer {
unsafe {
if let Some(name_table) = &MY_CONTEXT.name_table {
serializer.serialize_str(name_table[self.0].as_str())
} else {
serializer.serialize_u64(self.0 as u64)
}
} //end unsafe
}
}
static mut MY_CONTEXT : Context = Context{name_table : None};
fn main() {
//Init the context
unsafe {
MY_CONTEXT.name_table = Some(vec!["zero".to_string(), "one".to_string()]);
} // end unsafe
let my_index = IndexType(1);
let my_json = json!(my_index);
println!("{}", serde_json::to_string_pretty(&my_json).unwrap());
}
Thank you for the reply. The parallel "WithContext" struct was essentially what the other thread created by @ilammy was saying.
Perhaps I need to level-up my macro writing chops so I can write #derive[(SerDeWithContext)] or something once, and then derive it for all my structs that follow this pattern.
Also I still haven't wrapped my head around how the parallel struct "WithContext" approach works for deserialize. Does it need to work in two passes, first deserializing the input into a hierarchy of objects that track the structure of the input stream, and then translating that structure of objects into a the ultimate form?
I'm not convinced this would actually compile. The string slice case is problematic: How does one deserialize to a borrow? Where is the owner? And where is the data stored?