use crate::{Decimal, context::get_context, error::MPDecimalError};
use std::{ffi::CString, str::FromStr};
use mpdec_sys::mpd_qset_string;
macro_rules! gen_from_primitives_funcs {
(
$($func_name:ident($type:ty) => $mpd_qset_func:ident;)*
) => {
$(
pub fn $func_name(from: $type) -> Result<Decimal, MPDecimalError> {
let result = Decimal::checked_new()?;
let mut status: u32 = 0;
unsafe {
mpdec_sys::$mpd_qset_func(
result.inner,
from,
&mut *get_context(),
&mut status,
);
}
MPDecimalError::from_status(status)?;
Ok(result)
}
)*
};
}
impl Decimal {
gen_from_primitives_funcs!(
from_u32(u32) => mpd_qset_u32;
from_u64(u64) => mpd_qset_u64;
from_i32(i32) => mpd_qset_i32;
from_i64(i64) => mpd_qset_i64;
);
pub fn from_f32(value: f32) -> std::io::Result<Self> {
Self::from_str(&value.to_string())
}
pub fn from_f64(value: f64) -> std::io::Result<Self> {
Self::from_str(&value.to_string())
}
}
impl FromStr for Decimal {
type Err = std::io::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let cstr =
CString::new(s).map_err(|_| std::io::Error::from(std::io::ErrorKind::InvalidData))?;
let decimal = Self::checked_new()?;
let mut status = 0_u32;
unsafe {
mpd_qset_string(
decimal.inner,
cstr.as_ptr(),
&mut *get_context(),
&mut status,
)
};
MPDecimalError::from_status(status)?;
Ok(decimal)
}
}