use std::borrow::Borrow;
use std::marker::PhantomData;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use super::mapping::*;
macro_rules! number_type {
($wrapper_ty:ident, $mapping_ty:ident, $field_trait:ident, $std_ty:ident) => (
#[derive(Debug, Default, Clone, PartialEq)]
pub struct $wrapper_ty<TMapping> where TMapping: $mapping_ty {
value: $std_ty,
_m: PhantomData<TMapping>
}
impl<TMapping> $wrapper_ty<TMapping> where TMapping: $mapping_ty {
pub fn new<I: Into<$std_ty>>(num: I) -> $wrapper_ty<TMapping> {
$wrapper_ty {
value: num.into(),
_m: PhantomData
}
}
pub fn remap<TNewMapping>(number: $wrapper_ty<TMapping>) -> $wrapper_ty<TNewMapping>
where TNewMapping: $mapping_ty
{
$wrapper_ty::new(number.value)
}
}
impl<TMapping> $field_trait<TMapping> for $wrapper_ty<TMapping> where TMapping: $mapping_ty { }
impl_mapping_type!($std_ty, $wrapper_ty, $mapping_ty);
impl<TMapping> Serialize for $wrapper_ty<TMapping> where TMapping: $mapping_ty {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where
S: Serializer {
self.value.serialize(serializer)
}
}
impl <'de, TMapping> Deserialize<'de> for $wrapper_ty<TMapping> where TMapping: $mapping_ty {
fn deserialize<D>(deserializer: D) -> Result<$wrapper_ty<TMapping>, D::Error> where
D: Deserializer<'de> {
let t = try!($std_ty::deserialize(deserializer));
Ok($wrapper_ty::new(t))
}
}
)
}
number_type!(Integer, IntegerMapping, IntegerFieldType, i32);
number_type!(Long, LongMapping, LongFieldType, i64);
number_type!(Short, ShortMapping, ShortFieldType, i16);
number_type!(Byte, ByteMapping, ByteFieldType, i8);
number_type!(Float, FloatMapping, FloatFieldType, f32);
number_type!(Double, DoubleMapping, DoubleFieldType, f64);
#[cfg(test)]
mod tests {
use serde_json;
use prelude::*;
#[derive(Default)]
struct MyIntegerMapping;
impl IntegerMapping for MyIntegerMapping {}
#[derive(Default)]
struct MyLongMapping;
impl LongMapping for MyLongMapping {}
#[derive(Default)]
struct MyShortMapping;
impl ShortMapping for MyShortMapping {}
#[derive(Default)]
struct MyByteMapping;
impl ByteMapping for MyByteMapping {}
#[derive(Default)]
struct MyFloatMapping;
impl FloatMapping for MyFloatMapping {}
#[derive(Default)]
struct MyDoubleMapping;
impl DoubleMapping for MyDoubleMapping {}
#[test]
fn can_change_number_mapping() {
fn takes_custom_mapping(_: Integer<MyIntegerMapping>) -> bool {
true
}
let number: Integer<DefaultIntegerMapping> = Integer::new(1);
assert!(takes_custom_mapping(Integer::remap(number)));
}
#[test]
fn serialise_elastic_numbers() {
let ser = vec![
{
let num = Integer::<MyIntegerMapping>::new(1i32);
serde_json::to_string(&num).unwrap()
},
{
let num = Long::<MyLongMapping>::new(1i64);
serde_json::to_string(&num).unwrap()
},
{
let num = Short::<MyShortMapping>::new(1i16);
serde_json::to_string(&num).unwrap()
},
{
let num = Byte::<MyByteMapping>::new(1i8);
serde_json::to_string(&num).unwrap()
},
{
let num = Float::<MyFloatMapping>::new(1.01f32);
serde_json::to_string(&num).unwrap()
},
{
let num = Double::<MyDoubleMapping>::new(1.01f64);
serde_json::to_string(&num).unwrap()
},
];
let expected_ser = vec!["1", "1", "1", "1", "1.01", "1.01"];
let mut success = true;
for i in 0..ser.len() {
if expected_ser[i] != &ser[i] {
success = false;
break;
}
}
assert!(success);
}
#[test]
fn deserialise_elastic_numbers() {
let int_de: Integer<MyIntegerMapping> = serde_json::from_str("1").unwrap();
let long_de: Long<MyLongMapping> = serde_json::from_str("1").unwrap();
let short_de: Short<MyShortMapping> = serde_json::from_str("1").unwrap();
let byte_de: Byte<MyByteMapping> = serde_json::from_str("1").unwrap();
let float_de: Float<MyFloatMapping> = serde_json::from_str("1.01").unwrap();
let double_de: Double<MyDoubleMapping> = serde_json::from_str("1.01").unwrap();
assert_eq!(
(1i32, 1i64, 1i16, 1i8, 1.01f32, 1.01f64),
(
*int_de,
*long_de,
*short_de,
*byte_de,
*float_de,
*double_de
)
);
}
}