variant_rs/com_types/
decimal.rs

1//! Wrapper type for [`DECIMAL`]
2
3use 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/// Transparent wrapper around a [`DECIMAL`] value
11#[derive(Copy, Clone)]
12pub struct ComDecimal(pub DECIMAL);
13
14// seriously guys, why did you remove impl PartialEq for DECIMAL??
15// it was there, it worked, and now it's gone
16fn 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}