pub struct DecimalLexEncoder;Expand description
Variable-length lexicographic encoding for D128 values that preserves sort order.
This encoder converts D128 values into byte sequences that maintain the same lexicographic ordering as the original decimal values. This is crucial for database indexing where byte-level comparison must match numeric comparison.
§Encoding Format
The encoding uses a variable-length format optimized for lexicographic ordering:
§Zero Values
- Zero is encoded as a single byte:
0x80 - This ensures zero sorts between negative and positive numbers
§Non-Zero Values
The format consists of:
-
Class/marker byte (1 byte):
0x80Zero0x40Finite negative0xA0Finite positive0x20Negative infinity0xC0Positive infinity0xFFNaN
-
Biased scale (2 bytes, big-endian):
- We bias the “scale” (not the raw exponent). Scale is defined as:
scale = exponent + (digit_count - 1), i.e., the position of the most-significant digit in a scientific-notation sense. - Stored as:
biased = scale + EXP_BIAS(unsigned 16-bit) - For negative numbers: stored as
0xFFFF - biased(one’s complement) to reverse order - EXP_BIAS = 6144. With D128,
exponent ∈ [-6143, +6144]anddigit_count ∈ [1, 34], soscale ∈ [-6143, 6177], which maps into[1, 12321]after biasing, well withinu16.
- We bias the “scale” (not the raw exponent). Scale is defined as:
-
Packed digit representation (variable length):
- Digits are taken from the absolute value’s base-10 representation
- Each pair of digits is packed into one byte (4 bits per digit)
- For positive numbers: stored as-is
- For negative numbers: all bytes are bitwise complemented to reverse ordering
- Termination: encoding stops when a nibble equals
0x0. This naturally handles both odd and even digit counts: • odd count: the last byte has a low nibble of 0 • even count: an extra full terminator byte is appended (0x00 for positives, 0xFF for negatives)
Because a terminator is always present within (or immediately after) the mantissa, any trailing type-marker byte appended by higher layers will never be consumed by the mantissa decoder.
§Properties
- Preserves lexicographic ordering: if
a < bthenencode(a) < encode(b) - Variable length encoding (3+ bytes typical: 1 sign + 2 scale + packed digits)
- Handles full D128 range including extreme values
- Uses packed digit encoding for efficient storage (2 digits per byte)
Implementations§
Source§impl DecimalLexEncoder
impl DecimalLexEncoder
Sourcepub fn encode(dec: D128) -> Vec<u8> ⓘ
pub fn encode(dec: D128) -> Vec<u8> ⓘ
Encodes a D128 value into a lexicographically ordered byte sequence.
The encoding preserves sort order: if a < b then encode(a) < encode(b). This is essential for database indexing where byte-level
comparison must match numeric comparison.
Sourcepub fn decode(bytes: &[u8]) -> Result<D128>
pub fn decode(bytes: &[u8]) -> Result<D128>
Decodes a lexicographically encoded byte sequence back to a D128 value.
This reverses the encoding process, reconstructing the original D128 from its byte representation while handling all the encoding transformations.
Sourcepub fn to_d128(dec: Decimal) -> D128
pub fn to_d128(dec: Decimal) -> D128
Converts a rust_decimal::Decimal to a fastnum::D128.
This conversion extracts the mantissa, scale, and sign from the Decimal and reconstructs them as a D128 value.
Sourcepub fn to_decimal(d128: D128) -> Result<Decimal>
pub fn to_decimal(d128: D128) -> Result<Decimal>
Converts a fastnum::D128 to a rust_decimal::Decimal.
This conversion uses string representation as an intermediate format to ensure precision is maintained during the conversion.