Skip to main content

ggplot_rs/
format.rs

1//! Public value and label formatting helpers.
2//!
3//! [`format_value`] renders a single data [`Value`] the way ggplot-rs shows it
4//! in hover tooltips (rounded numbers, calendar dates for datetimes). The
5//! `label_*` axis/legend formatters from [`crate::scale::format`] are
6//! re-exported here so hosts can format numbers consistently with the plot.
7
8use crate::data::Value;
9
10pub use crate::scale::format::{
11    label_bytes, label_comma, label_currency, label_dollar, label_number, label_ordinal,
12    label_percent, label_scientific, label_si, LabelFormatter,
13};
14
15/// Format one data value for display (tooltips, data labels):
16///
17/// - strings as-is, booleans as `true`/`false`, `NA` as the empty string;
18/// - numbers rounded to three decimals with trailing zeros dropped
19///   (`3.14159` → `"3.142"`, `2.0` → `"2"`);
20/// - datetimes (epoch seconds) as `YYYY-MM-DD[ HH:MM:SS]` UTC.
21///
22/// ```
23/// use ggplot_rs::data::Value;
24/// use ggplot_rs::format::format_value;
25/// assert_eq!(format_value(&Value::Float(3.14159)), "3.142");
26/// assert_eq!(format_value(&Value::DateTime(86_400)), "1970-01-02");
27/// assert_eq!(format_value(&Value::Na), "");
28/// ```
29pub fn format_value(v: &Value) -> String {
30    match v {
31        Value::Str(s) => s.clone(),
32        Value::Bool(b) => b.to_string(),
33        Value::Na => String::new(),
34        // A datetime axis reads as a calendar date, not raw epoch seconds.
35        Value::DateTime(secs) => crate::data::format_epoch_secs(*secs),
36        _ => v
37            .as_f64()
38            .map(|f| format!("{}", (f * 1000.0).round() / 1000.0))
39            .unwrap_or_default(),
40    }
41}
42
43#[cfg(test)]
44mod tests {
45    use super::*;
46
47    #[test]
48    fn formats_each_variant() {
49        assert_eq!(format_value(&Value::Str("a<b".into())), "a<b");
50        assert_eq!(format_value(&Value::Bool(true)), "true");
51        assert_eq!(format_value(&Value::Integer(-42)), "-42");
52        assert_eq!(format_value(&Value::Float(2.0)), "2");
53        assert_eq!(format_value(&Value::Float(0.12345)), "0.123");
54        assert_eq!(format_value(&Value::DateTime(3_661)), "1970-01-01 01:01:01");
55        assert_eq!(format_value(&Value::Na), "");
56    }
57}