use std::convert::TryInto;
use std::fmt;
use std::fmt::Debug;
use std::hash::{Hash, Hasher};
use std::ops::Not;
use std::sync::Arc;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::bytes::{vec_to_bytes, vec_u128_from_bytes, vec_u64_to_bytes};
use crate::data_types::{array_type, get_size_in_bits, get_types_vector, ScalarType, Type, BIT};
use crate::errors::Result;
use crate::version::{VersionedData, DATA_VERSION};
#[cfg(feature = "py-binding")]
use pywrapper_macro::{impl_wrapper, struct_wrapper};
#[derive(Clone, Debug, Serialize, Deserialize)]
enum SerializableValueBody {
Bytes(Vec<u8>),
Vector(Vec<SerializableValue>),
}
#[derive(Clone, Debug, Serialize, Deserialize)]
struct SerializableValue {
body: Arc<SerializableValueBody>,
}
impl SerializableValue {
pub fn from_bytes(bytes: Vec<u8>) -> Self {
Self {
body: Arc::new(SerializableValueBody::Bytes(bytes)),
}
}
pub fn from_vector(v: Vec<SerializableValue>) -> Self {
Self {
body: Arc::new(SerializableValueBody::Vector(v)),
}
}
pub fn access<FB, FV, R>(&self, f_bytes: FB, f_vector: FV) -> Result<R>
where
FB: FnOnce(&[u8]) -> Result<R>,
FV: FnOnce(&Vec<SerializableValue>) -> Result<R>,
{
match self.body.as_ref() {
SerializableValueBody::Bytes(bytes) => f_bytes(bytes),
SerializableValueBody::Vector(v) => f_vector(v),
}
}
pub fn from_value(value: &Value) -> Self {
value
.access(
|bytes| Ok(SerializableValue::from_bytes(bytes.to_vec())),
|vector| {
let mut v_new = vec![];
for item in vector {
v_new.push(SerializableValue::from_value(item));
}
Ok(SerializableValue::from_vector(v_new))
},
)
.expect("Error during conversion from Value to SerializableValue!")
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
enum ValueBody {
Bytes(Vec<u8>),
Vector(Vec<Value>),
}
impl Value {
pub fn deep_clone(&self) -> Value {
self.access(
|bytes| Ok(Value::from_bytes(bytes.to_vec())),
|vector| {
let mut v_new = vec![];
for item in vector {
v_new.push(item.deep_clone());
}
Ok(Value::from_vector(v_new))
},
)
.unwrap()
}
pub fn deep_hash<H: Hasher>(&self, state: &mut H) {
match self.body.as_ref() {
ValueBody::Bytes(data) => {
data.hash(state);
}
ValueBody::Vector(elements) => {
for element in elements {
element.deep_hash(state);
}
}
}
}
}
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "py-binding", struct_wrapper)]
pub struct Value {
body: Arc<ValueBody>,
}
impl Serialize for Value {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: Serializer,
{
let versioned_value = self
.to_versioned_data()
.expect("Error during conversion from Value into VersionedData");
versioned_value.serialize(serializer)
}
}
impl<'de> Deserialize<'de> for Value {
fn deserialize<D>(deserializer: D) -> std::result::Result<Value, D::Error>
where
D: Deserializer<'de>,
{
let versioned_value = VersionedData::deserialize(deserializer)?;
if !versioned_value.check_version(DATA_VERSION) {
Err(runtime_error!(
"Value version doesn't match the requirement"
))
.map_err(serde::de::Error::custom)
} else {
let serializable_value =
serde_json::from_str::<SerializableValue>(versioned_value.get_data_string())
.expect("Error during conversion from String to SerializableValue!");
Value::from_serializable_value(serializable_value).map_err(serde::de::Error::custom)
}
}
}
impl fmt::Display for Value {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match serde_json::to_string(&self) {
Ok(s) => write!(f, "{s}"),
Err(_err) => Err(fmt::Error::default()),
}
}
}
fn recursively_pretty_print_value(
val: &Value,
f: &mut fmt::Formatter,
indent: &str,
) -> fmt::Result {
match val.body.as_ref() {
ValueBody::Bytes(bytes) => {
write!(f, "{indent}[")?;
let l = bytes.len();
for byte in &bytes[..usize::min(l, 256)] {
write!(f, "{byte:02x}")?;
}
if l > 256 {
write!(f, "...")?;
}
writeln!(f, "],")?;
}
ValueBody::Vector(vals) => {
writeln!(f, "{indent}[")?;
let l = vals.len();
for val in &vals[..usize::min(l, 8)] {
recursively_pretty_print_value(val, f, &format!("{indent} "))?;
}
if l > 8 {
writeln!(f, "{indent}...")?;
}
writeln!(f, "{indent}],")?;
}
}
Ok(())
}
impl Debug for Value {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
recursively_pretty_print_value(self, f, "")
}
}
#[cfg_attr(feature = "py-binding", impl_wrapper)]
impl Value {
pub fn from_bytes(bytes: Vec<u8>) -> Self {
Self {
body: Arc::new(ValueBody::Bytes(bytes)),
}
}
pub fn from_vector(v: Vec<Value>) -> Self {
Self {
body: Arc::new(ValueBody::Vector(v)),
}
}
#[cfg_attr(not(feature = "py-binding"), allow(dead_code))]
fn get_bytes(&self) -> Option<Vec<u8>> {
self.access(|bytes| Ok(Some(bytes.to_vec())), |_sub_values| Ok(None))
.unwrap()
}
#[cfg_attr(not(feature = "py-binding"), allow(dead_code))]
fn get_sub_values(&self) -> Option<Vec<Value>> {
self.access(|_bytes| Ok(None), |sub_values| Ok(Some(sub_values.clone())))
.unwrap()
}
}
impl Value {
pub fn from_scalar<T: TryInto<u128> + Not<Output = T> + TryInto<u8> + Copy>(
x: T,
st: ScalarType,
) -> Result<Self> {
let v = vec![x];
Ok(Value::from_bytes(vec_to_bytes(&v, st)?))
}
pub fn from_flattened_array<T: TryInto<u128> + Not<Output = T> + TryInto<u8> + Copy>(
x: &[T],
st: ScalarType,
) -> Result<Value> {
Ok(Value::from_bytes(vec_to_bytes(x, st)?))
}
pub fn from_flattened_array_u64<T: TryInto<u64> + Not<Output = T> + TryInto<u8> + Copy>(
x: &[T],
st: ScalarType,
) -> Result<Value> {
Ok(Value::from_bytes(vec_u64_to_bytes(x, st)?))
}
pub fn from_ndarray<T: TryInto<u128> + Not<Output = T> + TryInto<u8> + Copy>(
a: ndarray::ArrayD<T>,
st: ScalarType,
) -> Result<Value> {
match a.as_slice() {
Some(x) => Value::from_flattened_array(x, st),
None => Err(runtime_error!("Not a contiguous ndarray!")),
}
}
pub fn to_u8(&self, st: ScalarType) -> Result<u8> {
Ok(self.to_u128(st)? as u8)
}
pub fn to_bit(&self) -> Result<bool> {
Ok(self.to_flattened_array_u8(array_type(vec![1], BIT))?[0] != 0)
}
pub fn to_i8(&self, st: ScalarType) -> Result<i8> {
Ok(self.to_u128(st)? as i8)
}
pub fn to_u16(&self, st: ScalarType) -> Result<u16> {
Ok(self.to_u128(st)? as u16)
}
pub fn to_i16(&self, st: ScalarType) -> Result<i16> {
Ok(self.to_u128(st)? as i16)
}
pub fn to_u32(&self, st: ScalarType) -> Result<u32> {
Ok(self.to_u128(st)? as u32)
}
pub fn to_i32(&self, st: ScalarType) -> Result<i32> {
Ok(self.to_u128(st)? as i32)
}
pub fn to_u64(&self, st: ScalarType) -> Result<u64> {
Ok(self.to_u128(st)? as u64)
}
pub fn to_i64(&self, st: ScalarType) -> Result<i64> {
Ok(self.to_u128(st)? as i64)
}
pub fn to_u128(&self, st: ScalarType) -> Result<u128> {
let v = self.access_bytes(|bytes| vec_u128_from_bytes(bytes, st))?;
if v.len() != 1 && (v.len() != 8 || st != BIT) {
return Err(runtime_error!("Not a scalar"));
}
Ok(v[0])
}
pub fn to_i128(&self, st: ScalarType) -> Result<i128> {
Ok(self.to_u128(st)? as i128)
}
pub fn to_vector(&self) -> Result<Vec<Value>> {
if let ValueBody::Vector(contents) = self.body.as_ref() {
Ok(contents.clone())
} else {
Err(runtime_error!("Not a vector!"))
}
}
pub fn to_flattened_array_u8(&self, t: Type) -> Result<Vec<u8>> {
Ok(self
.to_flattened_array_u128(t)?
.into_iter()
.map(|x| x as u8)
.collect())
}
pub fn to_flattened_array_i8(&self, t: Type) -> Result<Vec<i8>> {
Ok(self
.to_flattened_array_u128(t)?
.into_iter()
.map(|x| x as i8)
.collect())
}
pub fn to_flattened_array_u16(&self, t: Type) -> Result<Vec<u16>> {
Ok(self
.to_flattened_array_u128(t)?
.into_iter()
.map(|x| x as u16)
.collect())
}
pub fn to_flattened_array_i16(&self, t: Type) -> Result<Vec<i16>> {
Ok(self
.to_flattened_array_u128(t)?
.into_iter()
.map(|x| x as i16)
.collect())
}
pub fn to_flattened_array_u32(&self, t: Type) -> Result<Vec<u32>> {
Ok(self
.to_flattened_array_u128(t)?
.into_iter()
.map(|x| x as u32)
.collect())
}
pub fn to_flattened_array_i32(&self, t: Type) -> Result<Vec<i32>> {
Ok(self
.to_flattened_array_u128(t)?
.into_iter()
.map(|x| x as i32)
.collect())
}
pub fn to_flattened_array_u64(&self, t: Type) -> Result<Vec<u64>> {
Ok(self
.to_flattened_array_u128(t)?
.into_iter()
.map(|x| x as u64)
.collect())
}
pub fn to_flattened_array_i64(&self, t: Type) -> Result<Vec<i64>> {
Ok(self
.to_flattened_array_u128(t)?
.into_iter()
.map(|x| x as i64)
.collect())
}
pub fn to_flattened_array_u128(&self, t: Type) -> Result<Vec<u128>> {
if !t.is_array() {
return Err(runtime_error!(
"Trying to extract array from a value of a wrong type"
));
}
if !self.check_type(t.clone())? {
return Err(runtime_error!("Type and value mismatch"));
}
let st = t.get_scalar_type();
if let ValueBody::Bytes(bytes) = self.body.as_ref() {
let mut result = vec_u128_from_bytes(bytes, st)?;
if st == BIT {
let num_values: u64 = t.get_dimensions().iter().product();
result.truncate(num_values as usize);
}
Ok(result)
} else {
Err(runtime_error!("Invalid Value"))
}
}
pub fn to_flattened_array_i128(&self, t: Type) -> Result<Vec<i128>> {
Ok(self
.to_flattened_array_u128(t)?
.into_iter()
.map(|x| x as i128)
.collect())
}
pub fn check_type(&self, t: Type) -> Result<bool> {
let s = get_size_in_bits(t.clone())?;
match t {
Type::Scalar(_) | Type::Array(_, _) => match self.body.as_ref() {
ValueBody::Bytes(bytes) => Ok(bytes.len() as u64 == (s + 7) / 8),
_ => Ok(false),
},
Type::Vector(_, _) | Type::Tuple(_) | Type::NamedTuple(_) => {
let ts = get_types_vector(t)?;
match self.body.as_ref() {
ValueBody::Vector(children) => {
if ts.len() != children.len() {
return Ok(false);
}
for i in 0..ts.len() {
if !children[i].check_type((*ts[i]).clone())? {
return Ok(false);
}
}
Ok(true)
}
_ => Ok(false),
}
}
}
}
pub fn access_bytes<F, R>(&self, f: F) -> Result<R>
where
F: FnOnce(&[u8]) -> Result<R>,
{
if let ValueBody::Bytes(bytes) = self.body.as_ref() {
f(bytes)
} else {
panic!("Value::access_bytes() on an invalid Value");
}
}
pub fn access_vector<F, R>(&self, f: F) -> Result<R>
where
F: FnOnce(&Vec<Value>) -> Result<R>,
{
if let ValueBody::Vector(v) = self.body.as_ref() {
f(v)
} else {
panic!("Value::access_vector() on an invalid Value");
}
}
pub fn access<FB, FV, R>(&self, f_bytes: FB, f_vector: FV) -> Result<R>
where
FB: FnOnce(&[u8]) -> Result<R>,
FV: FnOnce(&Vec<Value>) -> Result<R>,
{
match self.body.as_ref() {
ValueBody::Bytes(bytes) => f_bytes(bytes),
ValueBody::Vector(v) => f_vector(v),
}
}
pub fn zero_of_type(t: Type) -> Value {
match t {
Type::Scalar(_) | Type::Array(_, _) => {
let s = get_size_in_bits(t.clone()).unwrap();
Value::from_bytes(vec![0; ((s + 7) / 8) as usize])
}
Type::Vector(len, t1) => {
Value::from_vector(vec![Value::zero_of_type((*t1).clone()); len as usize])
}
Type::Tuple(element_types) => Value::from_vector(
element_types
.iter()
.map(|t| Value::zero_of_type((**t).clone()))
.collect(),
),
Type::NamedTuple(element_types) => Value::from_vector(
element_types
.iter()
.map(|(_, t)| Value::zero_of_type((**t).clone()))
.collect(),
),
}
}
pub fn one_of_type(t: Type) -> Result<Value> {
match t {
Type::Scalar(st) => Ok(Value::from_bytes(vec_to_bytes(&[1], st)?)),
Type::Array(shape, st) => {
let n: u64 = shape.iter().product();
Ok(Value::from_bytes(vec_to_bytes(&vec![1; n as usize], st)?))
}
Type::Vector(len, t1) => Ok(Value::from_vector(vec![
Value::one_of_type((*t1).clone())?;
len as usize
])),
Type::Tuple(element_types) => Ok(Value::from_vector(
element_types
.iter()
.map(|t| Value::one_of_type((**t).clone()))
.collect::<Result<_>>()?,
)),
Type::NamedTuple(element_types) => Ok(Value::from_vector(
element_types
.iter()
.map(|(_, t)| Value::one_of_type((**t).clone()))
.collect::<Result<_>>()?,
)),
}
}
fn from_serializable_value(value: SerializableValue) -> Result<Value> {
value.access(
|bytes| Ok(Value::from_bytes(bytes.to_vec())),
|vector| {
let mut v_new = vec![];
for item in vector {
v_new.push(Value::from_serializable_value(item.clone())?);
}
Ok(Value::from_vector(v_new))
},
)
}
fn to_versioned_data(&self) -> Result<VersionedData> {
VersionedData::create_versioned_data(
DATA_VERSION,
serde_json::to_string(&SerializableValue::from_value(self))?,
)
}
}
pub trait ToNdarray<T> {
fn to_ndarray(&self, t: Type) -> Result<ndarray::ArrayD<T>>;
}
impl ToNdarray<u8> for Value {
fn to_ndarray(&self, t: Type) -> Result<ndarray::ArrayD<u8>> {
let arr = ToNdarray::<u64>::to_ndarray(self, t)?;
Ok(arr.map(|x| *x as u8))
}
}
impl ToNdarray<i8> for Value {
fn to_ndarray(&self, t: Type) -> Result<ndarray::ArrayD<i8>> {
let arr = ToNdarray::<u64>::to_ndarray(self, t)?;
Ok(arr.map(|x| *x as i8))
}
}
impl ToNdarray<u16> for Value {
fn to_ndarray(&self, t: Type) -> Result<ndarray::ArrayD<u16>> {
let arr = ToNdarray::<u64>::to_ndarray(self, t)?;
Ok(arr.map(|x| *x as u16))
}
}
impl ToNdarray<i16> for Value {
fn to_ndarray(&self, t: Type) -> Result<ndarray::ArrayD<i16>> {
let arr = ToNdarray::<u64>::to_ndarray(self, t)?;
Ok(arr.map(|x| *x as i16))
}
}
impl ToNdarray<u32> for Value {
fn to_ndarray(&self, t: Type) -> Result<ndarray::ArrayD<u32>> {
let arr = ToNdarray::<u64>::to_ndarray(self, t)?;
Ok(arr.map(|x| *x as u32))
}
}
impl ToNdarray<i32> for Value {
fn to_ndarray(&self, t: Type) -> Result<ndarray::ArrayD<i32>> {
let arr = ToNdarray::<u64>::to_ndarray(self, t)?;
Ok(arr.map(|x| *x as i32))
}
}
impl ToNdarray<u64> for Value {
fn to_ndarray(&self, t: Type) -> Result<ndarray::ArrayD<u64>> {
match t.clone() {
Type::Array(shape, _) => {
let arr = self.to_flattened_array_u64(t)?;
let ndarr = ndarray::Array::from_vec(arr);
let shape: Vec<usize> = shape.iter().map(|x| *x as usize).collect();
Ok(ndarr.into_shape(shape)?)
}
_ => Err(runtime_error!("Not an array type")),
}
}
}
impl ToNdarray<u128> for Value {
fn to_ndarray(&self, t: Type) -> Result<ndarray::ArrayD<u128>> {
match t.clone() {
Type::Array(shape, _) => {
let arr = self.to_flattened_array_u128(t)?;
let ndarr = ndarray::Array::from_vec(arr);
let shape: Vec<usize> = shape.iter().map(|x| *x as usize).collect();
Ok(ndarr.into_shape(shape)?)
}
_ => Err(runtime_error!("Not an array type")),
}
}
}
impl ToNdarray<bool> for Value {
fn to_ndarray(&self, t: Type) -> Result<ndarray::ArrayD<bool>> {
match t.clone() {
Type::Array(shape, _) => {
let arr = self
.to_flattened_array_u8(t)?
.iter()
.map(|x| *x != 0)
.collect();
let ndarr = ndarray::Array::from_vec(arr);
let shape: Vec<usize> = shape.iter().map(|x| *x as usize).collect();
Ok(ndarr.into_shape(shape)?)
}
_ => Err(runtime_error!("Not an array type")),
}
}
}
impl ToNdarray<i64> for Value {
fn to_ndarray(&self, t: Type) -> Result<ndarray::ArrayD<i64>> {
let arr = ToNdarray::<u64>::to_ndarray(self, t)?;
Ok(arr.map(|x| *x as i64))
}
}
impl ToNdarray<i128> for Value {
fn to_ndarray(&self, t: Type) -> Result<ndarray::ArrayD<i128>> {
let arr = ToNdarray::<u128>::to_ndarray(self, t)?;
Ok(arr.map(|x| *x as i128))
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::constants::type_size_limit_constants;
use crate::data_types::{
array_type, named_tuple_type, scalar_type, tuple_type, vector_type, BIT, INT32, INT64,
INT8, UINT16, UINT32, UINT64, UINT8,
};
use std::panic::{catch_unwind, AssertUnwindSafe};
fn check_type_test_worker(v: &Value, t: Type) {
assert!(v.check_type(t).unwrap());
}
fn check_type_test_worker_fail(v: &Value, t: Type) {
assert!(!v.check_type(t).unwrap());
}
#[test]
fn check_type_test() {
let v = Value::from_bytes(vec![0]);
check_type_test_worker(&v, scalar_type(BIT));
check_type_test_worker(&v, scalar_type(UINT8));
check_type_test_worker(&v, scalar_type(INT8));
check_type_test_worker_fail(&v, scalar_type(INT32));
let v = Value::from_bytes(vec![0, 0, 0, 0]);
check_type_test_worker(&v, scalar_type(INT32));
check_type_test_worker_fail(&v, scalar_type(INT64));
let v = Value::from_bytes(vec![0, 0, 0, 0, 0, 0, 0, 0]);
check_type_test_worker(&v, scalar_type(INT64));
let v = Value::from_vector(vec![]);
check_type_test_worker_fail(&v, scalar_type(BIT));
let v = Value::from_vector(vec![
Value::from_bytes(vec![0]),
Value::from_bytes(vec![0, 0, 0, 0]),
]);
check_type_test_worker(&v, tuple_type(vec![scalar_type(BIT), scalar_type(INT32)]));
check_type_test_worker(
&v,
named_tuple_type(vec![
("field 1".to_owned(), scalar_type(BIT)),
("field 2".to_owned(), scalar_type(INT32)),
]),
);
let v = Value::from_vector(vec![Value::from_bytes(vec![0]), Value::from_bytes(vec![0])]);
check_type_test_worker(&v, vector_type(2, scalar_type(BIT)));
check_type_test_worker_fail(&v, tuple_type(vec![]));
let v = Value::from_bytes(vec![0, 0, 0]);
check_type_test_worker_fail(&v, tuple_type(vec![]));
}
#[test]
fn eq_test() {
let a = Value::from_bytes(vec![10, 10]);
let b = Value::from_bytes(vec![10, 10]);
assert_eq!(a, b);
let a = Value::from_vector(vec![Value::from_bytes(vec![10])]);
let b = Value::from_vector(vec![Value::from_bytes(vec![10])]);
assert_eq!(a, b);
let a = Value::from_vector(vec![
Value::from_bytes(vec![10]),
Value::from_bytes(vec![7]),
]);
let b = Value::from_vector(vec![
Value::from_bytes(vec![10]),
Value::from_bytes(vec![10]),
]);
assert!(a != b);
let a = Value::from_vector(vec![
Value::from_bytes(vec![10]),
Value::from_bytes(vec![7]),
]);
let b = Value::from_bytes(vec![10, 10]);
assert!(a != b);
assert!(b != a);
let a = Value::from_vector(vec![Value::from_bytes(vec![10])]);
let b = Value::from_vector(vec![
Value::from_bytes(vec![10]),
Value::from_bytes(vec![10]),
]);
assert!(a != b);
}
#[test]
fn test_get_bytes() {
let v = Value::from_bytes(vec![0, 1, 2, 3]);
v.access_bytes(|bytes| {
assert_eq!(bytes, vec![0, 1, 2, 3]);
Ok(())
})
.unwrap();
let v = Value::from_vector(vec![Value::from_bytes(vec![0]), Value::from_bytes(vec![0])]);
let e = catch_unwind(AssertUnwindSafe(|| v.access_bytes(|_| Ok(()))));
assert!(e.is_err());
}
#[test]
fn test_serialization() {
let v = Value::from_vector(vec![
Value::from_bytes(vec![1, 2, 3, 4, 5]),
Value::from_bytes(vec![6, 7, 8]),
]);
let se = serde_json::to_string(&v).unwrap();
assert_eq!(
se,
format!("{{\"version\":{},\"data\":\"{{\\\"body\\\":{{\\\"Vector\\\":[{{\\\"body\\\":{{\\\"Bytes\\\":[1,2,3,4,5]}}}},{{\\\"body\\\":{{\\\"Bytes\\\":[6,7,8]}}}}]}}}}\"}}", DATA_VERSION)
);
let de: Value = serde_json::from_str(&se).unwrap();
assert_eq!(v, de);
assert!(serde_json::from_str::<Value>("{{{").is_err());
}
#[test]
#[should_panic(expected = "Value version doesn't match the requirement")]
fn test_version_value() {
let invalid_versioned_value = VersionedData::create_versioned_data(
DATA_VERSION - 1,
serde_json::to_string(&SerializableValue::from_vector(vec![
SerializableValue::from_bytes(vec![1, 2, 3, 4, 5]),
SerializableValue::from_bytes(vec![6, 7, 8]),
]))
.unwrap(),
)
.unwrap();
let se = serde_json::to_string(&invalid_versioned_value).unwrap();
let _de: Value = serde_json::from_str(&se).unwrap();
}
#[test]
#[should_panic(expected = "Value version doesn't match the requirement")]
fn test_unsupported_version_value() {
let invalid_versioned_value = VersionedData::create_versioned_data(
DATA_VERSION - 1,
"{\"Unsupported_field\": Unsupported_value}".to_string(),
)
.unwrap();
let se = serde_json::to_string(&invalid_versioned_value).unwrap();
let _de: Value = serde_json::from_str(&se).unwrap();
}
#[test]
fn test_extract_scalar_bit() {
let v = Value::from_scalar(1, BIT).unwrap();
let result = v.to_u64(BIT).unwrap();
assert_eq!(result, 1);
}
#[test]
fn test_create_extract_scalar() {
assert_eq!(Value::from_scalar(0, BIT).unwrap().to_u64(BIT).unwrap(), 0);
assert_eq!(Value::from_scalar(1, BIT).unwrap().to_u64(BIT).unwrap(), 1);
assert_eq!(
Value::from_scalar(-73, INT32)
.unwrap()
.to_i32(INT32)
.unwrap(),
-73
);
assert_eq!(
Value::from_scalar(-73, INT32)
.unwrap()
.to_i32(UINT32)
.unwrap(),
-73
);
assert_eq!(
Value::from_scalar(187263, INT32)
.unwrap()
.to_i32(INT32)
.unwrap(),
187263
);
assert_eq!(
Value::from_scalar(187263, UINT32)
.unwrap()
.to_u32(UINT32)
.unwrap(),
187263
);
assert_eq!(
Value::from_flattened_array(&vec![0, 0, 0, 0, 0, 0, 0, 0], BIT)
.unwrap()
.to_u64(BIT)
.unwrap(),
0
);
assert_eq!(
Value::from_flattened_array(&vec![1, 0, 0, 0, 0, 0, 0, 0], BIT)
.unwrap()
.to_u64(BIT)
.unwrap(),
1
);
assert_eq!(
Value::from_flattened_array(&vec![1, 0, 0, 1, 0, 1, 0, 0], BIT)
.unwrap()
.to_u64(BIT)
.unwrap(),
1
);
assert!(
Value::from_flattened_array(&vec![0, 0, 0, 0, 0, 0, 0, 0, 0], BIT)
.unwrap()
.to_u64(BIT)
.is_err()
);
assert!(Value::from_flattened_array(&vec![123, 456], UINT32)
.unwrap()
.to_u64(UINT32)
.is_err());
}
#[test]
fn test_create_extract_vector() {
let v = Value::from_vector(vec![
Value::from_scalar(0, BIT).unwrap(),
Value::from_scalar(-73, INT32).unwrap(),
]);
let entries = v.to_vector().unwrap();
assert_eq!(entries.len(), 2);
assert_eq!(entries[0].to_u64(BIT).unwrap(), 0);
assert_eq!(entries[1].to_i32(INT32).unwrap(), -73);
assert!(Value::from_scalar(-73, INT32).unwrap().to_vector().is_err());
}
#[test]
fn test_create_extract_array() {
let t = array_type(vec![1], BIT);
assert_eq!(
Value::from_flattened_array(&vec![0], t.get_scalar_type())
.unwrap()
.to_flattened_array_u64(t.clone())
.unwrap(),
vec![0]
);
assert_eq!(
Value::from_flattened_array(&vec![1], t.get_scalar_type())
.unwrap()
.to_flattened_array_u64(t.clone())
.unwrap(),
vec![1]
);
assert_eq!(
Value::from_flattened_array(&vec![1, 0, 0, 1], t.get_scalar_type())
.unwrap()
.to_flattened_array_u64(t.clone())
.unwrap(),
vec![1]
);
assert_eq!(
Value::from_flattened_array(&vec![0, 0, 0, 1, 0, 0, 0, 0], t.get_scalar_type())
.unwrap()
.to_flattened_array_u64(t.clone())
.unwrap(),
vec![0]
);
assert!(Value::from_flattened_array(
&vec![0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1],
t.get_scalar_type()
)
.unwrap()
.to_flattened_array_u64(t.clone())
.is_err());
let t = array_type(vec![3, 3], BIT);
assert_eq!(
Value::from_flattened_array(&vec![0, 1, 1, 0, 1, 0, 0, 1, 0], t.get_scalar_type())
.unwrap()
.to_flattened_array_u64(t.clone())
.unwrap(),
vec![0, 1, 1, 0, 1, 0, 0, 1, 0]
);
assert!(
Value::from_flattened_array(&vec![0, 1, 1, 0, 1, 0, 0, 1], t.get_scalar_type())
.unwrap()
.to_flattened_array_u64(t.clone())
.is_err()
);
assert!(Value::from_flattened_array(
&vec![0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
t.get_scalar_type()
)
.unwrap()
.to_flattened_array_u64(t.clone())
.is_err());
let t = array_type(vec![2, 3], INT32);
assert_eq!(
Value::from_flattened_array(&vec![1, 2, 3, 4, 5, 6], t.get_scalar_type())
.unwrap()
.to_flattened_array_u64(t.clone())
.unwrap(),
vec![1, 2, 3, 4, 5, 6]
);
assert!(
Value::from_flattened_array(&vec![1, 2, 3, 4, 5, 6, 7], t.get_scalar_type())
.unwrap()
.to_flattened_array_u64(t.clone())
.is_err()
);
assert!(
Value::from_flattened_array(&vec![1, 2, 3, 4, 5], t.get_scalar_type())
.unwrap()
.to_flattened_array_u64(t.clone())
.is_err()
);
}
#[test]
fn test_zero_value_of_type() {
let types = vec![
scalar_type(BIT),
scalar_type(INT32),
scalar_type(UINT64),
array_type(vec![2, 3], BIT),
array_type(vec![1, 7], INT32),
array_type(vec![10, 10], UINT64),
tuple_type(vec![]),
tuple_type(vec![scalar_type(BIT), scalar_type(BIT)]),
tuple_type(vec![scalar_type(INT32), scalar_type(BIT)]),
tuple_type(vec![tuple_type(vec![]), array_type(vec![5, 5], INT32)]),
vector_type(10, tuple_type(vec![])),
vector_type(
10,
tuple_type(vec![vector_type(5, scalar_type(INT32)), scalar_type(BIT)]),
),
named_tuple_type(vec![
("field 1".to_string(), scalar_type(BIT)),
("field 2".to_string(), scalar_type(INT32)),
]),
];
for t in types {
assert!(Value::zero_of_type(t.clone())
.check_type(t.clone())
.unwrap());
}
}
#[test]
fn test_one_value_of_type() -> Result<()> {
let types = vec![
scalar_type(BIT),
scalar_type(INT32),
scalar_type(UINT64),
array_type(vec![2, 3], BIT),
array_type(vec![1, 7], INT32),
array_type(vec![10, 10], UINT64),
tuple_type(vec![]),
tuple_type(vec![scalar_type(BIT), scalar_type(BIT)]),
tuple_type(vec![scalar_type(INT32), scalar_type(BIT)]),
tuple_type(vec![tuple_type(vec![]), array_type(vec![5, 5], INT32)]),
vector_type(10, tuple_type(vec![])),
vector_type(
10,
tuple_type(vec![vector_type(5, scalar_type(INT32)), scalar_type(BIT)]),
),
named_tuple_type(vec![
("field 1".to_string(), scalar_type(BIT)),
("field 2".to_string(), scalar_type(INT32)),
]),
];
for t in types {
let v = Value::one_of_type(t.clone())?;
assert!(v.check_type(t.clone())?, "\nvalue: {v:?}\ntype: {t:?}");
}
Ok(())
}
#[test]
fn test_get_types_vector() {
let t = vector_type(100, scalar_type(UINT16));
let result = get_types_vector(t);
assert!(result.is_ok());
let t = vector_type(
type_size_limit_constants::TYPES_VECTOR_LENGTH_LIMIT as u64 + 1,
scalar_type(UINT16),
);
let result = get_types_vector(t);
assert!(result.is_err());
}
#[test]
fn test_deep_clone() {
|| -> Result<()> {
let v = Value::from_vector(vec![
Value::from_scalar(123, INT64)?,
Value::from_flattened_array(&[-1, 1, -2, 2], INT64)?,
]);
let v1 = v.deep_clone();
assert!(!Arc::ptr_eq(&v.body, &v1.body));
let vv = v.to_vector()?;
let vv1 = v1.to_vector()?;
assert_eq!(vv.len(), 2);
assert_eq!(vv1.len(), 2);
assert!(!Arc::ptr_eq(&vv[0].body, &vv1[0].body));
assert!(!Arc::ptr_eq(&vv[1].body, &vv1[1].body));
let vv_a = vv[0].to_i64(INT64)?;
let vv_b = vv[1].to_flattened_array_i64(array_type(vec![2, 2], INT64))?;
let vv1_a = vv1[0].to_i64(INT64)?;
let vv1_b = vv1[1].to_flattened_array_i64(array_type(vec![2, 2], INT64))?;
assert_eq!(vv_a, 123);
assert_eq!(vv_b, &[-1, 1, -2, 2]);
assert_eq!(vv1_a, 123);
assert_eq!(vv1_b, &[-1, 1, -2, 2]);
Ok(())
}()
.unwrap();
}
#[test]
fn test_from_ndarray() {
|| -> Result<()> {
let a = ndarray::Array::from_shape_vec((2, 3), vec![10, -20, 30, 40, -50, 60])?;
let v = Value::from_ndarray(a.into_dyn(), INT32)?;
let b = v.to_flattened_array_i32(array_type(vec![2, 3], INT32))?;
assert_eq!(b, &[10, -20, 30, 40, -50, 60]);
Ok(())
}()
.unwrap();
}
#[test]
fn test_to_scalar() {
|| -> Result<()> {
let v = Value::from_scalar(-123456, INT32)?;
assert_eq!(v.to_u8(INT32)?, (-123456i32) as u8);
assert_eq!(v.to_i8(INT32)?, (-123456i32) as i8);
assert_eq!(v.to_u16(INT32)?, (-123456i32) as u16);
assert_eq!(v.to_i16(INT32)?, (-123456i32) as i16);
assert_eq!(v.to_u32(INT32)?, (-123456i32) as u32);
assert_eq!(v.to_i32(INT32)?, (-123456i32) as i32);
assert_eq!(v.to_u64(INT32)?, (-123456i32) as u64);
assert_eq!(v.to_i64(INT32)?, (-123456i32) as i64);
assert_eq!(Value::from_scalar(156, UINT8)?.to_bit()?, false);
assert_eq!(Value::from_scalar(157, UINT8)?.to_bit()?, true);
Ok(())
}()
.unwrap();
}
#[test]
fn test_to_flattened_array() {
|| -> Result<()> {
let v = Value::from_scalar(-123456, INT32)?;
assert_eq!(
v.to_flattened_array_u8(array_type(vec![1], INT32))?,
&[(-123456i32) as u8]
);
assert_eq!(
v.to_flattened_array_i8(array_type(vec![1], INT32))?,
&[(-123456i32) as i8]
);
assert_eq!(
v.to_flattened_array_u16(array_type(vec![1], INT32))?,
&[(-123456i32) as u16]
);
assert_eq!(
v.to_flattened_array_i16(array_type(vec![1], INT32))?,
&[(-123456i32) as i16]
);
assert_eq!(
v.to_flattened_array_u32(array_type(vec![1], INT32))?,
&[(-123456i32) as u32]
);
assert_eq!(
v.to_flattened_array_i32(array_type(vec![1], INT32))?,
&[(-123456i32) as i32]
);
assert_eq!(
v.to_flattened_array_u64(array_type(vec![1], INT32))?,
&[(-123456i32) as u64]
);
assert_eq!(
v.to_flattened_array_i64(array_type(vec![1], INT32))?,
&[(-123456i32) as i64]
);
Ok(())
}()
.unwrap();
}
#[test]
fn test_to_ndarray() {
|| -> Result<()> {
{
let v = Value::from_scalar(1, BIT)?;
let a = ToNdarray::<bool>::to_ndarray(&v, array_type(vec![1], BIT))?;
assert_eq!(a.shape(), &[1]);
assert_eq!(a[[0]], true);
}
{
let v = Value::from_scalar(0, BIT)?;
let a = ToNdarray::<bool>::to_ndarray(&v, array_type(vec![1], BIT))?;
assert_eq!(a.shape(), &[1]);
assert_eq!(a[[0]], false);
}
let v = Value::from_scalar(-123456, INT32)?;
{
let a = ToNdarray::<u8>::to_ndarray(&v, array_type(vec![1], INT32))?;
assert_eq!(a.shape(), &[1]);
assert_eq!(a[[0]], -123456i32 as u8);
}
{
let a = ToNdarray::<i8>::to_ndarray(&v, array_type(vec![1], INT32))?;
assert_eq!(a.shape(), &[1]);
assert_eq!(a[[0]], -123456i32 as i8);
}
{
let a = ToNdarray::<u16>::to_ndarray(&v, array_type(vec![1], INT32))?;
assert_eq!(a.shape(), &[1]);
assert_eq!(a[[0]], -123456i32 as u16);
}
{
let a = ToNdarray::<i16>::to_ndarray(&v, array_type(vec![1], INT32))?;
assert_eq!(a.shape(), &[1]);
assert_eq!(a[[0]], -123456i32 as i16);
}
{
let a = ToNdarray::<u32>::to_ndarray(&v, array_type(vec![1], INT32))?;
assert_eq!(a.shape(), &[1]);
assert_eq!(a[[0]], -123456i32 as u32);
}
{
let a = ToNdarray::<i32>::to_ndarray(&v, array_type(vec![1], INT32))?;
assert_eq!(a.shape(), &[1]);
assert_eq!(a[[0]], -123456i32 as i32);
}
{
let a = ToNdarray::<u64>::to_ndarray(&v, array_type(vec![1], INT32))?;
assert_eq!(a.shape(), &[1]);
assert_eq!(a[[0]], -123456i32 as u64);
}
{
let a = ToNdarray::<i64>::to_ndarray(&v, array_type(vec![1], INT32))?;
assert_eq!(a.shape(), &[1]);
assert_eq!(a[[0]], -123456i32 as i64);
}
Ok(())
}()
.unwrap();
}
}