pub fn serialize_with_units<F, R>(f: F) -> Rwhere
F: FnOnce() -> R,Expand description
A wrapper around a serialization function / closure which enables serialization with units.
§Overview
By default, a quantity or angle is often serialized as its raw value in base SI
units, which is very efficient. Sometimes, it might be useful to store a value
together with its units. If a struct field uses serialize_quantity,
serialize_opt_quantity, serialize_angle or serialize_opt_angle
for serialization and this wrapper is applied to the actual serialization
function, then the units are stored together with the raw value in a string.
§Multithreaded serialization
This function is a thin wrapper around the passed in serialization function
which just sets SERIALIZE_WITH_UNITS to true, then calls the passed in
function, stores the result, then sets SERIALIZE_WITH_UNITS back to false
and finally returns the result. Since SERIALIZE_WITH_UNITS is a thread-local
variable, it will be set to its default value false if a new thread is created
inside the passed function. Hence, a multithreaded serializer needs to adjust
the value of SERIALIZE_WITH_UNITS in each thread it creates - which is why
SERIALIZE_WITH_UNITS is exposed in the first place.
§Examples
use serde::{Serialize};
use uom::si::{f64::Length, length::{millimeter, kilometer}};
use dyn_quantity::*;
use indoc::indoc;
#[derive(Serialize, Debug)]
struct Quantities {
#[serde(serialize_with = "serialize_quantity")]
length: Length,
#[serde(serialize_with = "serialize_opt_quantity")]
opt_length: Option<Length>,
#[serde(serialize_with = "serialize_angle")]
angle: f64,
#[serde(serialize_with = "serialize_opt_angle")]
opt_angle: Option<f64>,
}
let quantities = Quantities {
length: Length::new::<millimeter>(1.0),
opt_length: Some(Length::new::<kilometer>(1.0)),
angle: 1.0,
opt_angle: Some(2.0),
};
// Without units (standard serialization)
let expected = indoc! {"
---
length: 0.001
opt_length: 1000.0
angle: 1.0
opt_angle: 2.0
"};
let actual = serde_yaml::to_string(&quantities).expect("serialization succeeds");
assert_eq!(expected, actual);
// With units
let expected = indoc! {"
---
length: 0.001 m
opt_length: 1000 m
angle: 1 rad
opt_angle: 2 rad
"};
let actual = serialize_with_units(||{serde_yaml::to_string(&quantities)}).expect("serialization succeeds");
assert_eq!(expected, actual);