use std::marker::PhantomData;
use reddd_macros::ValueType;
pub trait ValueType: Clone {
type Inner: Clone + PartialEq + PartialOrd;
fn into_inner(self) -> Self::Inner;
fn as_inner(&self) -> &Self::Inner;
}
cfg_if::cfg_if! {
if #[cfg(feature = "serde")] {
#[derive(Debug, ValueType, serde::Serialize, serde::Deserialize)]
#[serde(transparent)]
pub struct TypedValue<V, T>(#[main_field] V, PhantomData<Box<T>>)
where
V: Clone + std::fmt::Debug + PartialEq + PartialOrd;
} else {
#[derive(Debug, ValueType)]
pub struct TypedValue<V, T>(#[main_field] V, PhantomData<dyn Fn() -> T>)
where
V: Clone + std::fmt::Debug + PartialEq + PartialOrd;
}
}
impl<V, T> TypedValue<V, T>
where
V: Clone + std::fmt::Debug + PartialEq + PartialOrd,
{
pub fn new(value: V) -> Self {
Self(value, Default::default())
}
}
impl<V, T> Clone for TypedValue<V, T>
where
V: Clone + std::fmt::Debug + PartialEq + PartialOrd,
{
fn clone(&self) -> Self {
Self(self.0.clone(), self.1)
}
}
#[cfg(test)]
mod tests {
use fake::{Dummy, Fake, Faker};
use reddd_macros::ValueType;
use super::*;
#[test]
fn simple_newtype_annotated_test() {
#[derive(Clone, ValueType, Dummy)]
struct NewType(#[main_field] i32);
let f: NewType = Faker.fake();
let fval = f.0;
assert_eq!(&fval, f.as_inner());
assert_eq!(fval, f.into_inner());
}
#[test]
fn simple_newtype_auto_test() {
#[derive(Clone, ValueType, Dummy)]
struct NewType(i32);
let f: NewType = Faker.fake();
let fval = f.0;
assert_eq!(&fval, f.as_inner());
assert_eq!(fval, f.into_inner());
}
#[test]
fn multifield_newtype_annotated_test() {
#[derive(Clone, ValueType, Dummy)]
struct NewType(i32, #[main_field] String);
let f: NewType = Faker.fake();
let fval = f.1.clone();
assert_eq!(&fval, f.as_inner());
assert_eq!(fval, f.into_inner());
}
#[test]
fn multifield_newtype_auto_test() {
#[derive(Clone, ValueType, Dummy)]
struct NewType(i32, String);
let f: NewType = Faker.fake();
let fval = f.0;
assert_eq!(&fval, f.as_inner());
assert_eq!(fval, f.into_inner());
}
#[test]
fn multifield_named_annotated_test() {
#[derive(Clone, ValueType, Dummy)]
struct NewType {
_field0: i32,
#[main_field]
field1: String,
}
let f: NewType = Faker.fake();
let fval = f.field1.clone();
assert_eq!(&fval, f.as_inner());
assert_eq!(fval, f.into_inner());
}
#[test]
fn multifield_named_auto_test() {
#[derive(Clone, ValueType, Dummy)]
struct NewType {
field0: i32,
_field1: String,
}
let f: NewType = Faker.fake();
let fval = f.field0;
assert_eq!(&fval, f.as_inner());
assert_eq!(fval, f.into_inner());
}
#[test]
fn equlity_test() {
#[derive(Clone, Debug, ValueType, Dummy)]
struct NewType(String);
let f1: NewType = Faker.fake();
let mut f2 = f1.clone();
assert_eq!(f1, f2);
f2.0 = f1.0.clone() + "_additional";
assert_ne!(f1, f2);
}
#[test]
fn order_test() {
#[derive(Clone, Debug, ValueType, Dummy)]
struct NewType(u64);
let mut f1: NewType = Faker.fake();
let mut f2 = f1.clone();
assert_eq!(f1, f2);
assert!(f1 <= f2);
assert!(f1 >= f2);
assert!(f2 <= f1);
assert!(f2 >= f1);
while f1 == f2 {
f1.0 += rand::random::<u64>() % (u64::MAX - f1.0);
}
assert_ne!(f1, f2);
assert!(f1 > f2);
assert!(f1 >= f2);
assert!(f2 < f1);
assert!(f2 <= f1);
while f1 >= f2 {
f2.0 += rand::random::<u64>() % (u64::MAX - f2.0);
}
assert_ne!(f1, f2);
assert!(f1 < f2);
assert!(f1 <= f2);
assert!(f2 > f1);
assert!(f2 >= f1);
}
#[test]
#[cfg(feature = "serde")]
fn serde_test() {
#[derive(Clone, Debug)]
struct SomeType;
type TestType = TypedValue<i64, SomeType>;
let inner = rand::random();
let value = TestType::new(inner);
assert_eq!(&inner, value.as_inner());
let serialized = serde_json::to_string(&value).unwrap();
assert_eq!(format!(r#"{inner}"#), serialized);
let deserialized: TestType = serde_json::from_str(&serialized).unwrap();
assert_eq!(value, deserialized);
assert_eq!(value.as_inner(), deserialized.as_inner());
assert_eq!(value.into_inner(), deserialized.into_inner());
}
}