pub struct Number(/* private fields */);Expand description
An OCPI number: an exact decimal.
Numbers in OCPI are formatted as JSON numbers. Unless mentioned otherwise, numbers use 4 decimals and a sufficiently large amount of digits.
§Why not f64
Every price, VAT percentage, energy volume and tax amount in OCPI ends up on an invoice. A
binary float cannot represent 0.10 and cannot add a column of cents without drift, so every
arithmetic operation in this crate — the whole tariffs engine included —
runs on rust_decimal::Decimal. f32/f64 are denied by lint in the modules where money
lives, and no public field of any OCPI object in this crate is a float.
§The JSON boundary
The spec requires these values to be JSON numbers, not strings. serde_json represents a
fractional JSON number as an f64 unless its arbitrary_precision feature is enabled — a
feature that changes serde_json::Value globally for every crate in the build, so
ocpi-kit does not impose it. The boundary therefore behaves as follows:
- Integral values pass through exactly, as JSON integers.
- Fractional values with at most 15 significant decimal digits — which covers OCPI’s entire
domain of prices, energies and percentages with room to spare — pass through exactly,
because the shortest decimal that round-trips an
f64is the original decimal. - Beyond that, a round-trip rounds to the nearest
f64.Number::json_round_tripssays whether a given value is affected andValidate::validatereports it asViolationCode::Imprecise, so this can never happen silently.
A peer that sends a number as a JSON string ("0.25") is tolerated on input and parsed
exactly; output is always a JSON number.
use ocpi_kit::types::Number;
let price: Number = "0.2500".parse().unwrap();
assert_eq!(serde_json::to_string(&price).unwrap(), "0.25");
let vat: Number = serde_json::from_str("20").unwrap();
assert_eq!(serde_json::to_string(&vat).unwrap(), "20");Spec: 2.3.0 §types_number_type
Implementations§
Source§impl Number
impl Number
Sourcepub fn json_round_trips(self) -> bool
pub fn json_round_trips(self) -> bool
Whether this value survives a JSON round-trip unchanged.
See the type documentation. false only for values with more
significant digits than an f64 can carry.
Sourcepub fn is_negative(self) -> bool
pub fn is_negative(self) -> bool
Whether the value is strictly negative.
Trait Implementations§
impl Copy for Number
Source§impl<'de> Deserialize<'de> for Number
impl<'de> Deserialize<'de> for Number
Source§fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error>
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error>
impl Eq for Number
Source§impl JsonSchema for Number
Available on crate feature schema only.
impl JsonSchema for Number
schema only.Source§fn json_schema(_g: &mut SchemaGenerator) -> Schema
fn json_schema(_g: &mut SchemaGenerator) -> Schema
Source§fn inline_schema() -> bool
fn inline_schema() -> bool
$ref keyword. Read moreSource§impl Ord for Number
impl Ord for Number
1.21.0 (const: unstable) · Source§fn max(self, other: Self) -> Selfwhere
Self: Sized,
fn max(self, other: Self) -> Selfwhere
Self: Sized,
1.21.0 (const: unstable) · Source§fn min(self, other: Self) -> Selfwhere
Self: Sized,
fn min(self, other: Self) -> Selfwhere
Self: Sized,
Source§impl PartialOrd for Number
impl PartialOrd for Number
impl StructuralPartialEq for Number
Auto Trait Implementations§
impl Freeze for Number
impl RefUnwindSafe for Number
impl Send for Number
impl Sync for Number
impl Unpin for Number
impl UnsafeUnpin for Number
impl UnwindSafe for Number
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Comparable<K> for Q
impl<Q, K> Comparable<K> for Q
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.