pub struct Amount {
pub number: Decimal,
pub currency: Currency,
}Expand description
An amount is a quantity paired with a currency.
§Examples
use rustledger_core::Amount;
use rust_decimal_macros::dec;
let amount = Amount::new(dec!(100.00), "USD");
assert_eq!(amount.number, dec!(100.00));
assert_eq!(amount.currency, "USD");
// Arithmetic operations
let other = Amount::new(dec!(50.00), "USD");
let sum = &amount + &other;
assert_eq!(sum.number, dec!(150.00));Fields§
§number: DecimalThe decimal quantity
currency: CurrencyThe currency code (e.g., “USD”, “EUR”, “AAPL”)
Implementations§
Source§impl Amount
impl Amount
Sourcepub fn zero(currency: impl Into<Currency>) -> Self
pub fn zero(currency: impl Into<Currency>) -> Self
Create a zero amount with the given currency.
Sourcepub const fn is_positive(&self) -> bool
pub const fn is_positive(&self) -> bool
Check if the amount is positive.
Sourcepub const fn is_negative(&self) -> bool
pub const fn is_negative(&self) -> bool
Check if the amount is negative.
Sourcepub fn inferred_tolerance(&self) -> Decimal
pub fn inferred_tolerance(&self) -> Decimal
Calculate the inferred tolerance for this amount.
Tolerance is 0.5 * 10^(-scale), so:
- scale 0 (integer) → tolerance 0.5
- scale 1 → tolerance 0.05
- scale 2 → tolerance 0.005
Sourcepub fn is_near_zero(&self, tolerance: Decimal) -> bool
pub fn is_near_zero(&self, tolerance: Decimal) -> bool
Check if this amount is near zero within tolerance.
Sourcepub fn is_near(&self, other: &Self, tolerance: Decimal) -> bool
pub fn is_near(&self, other: &Self, tolerance: Decimal) -> bool
Check if this amount is near another amount within tolerance.
Returns false if currencies don’t match.
Sourcepub fn eq_with_tolerance(&self, other: &Self, tolerance: Decimal) -> bool
pub fn eq_with_tolerance(&self, other: &Self, tolerance: Decimal) -> bool
Check if this amount equals another within the given tolerance.
This is an alias for is_near() with a more explicit name for equality comparison.
Returns false if currencies don’t match.
§Example
use rustledger_core::Amount;
use rust_decimal_macros::dec;
let a = Amount::new(dec!(100.00), "USD");
let b = Amount::new(dec!(100.004), "USD");
// Within tolerance of 0.005
assert!(a.eq_with_tolerance(&b, dec!(0.005)));
// Outside tolerance of 0.003
assert!(!a.eq_with_tolerance(&b, dec!(0.003)));Sourcepub fn eq_auto_tolerance(&self, other: &Self) -> bool
pub fn eq_auto_tolerance(&self, other: &Self) -> bool
Check if this amount equals another using auto-inferred tolerance.
The tolerance is computed as the maximum of both amounts’ inferred tolerances, which is based on their decimal precision (scale).
§Example
use rustledger_core::Amount;
use rust_decimal_macros::dec;
let a = Amount::new(dec!(100.00), "USD"); // scale 2 -> tolerance 0.005
let b = Amount::new(dec!(100.004), "USD"); // scale 3 -> tolerance 0.0005
// Uses max tolerance (0.005), so these are equal
assert!(a.eq_auto_tolerance(&b));Trait Implementations§
Source§impl AddAssign<&Amount> for Amount
impl AddAssign<&Amount> for Amount
Source§fn add_assign(&mut self, other: &Self)
fn add_assign(&mut self, other: &Self)
+= operation. Read moreSource§impl Archive for Amount
impl Archive for Amount
Source§type Archived = ArchivedAmount
type Archived = ArchivedAmount
Source§type Resolver = AmountResolver
type Resolver = AmountResolver
Source§fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>)
fn resolve(&self, resolver: Self::Resolver, out: Place<Self::Archived>)
Source§const COPY_OPTIMIZATION: CopyOptimization<Self> = _
const COPY_OPTIMIZATION: CopyOptimization<Self> = _
serialize. Read moreSource§impl<'de> Deserialize<'de> for Amount
impl<'de> Deserialize<'de> for Amount
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>,
Source§impl<__D: Fallible + ?Sized> Deserialize<Amount, __D> for Archived<Amount>where
AsDecimal: ArchiveWith<Decimal> + DeserializeWith<<AsDecimal as ArchiveWith<Decimal>>::Archived, Decimal, __D>,
Currency: Archive,
<Currency as Archive>::Archived: Deserialize<Currency, __D>,
impl<__D: Fallible + ?Sized> Deserialize<Amount, __D> for Archived<Amount>where
AsDecimal: ArchiveWith<Decimal> + DeserializeWith<<AsDecimal as ArchiveWith<Decimal>>::Archived, Decimal, __D>,
Currency: Archive,
<Currency as Archive>::Archived: Deserialize<Currency, __D>,
impl Eq for Amount
Source§impl From<Amount> for IncompleteAmount
impl From<Amount> for IncompleteAmount
Source§impl FromStr for Amount
impl FromStr for Amount
Source§fn from_str(s: &str) -> Result<Self, Self::Err>
fn from_str(s: &str) -> Result<Self, Self::Err>
Parse <number> <currency> — the exact shape produced by
fmt::Display. Round-trip is lossless:
Amount::from_str(&amt.to_string()) == Ok(amt).
Strict by design — there is intentionally no Python beancount equivalent of this parser, so we set the wire contract. Accepts:
- Any whitespace (one or more spaces/tabs) between the number and currency.
- Leading or trailing whitespace around the whole string.
- Negative numbers (
-100 USD). - Fractional decimals (
100.50 USD).
Rejects (typed error rather than silent fallback):
- Currency-first form (
"USD 100"). - Number-only (
"100") or currency-only ("USD"). - Scientific notation (
"1e2 USD"). - Thousands separators (
"1,000 USD"). - Lowercase commodity (
"100 usd"). - Empty / whitespace-only strings.
§Errors
Returns AmountParseError describing which axis of the
expected shape was violated; see AmountParseErrorReason.
Source§type Err = AmountParseError
type Err = AmountParseError
Source§impl ShiftSpans for Amount
impl ShiftSpans for Amount
impl StructuralPartialEq for Amount
Auto Trait Implementations§
impl Freeze for Amount
impl RefUnwindSafe for Amount
impl Send for Amount
impl Sync for Amount
impl Unpin for Amount
impl UnsafeUnpin for Amount
impl UnwindSafe for Amount
Blanket Implementations§
Source§impl<T> ArchivePointee for T
impl<T> ArchivePointee for T
Source§type ArchivedMetadata = ()
type ArchivedMetadata = ()
Source§fn pointer_metadata(
_: &<T as ArchivePointee>::ArchivedMetadata,
) -> <T as Pointee>::Metadata
fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata
Source§impl<T> ArchiveUnsized for Twhere
T: Archive,
impl<T> ArchiveUnsized for Twhere
T: Archive,
Source§type Archived = <T as Archive>::Archived
type Archived = <T as Archive>::Archived
Archive, it may be
unsized. Read moreSource§fn archived_metadata(
&self,
) -> <<T as ArchiveUnsized>::Archived as ArchivePointee>::ArchivedMetadata
fn archived_metadata( &self, ) -> <<T as ArchiveUnsized>::Archived as ArchivePointee>::ArchivedMetadata
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,
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<T> LayoutRaw for T
impl<T> LayoutRaw for T
Source§fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
Source§impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
Source§unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
Source§fn resolve_niched(out: Place<NichedOption<T, N1>>)
fn resolve_niched(out: Place<NichedOption<T, N1>>)
out indicating that a T is niched.