I have a struct S { a: &'static str, b: &'static str }
I want to serialize it as a + b, so S { a: "aaa", b: "bbb" } should be serialized as "aaabbb"
how do I achieve this without allocations?
I have a struct S { a: &'static str, b: &'static str }
I want to serialize it as a + b, so S { a: "aaa", b: "bbb" } should be serialized as "aaabbb"
how do I achieve this without allocations?
Yes, well mostly:
you'd utilize the collect_str
method which avoids allocation of an intermediate String
for those serializers that can support that, while those that don't would fall back to creating an allocation.
could you provide an example? collect_str
still expects just one value that is Display
Probably easiest to use format_args
, e.g.
use serde::{Serialize, Serializer};
struct S {
a: &'static str,
b: &'static str,
}
impl Serialize for S {
fn serialize<Ser>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error>
where
Ser: Serializer,
{
serializer.collect_str(&format_args!("{a}{b}", a = self.a, b = self.b))
}
}
fn main() {
let s = S { a: "aaa", b: "bbb" };
match serde_json::to_string(&s) {
Ok(json) => println!("Serialized: {}", json),
Err(e) => println!("Error during serialization: {}", e),
}
}
I'm not immediately sure if writing a manual Display
implementation has performance benefits over this though; the potential to avoid allocations is the same either way though. Edit: Yes, there's probably some very minor overhead in using format_args
because of an extra layer of dynamic calls to get to the bottom of the write_str
calls. Assuming you're wanting to avoid the allocation because the strings might be large, if that's the case, then the overhead becomes negligible.
Using a manual Display
implementation could look like this:
impl Serialize for S {
fn serialize<Ser>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error>
where
Ser: Serializer,
{
struct Wrap<'a>(&'a S);
impl std::fmt::Display for Wrap<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
f.write_str(self.0.a)?;
f.write_str(self.0.b)
}
}
serializer.collect_str(&Wrap(self))
}
}
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.