pub struct Decimal { /* private fields */ }Expand description
An arbitrary precision decimal number stored as sortable bytes.
The internal byte representation is designed to be lexicographically sortable, meaning that comparing the bytes directly yields the same result as comparing the numerical values. This enables efficient range queries in databases.
§Storage Efficiency
The encoding uses:
- 1 byte for the sign
- Variable bytes for the exponent (typically 1-3 bytes)
- 4 bits per decimal digit (BCD encoding, 2 digits per byte)
Implementations§
Source§impl Decimal
impl Decimal
Sourcepub fn with_precision_scale(
s: &str,
precision: Option<u32>,
scale: Option<i32>,
) -> Result<Self, DecimalError>
pub fn with_precision_scale( s: &str, precision: Option<u32>, scale: Option<i32>, ) -> Result<Self, DecimalError>
Creates a new Decimal with precision and scale constraints.
Values that exceed the constraints are truncated/rounded to fit. This is compatible with SQL NUMERIC(precision, scale) semantics.
precision: Maximum total number of significant digits (None = unlimited)scale: Digits after decimal point; negative values round to left of decimal
§PostgreSQL Compatibility
Supports negative scale (rounds to powers of 10):
scale = -3rounds to nearest 1000NUMERIC(2, -3)allows values like -99000 to 99000
§Examples
use decimal_bytes::Decimal;
// NUMERIC(5, 2) - up to 5 digits total, 2 after decimal
let d = Decimal::with_precision_scale("123.456", Some(5), Some(2)).unwrap();
assert_eq!(d.to_string(), "123.46"); // Rounded to 2 decimal places
// NUMERIC(2, -3) - rounds to nearest 1000, max 2 significant digits
let d = Decimal::with_precision_scale("12345", Some(2), Some(-3)).unwrap();
assert_eq!(d.to_string(), "12000"); // Rounded to nearest 1000Sourcepub fn from_bytes(bytes: &[u8]) -> Result<Self, DecimalError>
pub fn from_bytes(bytes: &[u8]) -> Result<Self, DecimalError>
Creates a Decimal from raw bytes.
The bytes must be a valid encoding produced by as_bytes().
Returns an error if the bytes are invalid.
§Examples
use decimal_bytes::Decimal;
use std::str::FromStr;
let original = Decimal::from_str("123.456").unwrap();
let bytes = original.as_bytes();
let restored = Decimal::from_bytes(bytes).unwrap();
assert_eq!(original, restored);Sourcepub fn from_bytes_unchecked(bytes: Vec<u8>) -> Self
pub fn from_bytes_unchecked(bytes: Vec<u8>) -> Self
Creates a Decimal from raw bytes without validation.
§Safety
The caller must ensure the bytes are a valid encoding. Using invalid bytes may cause panics or incorrect results.
Sourcepub fn as_bytes(&self) -> &[u8] ⓘ
pub fn as_bytes(&self) -> &[u8] ⓘ
Returns the raw byte representation.
These bytes are lexicographically sortable - comparing them directly yields the same result as comparing the numerical values.
Sourcepub fn into_bytes(self) -> Vec<u8> ⓘ
pub fn into_bytes(self) -> Vec<u8> ⓘ
Consumes the Decimal and returns the underlying bytes.
Sourcepub fn is_negative(&self) -> bool
pub fn is_negative(&self) -> bool
Returns true if this decimal is negative.
Sourcepub fn is_positive(&self) -> bool
pub fn is_positive(&self) -> bool
Returns true if this decimal is positive (and not zero).
Sourcepub fn is_pos_infinity(&self) -> bool
pub fn is_pos_infinity(&self) -> bool
Returns true if this decimal represents positive infinity.
Sourcepub fn is_neg_infinity(&self) -> bool
pub fn is_neg_infinity(&self) -> bool
Returns true if this decimal represents negative infinity.
Sourcepub fn is_infinity(&self) -> bool
pub fn is_infinity(&self) -> bool
Returns true if this decimal represents positive or negative infinity.
Sourcepub fn is_special(&self) -> bool
pub fn is_special(&self) -> bool
Returns true if this decimal is a special value (Infinity or NaN).
Sourcepub fn is_finite(&self) -> bool
pub fn is_finite(&self) -> bool
Returns true if this decimal is a finite number (not Infinity or NaN).
Sourcepub fn infinity() -> Self
pub fn infinity() -> Self
Creates positive infinity.
Infinity is greater than all finite numbers but less than NaN. Two positive infinities are equal to each other.
§Example
use decimal_bytes::Decimal;
use std::str::FromStr;
let inf = Decimal::infinity();
let big = Decimal::from_str("999999999999").unwrap();
assert!(inf > big);
assert_eq!(inf, Decimal::infinity());Sourcepub fn neg_infinity() -> Self
pub fn neg_infinity() -> Self
Creates negative infinity.
Negative infinity is less than all finite numbers and positive infinity. Two negative infinities are equal to each other.
§Example
use decimal_bytes::Decimal;
use std::str::FromStr;
let neg_inf = Decimal::neg_infinity();
let small = Decimal::from_str("-999999999999").unwrap();
assert!(neg_inf < small);
assert_eq!(neg_inf, Decimal::neg_infinity());Sourcepub fn nan() -> Self
pub fn nan() -> Self
Creates NaN (Not a Number).
§PostgreSQL Semantics
Unlike IEEE 754 floating-point where NaN != NaN, this follows PostgreSQL
semantics where:
NaN == NaNistrueNaNis the greatest value (greater than positive infinity)- All NaN values are equal regardless of how they were created
This makes NaN usable in sorting, indexing, and deduplication.
§Example
use decimal_bytes::Decimal;
use std::str::FromStr;
let nan1 = Decimal::nan();
let nan2 = Decimal::from_str("NaN").unwrap();
let inf = Decimal::infinity();
// NaN equals itself (PostgreSQL behavior)
assert_eq!(nan1, nan2);
// NaN is greater than everything
assert!(nan1 > inf);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>,
Source§impl FromStr for Decimal
impl FromStr for Decimal
Source§fn from_str(s: &str) -> Result<Self, Self::Err>
fn from_str(s: &str) -> Result<Self, Self::Err>
Creates a new Decimal from a string representation.
§Examples
use decimal_bytes::Decimal;
use std::str::FromStr;
let d = Decimal::from_str("123.456").unwrap();
let d = Decimal::from_str("-0.001").unwrap();
let d = Decimal::from_str("1e10").unwrap();
// Or use parse:
let d: Decimal = "42.5".parse().unwrap();Source§type Err = DecimalError
type Err = DecimalError
Source§impl Ord for Decimal
impl Ord for Decimal
Source§impl PartialOrd for Decimal
impl PartialOrd for Decimal
Source§impl TryFrom<f64> for Decimal
impl TryFrom<f64> for Decimal
Source§fn try_from(val: f64) -> Result<Self, Self::Error>
fn try_from(val: f64) -> Result<Self, Self::Error>
Converts an f64 to a Decimal.
Special values are handled:
f64::NAN→Decimal::nan()f64::INFINITY→Decimal::infinity()f64::NEG_INFINITY→Decimal::neg_infinity()
Note: Due to f64’s limited precision (~15-17 significant digits),
very precise decimal values may lose precision when converted from f64.
For exact decimal representation, use Decimal::from_str() instead.
§Example
use decimal_bytes::Decimal;
let d: Decimal = 123.456f64.try_into().unwrap();
assert_eq!(d.to_string(), "123.456");
let inf: Decimal = f64::INFINITY.try_into().unwrap();
assert!(inf.is_pos_infinity());
let nan: Decimal = f64::NAN.try_into().unwrap();
assert!(nan.is_nan());