dec_number_sys/
dec_double.rs

1//! Safe bindings for 64-bit decimal.
2
3use crate::dec_context::DecContext;
4use crate::dec_double_c::*;
5use libc::c_char;
6use std::ffi::{CStr, CString};
7use std::fmt::Debug;
8
9/// Length in bytes of [DecDouble] union.
10pub const DEC_DOUBLE_BYTES: usize = 8;
11
12/// Maximum length of the [DecDouble] string.
13pub const DEC_DOUBLE_STRING: usize = 25;
14
15/// Buffer for [DecDouble] string.
16pub const DEC_DOUBLE_STRING_BUFFER: [c_char; DEC_DOUBLE_STRING] = [0; DEC_DOUBLE_STRING];
17
18/// Convenient constant for [DecDouble] equal to positive zero.
19
20pub const DEC_DOUBLE_ZERO: DecDouble = {
21  #[cfg(target_endian = "little")]
22  {
23    DecDouble {
24      bytes: [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x22],
25    }
26  }
27  #[cfg(target_endian = "big")]
28  {
29    DecDouble {
30      bytes: [0x22, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
31    }
32  }
33};
34
35/// 64-bit decimal number.
36#[repr(C)]
37#[derive(Copy, Clone)]
38pub union DecDouble {
39  pub bytes: [u8; DEC_DOUBLE_BYTES],
40  pub shorts: [u16; DEC_DOUBLE_BYTES / 2],
41  pub words: [u32; DEC_DOUBLE_BYTES / 4],
42  pub longs: [u64; DEC_DOUBLE_BYTES / 8],
43}
44
45impl Default for DecDouble {
46  /// The default value for [DecDouble] is positive zero.
47  fn default() -> Self {
48    DEC_DOUBLE_ZERO
49  }
50}
51
52impl Debug for DecDouble {
53  /// Converts [DecDouble] to a string in the form of hexadecimal bytes separated with spaces.
54  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55    write!(
56      f,
57      "[{}]",
58      (0..DEC_DOUBLE_BYTES)
59        .rev()
60        .fold("".to_string(), |s, i| format!("{} {:02X}", s, unsafe { self.bytes[i] }))
61        .trim_start()
62    )
63  }
64}
65
66/// Safe binding to *decDoubleAdd* function.
67pub fn dec_double_add(dd1: &DecDouble, dd2: &DecDouble, dc: &mut DecContext) -> DecDouble {
68  let mut dd = DEC_DOUBLE_ZERO;
69  unsafe {
70    decDoubleAdd(&mut dd, dd1, dd2, dc);
71  }
72  dd
73}
74
75/// Safe binding to *decDoubleFromString* function.
76pub fn dec_double_from_string(s: &str, dc: &mut DecContext) -> DecDouble {
77  let c_s = CString::new(s).unwrap();
78  let mut dd = DEC_DOUBLE_ZERO;
79  unsafe {
80    decDoubleFromString(&mut dd, c_s.as_ptr(), dc);
81  }
82  dd
83}
84
85/// Safe binding to *decDoubleToString* function.
86pub fn dec_double_to_string(dd1: &DecDouble) -> String {
87  unsafe {
88    let mut buf = DEC_DOUBLE_STRING_BUFFER;
89    decDoubleToString(dd1, buf.as_mut_ptr() as *mut c_char);
90    CStr::from_ptr(buf.as_ptr() as *const c_char)
91      .to_string_lossy()
92      .into_owned()
93  }
94}
95
96/// Safe binding to *decDoubleZero* function.
97pub fn dec_double_zero(dd1: &mut DecDouble) {
98  unsafe {
99    decDoubleZero(dd1);
100  }
101}