Search code examples
rustserde

Serializing data structure to an existing array using serde


I am trying to serialize a bunch of enum Action {} to a file which is expected to contain a RON array of Actions :

Action(..)
Action(..)

But for convenient deserialization I would prefer it in this format Vec<Action>:

[
  Action(..),
  Action(..),
]

The problem I am facing is I can use ron::ser::to_string to serialize a single Action item but how do I add it to a file already containing an array or if it's a blank file, create an array and then insert an Action ?

As the comments have pointed out, I could overwrite the entire file on each Action append but ideally I am allowing for the possibility of this file being too large for memory.


Solution

  • I'd like to challenge one assumption of yours: Is deserialization of a list […,…,…] into a Vec<Action> really that much more convenient? Here's how you deserialize a plain agglutination of Action(…) Action(…) into a Vec<Action>:

    std::iter::from_fn({
        let mut de = ron::Deserializer::from_str(INPUT)?;
        move || {
            de.end()
                .is_err()
                .then_some(Action::deserialize::<_>(&mut de))
        }
    })
    .collect::<Result<Vec<_>, _>>()
    

    Rust explorer

    If that's a little bit too much magic for your taste, you can go iteratively:

    let mut res = Vec::new();
    let mut de = ron::Deserializer::from_str(INPUT)?;
    loop {
        let act = Action::deserialize::<_>(&mut de)?;
        res.push(act);
        if de.end().is_ok() {
            break;
        }
    }
    

    Serialization/saving is then a plain appending write (adding a newline is optional).

    This goes into the JSONL direction @cafce25 suggested, but without the limitation that your RON must be newline-free. That being said, if you do go for RONL, it has the added benefit that if eventually one of your writes fails and you get a broken record, you can still parse all others. Which to go for depends on how often your file is viewed by humans vs how often it is appended.