use core::num::NonZeroU16;
use token_value_map::*;
#[test]
fn value_from_primitives() {
let _: Data = 42i64.into();
let _: Data = 3.5f64.into();
let _: Data = true.into();
let _: Data = "hello".into();
#[cfg(feature = "vector2")]
{
let _: Data = [1.0, 2.0].into();
}
#[cfg(feature = "vector3")]
{
let _: Data = [1.0, 2.0, 3.0].into();
}
let _: Data = [1.0, 0.5, 0.0, 1.0].into(); }
#[test]
fn value_to_primitives() {
let v: Data = 42i64.into();
assert_eq!(i64::try_from(v).unwrap(), 42);
let v: Data = [1.0, 0.5, 0.0, 1.0].into();
assert_eq!(<[f32; 4]>::try_from(v).unwrap(), [1.0, 0.5, 0.0, 1.0]);
}
#[test]
fn data_type() {
assert_eq!(Data::from(42i64).data_type(), DataType::Integer);
assert_eq!(Data::from(3.5).data_type(), DataType::Real);
assert_eq!(Data::from(true).data_type(), DataType::Boolean);
assert_eq!(Data::from("hello").data_type(), DataType::String);
}
#[test]
fn try_convert() {
let v = Data::from(42i64);
assert_eq!(v.try_convert(DataType::Real).unwrap(), Data::from(42.0));
assert_eq!(v.try_convert(DataType::Boolean).unwrap(), Data::from(true));
assert_eq!(v.try_convert(DataType::String).unwrap(), Data::from("42"));
let v = Data::from(true);
assert_eq!(v.try_convert(DataType::Integer).unwrap(), Data::from(1i64));
assert_eq!(v.try_convert(DataType::Real).unwrap(), Data::from(1.0));
let v = Data::from(false);
assert_eq!(v.try_convert(DataType::Integer).unwrap(), Data::from(0i64));
let v = Data::from("123");
assert_eq!(
v.try_convert(DataType::Integer).unwrap(),
Data::from(123i64)
);
assert_eq!(v.try_convert(DataType::Real).unwrap(), Data::from(123.0));
let v = Data::from("true");
assert_eq!(v.try_convert(DataType::Boolean).unwrap(), Data::from(true));
#[cfg(feature = "vector2")]
{
let v = Data::from(5.0);
let vec2 = v.try_convert(DataType::Vector2).unwrap();
assert_eq!(
token_value_map::math::Vec2Impl::try_from(vec2).unwrap(),
token_value_map::math::Vec2Impl::new(5.0, 5.0)
);
}
#[cfg(feature = "vector3")]
{
let v = Data::from(5.0);
let vec3 = v.try_convert(DataType::Vector3).unwrap();
assert_eq!(
token_value_map::math::Vec3Impl::try_from(vec3).unwrap(),
token_value_map::math::Vec3Impl::new(5.0, 5.0, 5.0)
);
}
let v = Data::from(0.5);
let color = v.try_convert(DataType::Color).unwrap();
assert_eq!(<[f32; 4]>::try_from(color).unwrap(), [0.5, 0.5, 0.5, 1.0]);
#[cfg(feature = "vector3")]
{
let v = Data::from([1.0, 0.5, 0.25]);
let color = v.try_convert(DataType::Color).unwrap();
assert_eq!(<[f32; 4]>::try_from(color).unwrap(), [1.0, 0.5, 0.25, 1.0]);
}
}
#[test]
fn string_parsing() {
#[cfg(feature = "vector2")]
{
let v = Data::from("[1.0, 2.0]");
let vec2 = v.try_convert(DataType::Vector2).unwrap();
assert_eq!(
token_value_map::math::Vec2Impl::try_from(vec2).unwrap(),
token_value_map::math::Vec2Impl::new(1.0, 2.0)
);
}
let v = Data::from("#FF0000");
let color = v.try_convert(DataType::Color).unwrap();
assert_eq!(<[f32; 4]>::try_from(color).unwrap(), [1.0, 0.0, 0.0, 1.0]);
#[cfg(feature = "matrix3")]
{
let v = Data::from("5.0");
let mat = v.try_convert(DataType::Matrix3).unwrap();
let expected = token_value_map::math::mat3_from_diagonal_element(5.0);
assert_eq!(
token_value_map::math::Mat3Impl::try_from(mat).unwrap(),
expected
);
}
}
#[test]
fn attribute_value() -> token_value_map::Result<()> {
let av = Value::animated(vec![
(Time::from_secs(0.0), 0.0),
(Time::from_secs(1.0), 1.0),
(Time::from_secs(2.0), 2.0),
])?;
assert_eq!(av.sample_count(), 3);
assert!(av.is_animated());
let (before, _after) = av.sample_bracket(Time::from_secs(1.5));
assert!(before.is_some());
Ok(())
}
#[test]
fn token_value_map() -> token_value_map::Result<()> {
let mut map = TokenValueMap::new();
#[cfg(feature = "vector3")]
map.insert("position", [1.0, 2.0, 3.0]);
#[cfg(all(not(feature = "vector3"), feature = "vector2"))]
map.insert("position", [1.0, 2.0]);
#[cfg(all(not(feature = "vector3"), not(feature = "vector2")))]
map.insert("position", 42.0);
map.insert(
"color",
Value::animated(vec![
(Time::from_secs(0.0), [1.0, 0.0, 0.0, 1.0]),
(Time::from_secs(1.0), [0.0, 1.0, 0.0, 1.0]),
])?,
);
assert_eq!(map.len(), 2);
assert!(map.contains(&"position".into()));
Ok(())
}
#[test]
fn value_with_animated_data() -> token_value_map::Result<()> {
let animated_real = Value::animated(vec![
(Time::from_secs(0.0), 1.0),
(Time::from_secs(1.0), 2.0),
(Time::from_secs(2.0), 3.0),
])?;
assert!(animated_real.is_animated());
assert_eq!(animated_real.sample_count(), 3);
let sample = animated_real.sample_at(Time::from_secs(1.0));
assert_eq!(sample, Some(Data::Real(Real(2.0))));
let interpolated = animated_real.interpolate(Time::from_secs(0.5));
assert_eq!(interpolated, Data::Real(Real(1.5)));
Ok(())
}
#[test]
#[cfg(feature = "vector3")]
fn value_with_animated_vectors() -> token_value_map::Result<()> {
let animated_vec3 = Value::animated(vec![
(Time::from_secs(0.0), [0.0f32, 0.0, 0.0]),
(Time::from_secs(1.0), [1.0f32, 2.0, 3.0]),
])?;
assert!(animated_vec3.is_animated());
assert_eq!(animated_vec3.sample_count(), 2);
let interpolated = animated_vec3.interpolate(Time::from_secs(0.5));
match interpolated {
Data::Vector3(Vector3(v)) => {
assert_eq!(v, token_value_map::math::Vec3Impl::new(0.5, 1.0, 1.5));
}
_ => panic!("Expected Vector3 data, got: {:?}", interpolated),
}
Ok(())
}
#[test]
fn value_add_sample_conversion() -> token_value_map::Result<()> {
let mut value = Value::uniform(1.0);
assert!(!value.is_animated()); assert_eq!(value.sample_count(), 1);
value.add_sample(Time::from_secs(1.0), 2.0)?;
assert!(!value.is_animated());
assert_eq!(value.sample_count(), 1);
let sample = value.sample_at(Time::from_secs(1.0));
assert_eq!(sample, Some(Data::Real(Real(2.0))));
value.add_sample(Time::from_secs(2.0), 3.0)?;
assert!(value.is_animated());
assert_eq!(value.sample_count(), 2);
Ok(())
}
#[test]
fn value_type_safety() -> token_value_map::Result<()> {
let mut real_value = Value::animated(vec![(Time::from_secs(0.0), 1.0)])?;
let result = real_value.add_sample(Time::from_secs(1.0), true);
assert!(result.is_err());
let mixed_result = Value::animated(vec![
(Time::from_secs(0.0), Data::Real(Real(1.0))),
(Time::from_secs(1.0), Data::Boolean(Boolean(true))),
]);
assert!(mixed_result.is_err());
Ok(())
}
#[test]
fn value_animated_boolean_no_interpolation() -> token_value_map::Result<()> {
let animated_bool = Value::animated(vec![
(Time::from_secs(0.0), false),
(Time::from_secs(1.0), true),
])?;
let sample_early = animated_bool.interpolate(Time::from_secs(0.3));
assert_eq!(sample_early, Data::Boolean(Boolean(false)));
let sample_late = animated_bool.interpolate(Time::from_secs(0.7));
assert_eq!(sample_late, Data::Boolean(Boolean(true)));
Ok(())
}
#[test]
fn value_empty_animated_creation() {
let empty_result: token_value_map::Result<Value> = Value::animated(Vec::<(Time, f64)>::new());
assert!(empty_result.is_err());
}
#[test]
fn value_uses_generic_insert() -> token_value_map::Result<()> {
let animated_mixed = Value::animated(vec![
(Time::from_secs(0.0), Data::Real(Real(0.0))),
(Time::from_secs(1.0), Data::Real(Real(1.0))),
(Time::from_secs(2.0), Data::Real(Real(2.0))),
])?;
assert!(animated_mixed.is_animated());
assert_eq!(animated_mixed.sample_count(), 3);
let interpolated = animated_mixed.interpolate(Time::from_secs(1.5));
assert_eq!(interpolated, Data::Real(Real(1.5)));
let mut mutable_value = animated_mixed;
mutable_value.add_sample(Time::from_secs(3.0), Data::Real(Real(3.0)))?;
assert_eq!(mutable_value.sample_count(), 4);
Ok(())
}
#[test]
fn data_type_dispatch() {
let data = Data::Real(Real(42.0));
assert_eq!(data.data_type(), DataType::Real);
assert_eq!(data.type_name(), "real");
let animated = AnimatedData::Real(TimeDataMap::from_iter(vec![(
Time::from_secs(0.0),
Real(1.0),
)]));
assert_eq!(animated.data_type(), DataType::Real);
assert_eq!(animated.type_name(), "real");
let uniform_value = Value::uniform(42.0);
assert_eq!(uniform_value.data_type(), DataType::Real);
assert_eq!(uniform_value.type_name(), "real");
let animated_value = Value::animated(vec![(Time::from_secs(0.0), 1.0)]).unwrap();
assert_eq!(animated_value.data_type(), DataType::Real);
assert_eq!(animated_value.type_name(), "real");
let bool_data = Data::Boolean(Boolean(true));
assert_eq!(bool_data.data_type(), DataType::Boolean);
assert_eq!(bool_data.type_name(), "boolean");
#[cfg(feature = "vector3")]
{
let vec3_data = Data::Vector3(Vector3(token_value_map::math::Vec3Impl::new(1.0, 2.0, 3.0)));
assert_eq!(vec3_data.data_type(), DataType::Vector3);
assert_eq!(vec3_data.type_name(), "vec3");
}
}
#[test]
fn sample_trait_implementations() -> token_value_map::Result<()> {
let uniform_real = Value::uniform(42.0);
let shutter = Shutter {
range: Time::from_secs(0.0)..Time::from_secs(1.0),
opening: Time::from_secs(0.0)..Time::from_secs(1.0),
};
let samples: Vec<(Real, SampleWeight)> =
uniform_real.sample(&shutter, NonZeroU16::new(5).unwrap())?;
assert_eq!(samples.len(), 1);
assert_eq!(samples[0].0, Real(42.0));
assert_eq!(samples[0].1, 1.0);
#[cfg(feature = "vector3")]
{
let uniform_vector = Value::uniform([1.0f32, 2.0, 3.0]);
let samples: Vec<(Vector3, SampleWeight)> =
uniform_vector.sample(&shutter, NonZeroU16::new(3).unwrap())?;
assert_eq!(samples.len(), 1);
assert_eq!(
samples[0].0,
Vector3(token_value_map::math::Vec3Impl::new(1.0, 2.0, 3.0))
);
assert_eq!(samples[0].1, 1.0);
}
let animated_real = Value::animated(vec![
(Time::from_secs(0.0), 0.0),
(Time::from_secs(1.0), 100.0),
])?;
let samples: Vec<(Real, SampleWeight)> =
animated_real.sample(&shutter, NonZeroU16::new(3).unwrap())?;
assert_eq!(samples.len(), 3);
for (value, _weight) in samples {
assert!(value.0 >= 0.0 && value.0 <= 100.0);
}
Ok(())
}
#[cfg(all(test, feature = "rkyv"))]
mod rkyv_tests {
use super::*;
use rkyv::{Deserialize, archived_root, to_bytes};
#[test]
fn test_data_rkyv_roundtrip() {
let original = Data::Integer(Integer(42));
let bytes = to_bytes::<_, 256>(&original).unwrap();
let archived = unsafe { archived_root::<Data>(&bytes) };
let deserialized: Data = archived.deserialize(&mut rkyv::Infallible).unwrap();
assert_eq!(original, deserialized);
}
#[test]
fn test_value_rkyv_roundtrip() {
let original = Value::uniform(42.0);
let bytes = to_bytes::<_, 256>(&original).unwrap();
let archived = unsafe { archived_root::<Value>(&bytes) };
let deserialized: Value = archived.deserialize(&mut rkyv::Infallible).unwrap();
assert_eq!(original, deserialized);
}
#[test]
fn test_animated_value_rkyv_roundtrip() -> token_value_map::Result<()> {
let original = Value::animated(vec![
(Time::from_secs(0.0), 0.0),
(Time::from_secs(1.0), 1.0),
(Time::from_secs(2.0), 2.0),
])?;
let bytes = to_bytes::<_, 1024>(&original).unwrap();
let archived = unsafe { archived_root::<Value>(&bytes) };
let deserialized: Value = archived.deserialize(&mut rkyv::Infallible).unwrap();
assert_eq!(original, deserialized);
Ok(())
}
#[test]
#[cfg(feature = "vector3")]
fn test_vector3_rkyv_roundtrip() {
let original = Data::Vector3(Vector3(token_value_map::math::Vec3Impl::new(1.0, 2.0, 3.0)));
let bytes = to_bytes::<_, 256>(&original).unwrap();
let archived = unsafe { archived_root::<Data>(&bytes) };
let deserialized: Data = archived.deserialize(&mut rkyv::Infallible).unwrap();
assert_eq!(original, deserialized);
}
#[test]
fn test_token_value_map_rkyv_roundtrip() -> token_value_map::Result<()> {
let mut original = TokenValueMap::new();
original.insert("position", 42.0);
original.insert(
"color",
Value::animated(vec![
(Time::from_secs(0.0), [1.0, 0.0, 0.0, 1.0]),
(Time::from_secs(1.0), [0.0, 1.0, 0.0, 1.0]),
])?,
);
let bytes = to_bytes::<_, 2048>(&original).unwrap();
let archived = unsafe { archived_root::<TokenValueMap>(&bytes) };
let deserialized: TokenValueMap = archived.deserialize(&mut rkyv::Infallible).unwrap();
assert_eq!(original, deserialized);
Ok(())
}
}