pub struct Decimal(/* private fields */);Expand description
A rational number with implicit precision, used to represent measurement values and other quantities where the number of significant digits carries meaning.
§Precision is data
FHIR states that the precision of a decimal has significance: a laboratory
result of 0.50 mmol/L claims two significant figures where 0.5 claims
one, and a dose of 1.000 mg is a different assertion from 1.0 mg. This
type therefore stores the lexical form it was given and emits it back
unchanged (spec R2.2).
Backed by f64 — which is what serde_json::Number is by default —
0.50 becomes 0.5, 1.000 becomes 1.0, and
12345678901234567890.5 becomes 1.2345678901234567e+19. This crate
therefore enables serde_json/arbitrary_precision unconditionally, so
a Number carries the lexeme it was parsed from. Cargo features are
additive and cannot be switched off by a dependent, which makes precision
a guarantee rather than a default someone can lose.
The cost is real and worth stating: arbitrary_precision is global to the
compiled binary, so every other crate’s serde_json::Number in the same
build also becomes lexeme-preserving, and Number arithmetic goes through
as_f64(). For a library whose numbers are drug doses and lab results,
that is the correct side to err on.
§Equality is lexical, ordering is numeric
Decimal("1.0") != Decimal("1.00"), because the two say different things
about precision and must survive a round trip distinctly. They compare
equal, because they denote the same quantity:
use fhir::decimal::Decimal;
use std::cmp::Ordering;
let one_dp = Decimal::new("1.0").unwrap();
let two_dp = Decimal::new("1.00").unwrap();
assert_ne!(one_dp, two_dp);
assert_eq!(one_dp.partial_cmp(&two_dp), Some(Ordering::Equal));§JSON
The lexeme survives every serde path this crate uses — from_str,
from_slice, from_reader, from_value, and through the
#[serde(flatten)] that choice elements rely on. A serde_json::Value
built in the same binary is likewise lexeme-preserving, so
json!(0.50) != json!(0.5), and a round-trip test comparing Values can
see precision loss rather than silently tolerating it (spec R13.3).
use fhir::decimal::Decimal;
let parsed: Decimal = ::serde_json::from_str("0.50").unwrap();
assert_eq!(parsed.as_str(), "0.50");
assert_eq!(::serde_json::to_string(&parsed).unwrap(), "0.50");Implementations§
Source§impl Decimal
impl Decimal
Sourcepub fn new(lexeme: impl Into<String>) -> Result<Self, DecimalError>
pub fn new(lexeme: impl Into<String>) -> Result<Self, DecimalError>
A decimal from its lexical form, checked against the FHIR decimal
production -?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?.
§Errors
Returns DecimalError when the text is not a FHIR decimal.
Sourcepub fn as_f64(&self) -> f64
pub fn as_f64(&self) -> f64
The value as an f64, which is lossy by definition — use it for
arithmetic, never for storage or comparison.
Sourcepub fn from_json_number(n: &Number) -> Self
pub fn from_json_number(n: &Number) -> Self
A decimal from an already-parsed serde_json::Number, for callers
holding a serde_json::Value. Lossless, because this crate
guarantees arbitrary_precision.
Trait Implementations§
Source§impl<'de> Deserialize<'de> for Decimal
impl<'de> Deserialize<'de> for Decimal
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for Decimal
Source§impl PartialOrd for Decimal
Numeric ordering over lexically distinct values: 1.0 and 1.00 are the
same quantity even though they are not the same assertion.
impl PartialOrd for Decimal
Numeric ordering over lexically distinct values: 1.0 and 1.00 are the
same quantity even though they are not the same assertion.
impl StructuralPartialEq for Decimal
Source§impl Validate for Decimal
Decimal validates its own lexeme (spec R2.6).
impl Validate for Decimal
Decimal validates its own lexeme (spec R2.6).
One impl for one shared type: were this written per release, compiling two releases together would be a conflicting-impl error.
Source§fn validate(&self) -> Vec<ValidationIssue>
fn validate(&self) -> Vec<ValidationIssue>
Source§fn is_valid(&self) -> bool
fn is_valid(&self) -> bool
true when Validate::validate finds no issues.