use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct TPCHDecimal(pub i64);
impl TPCHDecimal {
pub fn new(value: i64) -> Self {
TPCHDecimal(value)
}
pub const ZERO: TPCHDecimal = TPCHDecimal(0);
pub const fn as_f64(&self) -> f64 {
self.0 as f64 / 100.0
}
pub const fn is_negative(&self) -> bool {
self.0.is_negative()
}
pub const fn int_digits(&self) -> i64 {
(self.0 / 100).abs()
}
pub const fn decimal_digits(&self) -> i64 {
(self.0 % 100).abs()
}
pub const fn into_inner(self) -> i64 {
self.0
}
}
impl fmt::Display for TPCHDecimal {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}{}.{:0>2}",
if self.is_negative() { "-" } else { "" },
self.int_digits(),
self.decimal_digits()
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn decimal_format() {
struct TestCase {
decimal: TPCHDecimal,
expected: &'static str,
}
let test_cases = [
TestCase {
decimal: TPCHDecimal(0),
expected: "0.00",
},
TestCase {
decimal: TPCHDecimal(1),
expected: "0.01",
},
TestCase {
decimal: TPCHDecimal(10),
expected: "0.10",
},
TestCase {
decimal: TPCHDecimal(100),
expected: "1.00",
},
TestCase {
decimal: TPCHDecimal(1000),
expected: "10.00",
},
TestCase {
decimal: TPCHDecimal(1234),
expected: "12.34",
},
TestCase {
decimal: TPCHDecimal(-1),
expected: "-0.01",
},
TestCase {
decimal: TPCHDecimal(-10),
expected: "-0.10",
},
TestCase {
decimal: TPCHDecimal(-100),
expected: "-1.00",
},
TestCase {
decimal: TPCHDecimal(-1000),
expected: "-10.00",
},
TestCase {
decimal: TPCHDecimal(999_999_999_999),
expected: "9999999999.99",
},
TestCase {
decimal: TPCHDecimal(-999_999_999_999),
expected: "-9999999999.99",
},
];
for test_case in test_cases {
let formatted = test_case.decimal.to_string();
assert_eq!(
test_case.expected, formatted,
"input decimal: {:?}",
test_case.decimal,
);
}
}
}