sea_core/primitives/
quantity.rs1use crate::units::Dimension;
2#[cfg(feature = "formatting")]
3use fixed_decimal::FixedDecimal;
4#[cfg(feature = "formatting")]
5use icu_decimal::FixedDecimalFormatter;
6#[cfg(feature = "formatting")]
7use icu_locid::Locale;
8use serde::{Deserialize, Serialize};
9#[cfg(feature = "formatting")]
10use std::str::FromStr;
11
12#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
13pub struct Quantity {
14 pub value: f64,
15 pub unit: String,
16 pub dimension: Dimension,
17}
18
19impl Quantity {
20 pub fn new(value: f64, unit: String, dimension: Dimension) -> Result<Self, String> {
21 if !value.is_finite() {
22 return Err(format!("Quantity value must be finite, got {}", value));
23 }
24 Ok(Self {
25 value,
26 unit,
27 dimension,
28 })
29 }
30}
31
32#[cfg(feature = "formatting")]
33pub struct QuantityFormatter {
34 formatter: FixedDecimalFormatter,
35 #[allow(dead_code)]
37 locale: Locale,
38}
39
40#[cfg(feature = "formatting")]
41impl QuantityFormatter {
42 pub fn new(locale: Locale) -> Self {
43 let formatter = FixedDecimalFormatter::try_new(&(&locale).into(), Default::default())
44 .expect("Failed to create FixedDecimalFormatter");
45 Self { formatter, locale }
46 }
47
48 pub fn format(&self, quantity: &Quantity) -> Result<String, String> {
49 let decimal = FixedDecimal::from_str(&quantity.value.to_string())
52 .map_err(|e| format!("Failed to convert quantity value to decimal: {}", e))?;
53 let formatted_value = self.formatter.format(&decimal).to_string();
54 Ok(format!("{} \"{}\"", formatted_value, quantity.unit))
55 }
56}