pub struct EstimatedUsd(/* private fields */);Expand description
Dollars derived from published rates. Not the bill.
There is deliberately no ActualUsd alongside this: a client that never sees an
invoice cannot produce an actual. And there is deliberately no way to get an
f64 out (COST-2) — no From<EstimatedUsd> for f64, no Into, no Deref, no
as_f64. The Python original could only omit __float__ and hope; the cheapest
way to launder an estimate into a bill is f"${float(x):.2f}", and the Rust
equivalent does not compile.
EstimatedUsd::amount returns a Decimal, which is one visible step and
keeps the type name at the call site. A caller who genuinely needs a float
reaches for Decimal::to_f64, which is two named steps and a Option — and
which is a decision a reviewer can see.
Add is implemented only against itself, so summing an amount
that might be Amount::Unpriced is a type error rather than a silent zero.
§The coercion does not compile (COST-2)
The requirement is about an impl that is absent, so the check has to be a
program that fails to build. compile_fail doctests are that check, and they are
run by cargo test like any other:
The error code is pinned on each one, because a bare compile_fail passes for
any build failure — including a typo in the test itself, which would leave the
guard green while measuring nothing.
let estimate = EstimatedUsd::new(dec!(1.23));
// No `From<EstimatedUsd> for f64`, so no `Into` either. This is the line the
// Python client could only ask a reader not to write.
let laundered: f64 = estimate.into();let estimate = EstimatedUsd::new(dec!(1.23));
// No `Deref` and no public field: the figure comes out through `amount()`, which
// names the type at the call site.
let bare = *estimate;let estimate = EstimatedUsd::new(dec!(1.23));
let unknown = Amount::unpriced("no rate is published");
// `Add` is implemented only against `EstimatedUsd`, so the Python's runtime
// `TypeError` from `NotImplemented` is a compile error here (COST-4).
let wrong = estimate + unknown;Implementations§
Source§impl EstimatedUsd
impl EstimatedUsd
Sourcepub const ZERO: EstimatedUsd
pub const ZERO: EstimatedUsd
Zero dollars, which is a legitimate priced figure — a zero-length hold, a
zero-cycle comparison — and is not the same claim as Amount::Unpriced.
Sourcepub fn new(amount: Decimal) -> EstimatedUsd
pub fn new(amount: Decimal) -> EstimatedUsd
An estimate from a decimal figure already in the money path.
Takes a Decimal and not an f64, so this constructor cannot be the second
float boundary: gb_decimal and seconds_of are the only two, which is
what makes COST-6’s “exactly once” checkable by reading them.
Sourcepub fn amount(self) -> Decimal
pub fn amount(self) -> Decimal
The figure, in decimal.
The one visible step out. Deliberately not Into<Decimal>: an explicit call
keeps EstimatedUsd in the reader’s view at the point the label is dropped.
Sourcepub fn amount_string(self) -> String
pub fn amount_string(self) -> String
The figure rendered at display precision, without the estimate label.
For a caller assembling its own sentence. fmt::Display is what carries
the label, and it is what a report renders through.
Sourcepub fn parse(text: &str) -> Result<EstimatedUsd, Error>
pub fn parse(text: &str) -> Result<EstimatedUsd, Error>
A dollar figure from a caller’s decimal string — a budget, typically.
A string and not an f64, so this is not a third float boundary beside
gb_decimal and seconds_of: the caller typed a decimal, and parsing
the text they typed keeps 0.1 meaning a tenth rather than the nearest
binary float. Negative is refused here rather than compared later, because
every total this could be compared against is non-negative and a negative
budget can only ever be a sign error the comparison would launder into
“always breached”.
Trait Implementations§
Source§impl Add for EstimatedUsd
impl Add for EstimatedUsd
Source§fn add(self, other: EstimatedUsd) -> EstimatedUsd
fn add(self, other: EstimatedUsd) -> EstimatedUsd
Only an estimate adds to an estimate.
There is no Add<Amount> and no Add<Unpriced>, so the Python’s
NotImplemented — a runtime TypeError — becomes a compile error. This is
the last line of defence for COST-4: even a consumer that ignores
CostReport::is_complete cannot sum an unknown into a dollar figure.
Source§type Output = EstimatedUsd
type Output = EstimatedUsd
+ operator.Source§impl Clone for EstimatedUsd
impl Clone for EstimatedUsd
Source§fn clone(&self) -> EstimatedUsd
fn clone(&self) -> EstimatedUsd
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreimpl Copy for EstimatedUsd
Source§impl Debug for EstimatedUsd
impl Debug for EstimatedUsd
Source§impl Display for EstimatedUsd
A figure copied out of a terminal loses its docstring, so the label travels in
Display rather than sitting in the type name alone.
impl Display for EstimatedUsd
A figure copied out of a terminal loses its docstring, so the label travels in
Display rather than sitting in the type name alone.
impl Eq for EstimatedUsd
Source§impl Ord for EstimatedUsd
impl Ord for EstimatedUsd
Source§fn cmp(&self, other: &EstimatedUsd) -> Ordering
fn cmp(&self, other: &EstimatedUsd) -> Ordering
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 PartialEq for EstimatedUsd
impl PartialEq for EstimatedUsd
Source§impl PartialOrd for EstimatedUsd
impl PartialOrd for EstimatedUsd
impl StructuralPartialEq for EstimatedUsd
Source§impl Sum for EstimatedUsd
impl Sum for EstimatedUsd
Source§fn sum<I>(iter: I) -> EstimatedUsdwhere
I: Iterator<Item = EstimatedUsd>,
fn sum<I>(iter: I) -> EstimatedUsdwhere
I: Iterator<Item = EstimatedUsd>,
Self from the elements by “summing up”
the items.Auto Trait Implementations§
impl Freeze for EstimatedUsd
impl RefUnwindSafe for EstimatedUsd
impl Send for EstimatedUsd
impl Sync for EstimatedUsd
impl Unpin for EstimatedUsd
impl UnsafeUnpin for EstimatedUsd
impl UnwindSafe for EstimatedUsd
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
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.Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more