I am trying to serialize a bunch of enum Action {}
to a file which is expected to contain a RON array of Action
s :
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.
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<_>, _>>()
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.