use crate::Row;
use crate::row::Primitive;
use serde::{Deserialize, Serialize};
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Timestamp32(u32);
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Timestamp64(u64);
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Time32(i32);
impl Primitive for Time32 {}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Time64(i64);
impl Primitive for Time64 {}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct FixedPoint64(i64);
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct FixedPoint128(i128);
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Sample<'a> {
int8: i8,
int32: i32,
int64: i64,
uint8: u8,
uint32: u32,
uint64: u64,
float32: f32,
float64: f64,
datetime: Timestamp32,
datetime64: Timestamp64,
time32: Time32,
time64: Time64,
decimal64: FixedPoint64,
decimal128: FixedPoint128,
string: &'a str,
#[serde(with = "serde_bytes")]
blob: &'a [u8],
optional_decimal64: Option<FixedPoint64>,
optional_datetime: Option<Timestamp32>,
fixed_string: [u8; 4],
array: Vec<i8>,
boolean: bool,
}
impl Row for Sample<'_> {
const NAME: &'static str = "Sample";
const COLUMN_NAMES: &'static [&'static str] = &[
"int8",
"int32",
"int64",
"uint8",
"uint32",
"uint64",
"float32",
"float64",
"datetime",
"datetime64",
"time32",
"time64",
"decimal64",
"decimal128",
"string",
"blob",
"optional_decimal64",
"optional_datetime",
"fixed_string",
"array",
"boolean",
];
const COLUMN_COUNT: usize = 21;
const KIND: crate::row::RowKind = crate::row::RowKind::Struct;
type Value<'a> = Sample<'a>;
}
fn sample() -> Sample<'static> {
Sample {
int8: -42,
int32: -3242,
int64: -6442,
uint8: 42,
uint32: 3242,
uint64: 6442,
float32: 42.42,
float64: 42.42,
datetime: Timestamp32(2_301_990_162),
datetime64: Timestamp64(2_301_990_162_123),
time32: Time32(42_000), time64: Time64(42_000_000_000), decimal64: FixedPoint64(4242 * 10_000_000),
decimal128: FixedPoint128(4242 * 10_000_000),
string: "01234",
blob: &[0, 1, 2, 3, 4],
optional_decimal64: None,
optional_datetime: Some(Timestamp32(2_301_990_162)),
fixed_string: [b'B', b'T', b'C', 0],
array: vec![-42, 42, -42, 42],
boolean: true,
}
}
fn sample_serialized() -> Vec<u8> {
vec![
0xd6, 0x56, 0xf3, 0xff, 0xff, 0xd6, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2a, 0xaa, 0x0c, 0x00, 0x00, 0x2a, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xae, 0x29, 0x42, 0xf6, 0x28, 0x5c, 0x8f, 0xc2, 0x35, 0x45, 0x40, 0x12, 0x95, 0x35, 0x89, 0xcb, 0x4e, 0x4e, 0xf9, 0x17, 0x02, 0x00, 0x00, 0x10, 0xa4, 0x00, 0x00, 0x00, 0x24, 0x65, 0xc7, 0x09, 0x00, 0x00, 0x00, 0x00, 0xd5, 0x6d, 0xe0, 0x09, 0x00, 0x00, 0x00, 0x00, 0xd5, 0x6d, 0xe0, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x30, 0x31, 0x32, 0x33, 0x34, 0x05, 0x00, 0x01, 0x02, 0x03, 0x04, 0x01, 0x00, 0x12, 0x95, 0x35, 0x89, 0x42, 0x54, 0x43, 0x00, 0x04, 0xd6, 0x2a, 0xd6, 0x2a, 0x01, ]
}
#[test]
fn it_serializes() {
let mut actual = Vec::new();
super::serialize_row_binary(&mut actual, &sample()).unwrap();
assert_eq!(actual, sample_serialized());
}
#[test]
fn it_deserializes() {
let input = sample_serialized();
for i in 0..input.len() {
let (mut left, mut right) = input.split_at(i);
let _: Result<Sample<'_>, _> = super::deserialize_row(&mut left, None);
let _: Result<Sample<'_>, _> = super::deserialize_row(&mut right, None);
let actual: Sample<'_> = super::deserialize_row(&mut input.as_slice(), None).unwrap();
assert_eq!(actual, sample());
}
}
#[test]
fn it_serializes_time64() {
let value = 42_000_000_000;
let time64 = Time64(value);
println!("Time64 value: {}", time64.0);
let mut actual = Vec::new();
super::serialize_row_binary(&mut actual, &time64).unwrap();
let expected = value.to_le_bytes();
assert_eq!(actual, expected, "Time64 serialization mismatch");
}
#[test]
fn it_deserializes_time64() {
let value_bytes = 42_000_000_000_i64.to_le_bytes();
let time64 = { Time64(i64::from_le_bytes(value_bytes)) };
assert_eq!(time64.0, 42_000_000_000, "Time deserialization mismatch");
}
#[test]
fn it_serializes_time32() {
let value = 42_000;
let time32 = Time32(value);
let mut actual = Vec::new();
super::serialize_row_binary(&mut actual, &time32).unwrap();
let expected = value.to_le_bytes();
assert_eq!(actual, expected, "Time32 serialization mismatch");
}
#[test]
fn it_deserializes_time32() {
let value_bytes = 42_000_i32.to_le_bytes();
let time64 = { Time32(i32::from_le_bytes(value_bytes)) };
assert_eq!(time64.0, 42_000, "Time deserialization mismatch");
}
#[test]
fn it_serializes_option_time32_some() {
let value = 42_000;
let time: Option<Time32> = Some(Time32(value));
let mut actual = Vec::new();
super::serialize_row_binary(&mut actual, &time).unwrap();
let mut expected = vec![0x00];
expected.extend_from_slice(&value.to_le_bytes());
assert_eq!(
actual, expected,
"Option<Time32> (Some) serialization mismatch"
);
}
#[cfg(feature = "chrono")]
#[test]
fn it_serializes_time32_overflow_fails() {
use crate::serde::chrono::time;
use chrono::Duration;
let value = Duration::seconds(i64::from(i32::MAX) + 1);
let result = time::serialize(&value, serde_json::value::Serializer);
assert!(result.is_err(), "Expected error due to overflow");
let err = result.unwrap_err().to_string();
assert!(
err.contains("cannot be represented as Time"),
"Unexpected error message: {err}"
);
}
#[cfg(feature = "time")]
#[test]
fn it_time_serializes_time64_millis_overflow_fails() {
use crate::serde::time::time64::millis;
use time::Duration;
let value = Duration::milliseconds(i64::MAX) + Duration::milliseconds(1);
let result = millis::serialize(&value, serde_json::value::Serializer);
assert!(
result.is_err(),
"Expected error due to milliseconds overflow"
);
let err = result.unwrap_err().to_string();
assert!(
err.contains("milliseconds too large for i64"),
"Unexpected error message: {err}"
);
}
#[cfg(feature = "time")]
#[test]
fn it_time_serializes_time64_micros_overflow_fails() {
use crate::serde::time::time64::micros;
use time::Duration;
let value = Duration::microseconds(i64::MAX) + Duration::microseconds(1);
let result = micros::serialize(&value, serde_json::value::Serializer);
assert!(
result.is_err(),
"Expected error due to microseconds overflow"
);
let err = result.unwrap_err().to_string();
assert!(
err.contains("microseconds too large for i64"),
"Unexpected error message: {err}"
);
}
#[cfg(feature = "time")]
#[test]
fn it_time_serializes_time64_nanos_overflow_fails() {
use crate::serde::time::time64::nanos;
use time::Duration;
let value = Duration::nanoseconds(i64::MAX) + Duration::nanoseconds(1);
let result = nanos::serialize(&value, serde_json::value::Serializer);
assert!(
result.is_err(),
"Expected error due to nanoseconds overflow"
);
let err = result.unwrap_err().to_string();
assert!(
err.contains("nanoseconds too large for i64"),
"Unexpected error message: {err}"
);
}