Skip to main content

serialize_with_units

Function serialize_with_units 

Source
pub fn serialize_with_units<F, R>(f: F) -> R
where 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);