pub fn money_to_string(bytes: &[u8; 8]) -> String {
let raw = i64::from_le_bytes(*bytes);
let negative = raw < 0;
let abs_val = (raw as i128).unsigned_abs(); let integer = abs_val / 10_000;
let decimal = abs_val % 10_000;
if negative {
format!("-{integer}.{decimal:04}")
} else {
format!("{integer}.{decimal:04}")
}
}
pub fn numeric_to_string(bytes: &[u8; 17], scale: u8) -> String {
let negative = bytes[0] != 0x00;
let mut fixed = [0u8; 16];
for group in 0..4 {
let src = 1 + group * 4;
let dst = group * 4;
fixed[dst] = bytes[src + 3];
fixed[dst + 1] = bytes[src + 2];
fixed[dst + 2] = bytes[src + 1];
fixed[dst + 3] = bytes[src];
}
let value = u128::from_be_bytes(fixed);
if scale == 0 {
let s = value.to_string();
if negative && value != 0 {
format!("-{s}")
} else {
s
}
} else {
let divisor = 10u128.pow(scale as u32);
let integer = value / divisor;
let decimal = value % divisor;
let s = format!("{integer}.{decimal:0>width$}", width = scale as usize);
if negative && value != 0 {
format!("-{s}")
} else {
s
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn money_zero() {
assert_eq!(money_to_string(&0i64.to_le_bytes()), "0.0000");
}
#[test]
fn money_one() {
assert_eq!(money_to_string(&10_000i64.to_le_bytes()), "1.0000");
}
#[test]
fn money_positive() {
assert_eq!(money_to_string(&123_456_789i64.to_le_bytes()), "12345.6789");
}
#[test]
fn money_negative() {
assert_eq!(
money_to_string(&(-123_456_789i64).to_le_bytes()),
"-12345.6789"
);
}
#[test]
fn money_fractional_only() {
assert_eq!(money_to_string(&5i64.to_le_bytes()), "0.0005");
}
#[test]
fn money_max() {
let s = money_to_string(&i64::MAX.to_le_bytes());
assert_eq!(s, "922337203685477.5807");
}
#[test]
fn money_min() {
let s = money_to_string(&i64::MIN.to_le_bytes());
assert_eq!(s, "-922337203685477.5808");
}
#[test]
fn numeric_zero() {
let bytes = [0u8; 17];
assert_eq!(numeric_to_string(&bytes, 2), "0.00");
}
#[test]
fn numeric_positive_integer() {
let mut bytes = [0u8; 17];
bytes[0] = 0x00; bytes[13] = 0x2A;
bytes[14] = 0x00;
bytes[15] = 0x00;
bytes[16] = 0x00;
assert_eq!(numeric_to_string(&bytes, 0), "42");
}
#[test]
fn numeric_with_scale() {
let mut bytes = [0u8; 17];
bytes[0] = 0x00; bytes[13] = 0x39;
bytes[14] = 0x30;
bytes[15] = 0x00;
bytes[16] = 0x00;
assert_eq!(numeric_to_string(&bytes, 2), "123.45");
}
#[test]
fn numeric_negative() {
let mut bytes = [0u8; 17];
bytes[0] = 0x80; bytes[13] = 0x39;
bytes[14] = 0x30;
bytes[15] = 0x00;
bytes[16] = 0x00;
assert_eq!(numeric_to_string(&bytes, 2), "-123.45");
}
#[test]
fn numeric_negative_zero() {
let mut bytes = [0u8; 17];
bytes[0] = 0x80;
assert_eq!(numeric_to_string(&bytes, 2), "0.00");
}
#[test]
fn numeric_leading_decimal_zeros() {
let mut bytes = [0u8; 17];
bytes[0] = 0x00;
bytes[13] = 0x05;
assert_eq!(numeric_to_string(&bytes, 4), "0.0005");
}
#[test]
fn numeric_multi_group() {
let mut bytes = [0u8; 17];
bytes[0] = 0x00;
bytes[9] = 0x01; assert_eq!(numeric_to_string(&bytes, 0), "4294967296");
}
#[test]
fn numeric_negative_scale_zero() {
let mut bytes = [0u8; 17];
bytes[0] = 0x80; bytes[13] = 0x2A; assert_eq!(numeric_to_string(&bytes, 0), "-42");
}
#[test]
fn numeric_positive_scale_zero() {
let mut bytes = [0u8; 17];
bytes[0] = 0x00;
bytes[13] = 0x64; assert_eq!(numeric_to_string(&bytes, 0), "100");
}
}