use std::{fmt, hash::{Hash, Hasher}};
use crate::form::{FieldType, FIELDTYPE_NUMERIC, IsFieldType};
pub struct Numeric<'a> {
fieldtype: &'a FieldType,
arguments: u8,
padding: i32,
minimum: libc::c_double,
maximum: libc::c_double
}
impl<'a> Numeric<'a> {
pub fn new(padding: i32, minimum: libc::c_double, maximum: libc::c_double) -> Self {
Self { fieldtype: &*FIELDTYPE_NUMERIC, arguments: 3, padding, minimum, maximum }
}
}
impl<'a> IsFieldType<'a, i32, libc::c_double, libc::c_double> for Numeric<'a> {
fn fieldtype(&self) -> &'a FieldType {
self.fieldtype
}
fn arguments(&self) -> u8 {
self.arguments
}
fn arg1(&self) -> i32 {
self.padding
}
fn arg2(&self) -> libc::c_double {
self.minimum
}
fn arg3(&self) -> libc::c_double {
self.maximum
}
}
unsafe impl<'a> Send for Numeric<'a> { } unsafe impl<'a> Sync for Numeric<'a> { }
impl<'a> PartialEq for Numeric<'a> {
fn eq(&self, rhs: &Self) -> bool {
self.fieldtype == rhs.fieldtype &&
self.arguments == rhs.arguments &&
self.padding == rhs.padding &&
canonicalize(self.minimum) == canonicalize(rhs.minimum) &&
canonicalize(self.maximum) == canonicalize(rhs.maximum)
}
}
impl<'a> Eq for Numeric<'a> { }
impl<'a> Hash for Numeric<'a> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.fieldtype.hash(state);
self.arguments.hash(state);
self.padding.hash(state);
transmute_value(self.minimum).hash(state);
transmute_value(self.maximum).hash(state);
}
}
impl <'a>AsRef<Numeric<'a>> for Numeric<'a> {
fn as_ref(&self) -> &Self {
self
}
}
impl <'a>AsMut<Numeric<'a>> for Numeric<'a> {
fn as_mut(&mut self) -> &mut Self {
self
}
}
impl<'a> fmt::Debug for Numeric<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{{ fieldtype: {:?}, arguments: {}, padding: {}, minimum: {}, maximum: {} }}",
self.fieldtype,
self.arguments,
self.padding,
self.minimum,
self.maximum
)
}
}
fn canonicalize(value: libc::c_double) -> libc::c_long {
(value * 1024.0 * 1024.0).round() as libc::c_long
}
fn transmute_value(value: libc::c_double) -> libc::c_long {
value.to_bits() as libc::c_long
}