Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possible `deserialize_into()` method? #252

Closed
frankmcsherry opened this issue Oct 14, 2018 · 2 comments
Closed

Possible `deserialize_into()` method? #252

frankmcsherry opened this issue Oct 14, 2018 · 2 comments

Comments

@frankmcsherry
Copy link

@frankmcsherry frankmcsherry commented Oct 14, 2018

I'm new here, and perhaps this is old news, but I'd love to have a method

    fn deserialize_into<'a,T>(bytes: &[u8], target: T) -> Result<T>
    where 
        T: Deserialize<'a>;

with the point being that any allocations already present in target can be re-used. So, if I am deserializing a Vec<String> I might reasonably have a Vec<String> already on hand (perhaps I've just previously deserialized and processed such a thing) with a bunch of allocations ready to be populated.

This is a bit like Clone's method clone_from(&mut self, other: &T) which has some decent performance properties. Also, it is a bit analogous to Recycler (edit: specifically the recreate method) which hasn't been used in forever, but which gives about a 2x performance bump in Vec<Vec<String>> cloning.

Anyhow, maybe this is a non-goal, but it's something I'm looking at right now as a clear perf speedbump in some code (I have owned T types being dropped because I don't know how to hand the resources to bincode to use for deserialization). Also very possible that there is a clever pattern that lets bincode do this and I don't know it, in which case I apologize!

@dtolnay
Copy link
Collaborator

@dtolnay dtolnay commented Oct 14, 2018

This is waiting on a bincode release, but you could implement that function today as:

// [dependencies]
// bincode = { git = "https://github.com/TyOverby/bincode" }

use serde::de::{Deserialize, DeserializeSeed, Deserializer};

fn deserialize_into<'de, T>(bytes: &'de [u8], mut target: T) -> bincode::Result<T>
where 
    T: Deserialize<'de>,
{
    struct InPlace<'a, T>(&'a mut T);

    impl<'a, 'de, T> DeserializeSeed<'de> for InPlace<'a, T>
    where
        T: Deserialize<'de>,
    {
        type Value = ();

        fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
        where
            D: Deserializer<'de>,
        {
            T::deserialize_in_place(deserializer, self.0)
        }
    }

    bincode::config().deserialize_seed(InPlace(&mut target), bytes)?;
    Ok(target)
}
@frankmcsherry
Copy link
Author

@frankmcsherry frankmcsherry commented Oct 14, 2018

Thank you! Let me get my head around this and I'll re-open if I can't figure out what is going on. :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.