I have a struct like this:
#[derive(Serialize, Deserialize)]
struct Thing {
pub small_header: Header,
pub big_body: Body,
}
I want to serialize this Thing
to send over the network. I already have a Body
available but I can't move it (imagine I am doing something with it, and every now and then I receive a command to temporarily stop what I'm doing and send over whatever data I have now) and I can't copy it (it's too big, possibly hundreds of megabytes).
So I'd like Serde to just borrow the one I have for serializing it, since it shouldn't need to be moved into a struct for that. If I rewrite Thing
to take a reference, I obviously can't derive Deserialize
!
The workaround I've been using is just using an Arc<Body>
in my code, so that I can work with the body in my normal logic and when I need to serialize it, I can just do a cheap clone and put the Arc<Body>
into the struct for serialization. During deserialization Serde will make a new Arc
with a refcount of 1.
This still involves scattering Arc
all over my code, which isn't great, not to mention the unnecessary (though minor) runtime cost. What is the correct solution for this use case?
The funny thing is that if I didn't have to send a header, then this would be a non-issue since I could serialize by reference and deserialize by value, but the presence of a header makes this impossible. I feel like I'm missing something about how Serde borrows data here...
You could use a Cow
, which will be Cow::Borrowed
when serializing and will deserialize as Cow::Owned
when deserializing.
use std::borrow::Cow;
#[derive(Serialize, Deserialize)]
struct Thing<'a> {
small_header: Header,
big_body: Cow<'a, Body>,
}
Alternatively, you could serialize and deserialize as two independent data structures.
#[derive(Serialize)]
struct SerializeThing<'a> {
small_header: Header,
big_body: &'a Body,
}
#[derive(Deserialize)]
struct DeserializeThing {
small_header: Header,
big_body: Body,
}