variant_rs/com_types/
decimal.rs1use crate::VariantType;
4use rust_decimal::Decimal;
5use std::fmt::{Debug, Display};
6use windows::Win32::Foundation::{DECIMAL, DECIMAL_0, DECIMAL_0_0, DECIMAL_1};
7
8const DECIMAL_NEG: u8 = 0x80;
9
10#[derive(Copy, Clone)]
12pub struct ComDecimal(pub DECIMAL);
13
14fn dec_to_bytes(dec: &DECIMAL) -> &[u8] {
17 unsafe {
18 std::slice::from_raw_parts(
19 dec as *const DECIMAL as *const u8,
20 std::mem::size_of::<DECIMAL>(),
21 )
22 }
23}
24
25impl PartialEq for ComDecimal {
26 fn eq(&self, other: &Self) -> bool {
27 dec_to_bytes(&self.0) == dec_to_bytes(&other.0)
28 }
29}
30
31impl Eq for ComDecimal {}
32
33impl Display for ComDecimal {
34 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
35 write!(f, "{}", Into::<Decimal>::into(self))
36 }
37}
38
39impl Debug for ComDecimal {
40 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
41 write!(f, "ComDecimal({})", self)
42 }
43}
44
45impl From<&Decimal> for ComDecimal {
46 fn from(dec: &Decimal) -> Self {
47 let unpack = dec.unpack();
48 ComDecimal(DECIMAL {
49 wReserved: VariantType::VT_DECIMAL as u16,
50 Anonymous1: DECIMAL_0 {
51 Anonymous: DECIMAL_0_0 {
52 scale: dec.scale() as u8,
53 sign: if dec.is_sign_positive() {
54 0
55 } else {
56 DECIMAL_NEG
57 },
58 },
59 },
60 Hi32: unpack.hi,
61 Anonymous2: DECIMAL_1 {
62 Lo64: ((unpack.mid as u64) << 32) + unpack.lo as u64,
63 },
64 })
65 }
66}
67
68impl From<Decimal> for ComDecimal {
69 fn from(dec: Decimal) -> Self {
70 Self::from(&dec)
71 }
72}
73
74impl From<&ComDecimal> for Decimal {
75 fn from(dec: &ComDecimal) -> Self {
76 let num = dec.0;
77 unsafe {
78 Decimal::from_parts(
79 (num.Anonymous2.Lo64 & 0xFFFFFFFF) as u32,
80 ((num.Anonymous2.Lo64 >> 32) & 0xFFFFFFFF) as u32,
81 num.Hi32,
82 num.Anonymous1.Anonymous.sign == DECIMAL_NEG,
83 num.Anonymous1.Anonymous.scale as u32,
84 )
85 }
86 }
87}
88
89impl From<ComDecimal> for Decimal {
90 fn from(dec: ComDecimal) -> Self {
91 Self::from(&dec)
92 }
93}
94
95impl From<*mut DECIMAL> for &mut ComDecimal {
96 fn from(dec: *mut DECIMAL) -> Self {
97 unsafe { &mut *(dec as *mut ComDecimal) }
98 }
99}
100
101impl ComDecimal {
102 pub fn as_mut_ptr(&mut self) -> *mut DECIMAL {
103 (&mut self.0) as *mut DECIMAL
104 }
105}