use super::super::*;
use super::*;
use serde::{
de::{self, value::Error, DeserializeSeed, IntoDeserializer, Visitor},
forward_to_deserialize_any,
};
impl<'b, 'de: 'b> serde::de::EnumAccess<'de> for BorrowedValue<'b> {
type Error = Error;
type Variant = UnitOnly;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
where
V: de::DeserializeSeed<'de>,
{
let d = self.strict_as_str().into_deserializer();
seed.deserialize(d).map(|v| (v, UnitOnly))
}
}
#[derive(Debug, Clone)]
struct EnumTimestampDeserializer<'b> {
value: BorrowedValue<'b>,
}
#[derive(Debug, Clone)]
struct EnumValueDeserializer<'b> {
value: BorrowedValue<'b>,
}
impl<'de, 'b: 'de> serde::de::EnumAccess<'de> for EnumValueDeserializer<'b> {
type Error = Error;
type Variant = Self;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
where
V: DeserializeSeed<'de>,
{
return seed
.deserialize(self.value.ty().as_variant_str().into_deserializer())
.map(|v| (v, self));
}
}
impl<'de, 'b: 'de> de::VariantAccess<'de> for EnumValueDeserializer<'b> {
type Error = Error;
fn unit_variant(self) -> Result<(), Self::Error> {
Ok(())
}
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
where
T: DeserializeSeed<'de>,
{
seed.deserialize(self.value)
}
fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
todo!()
}
fn struct_variant<V>(
self,
_fields: &'static [&'static str],
_visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
todo!()
}
}
impl<'b, 'de> serde::de::EnumAccess<'de> for EnumTimestampDeserializer<'b> {
type Error = Error;
type Variant = VariantTimestampDeserializer;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
where
V: de::DeserializeSeed<'de>,
{
match &self.value {
BorrowedValue::Timestamp(Timestamp::Microseconds(v)) => Ok((
seed.deserialize("Microseconds".into_deserializer())?,
VariantTimestampDeserializer { value: *v },
)),
BorrowedValue::Timestamp(Timestamp::Milliseconds(v)) => Ok((
seed.deserialize("Milliseconds".into_deserializer())?,
VariantTimestampDeserializer { value: *v },
)),
BorrowedValue::Timestamp(Timestamp::Nanoseconds(v)) => Ok((
seed.deserialize("Nanoseconds".into_deserializer())?,
VariantTimestampDeserializer { value: *v },
)),
_ => todo!(),
}
}
}
impl<'de, 'b: 'de> serde::de::Deserializer<'de> for BorrowedValue<'de> {
type Error = Error;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
use BorrowedValue::*;
match self {
Null(_) => visitor.visit_none(),
Bool(v) => visitor.visit_bool(v),
TinyInt(v) => visitor.visit_i8(v),
SmallInt(v) => visitor.visit_i16(v),
Int(v) => visitor.visit_i32(v),
BigInt(v) => visitor.visit_i64(v),
UTinyInt(v) => visitor.visit_u8(v),
USmallInt(v) => visitor.visit_u16(v),
UInt(v) => visitor.visit_u32(v),
UBigInt(v) => visitor.visit_u64(v),
Float(v) => visitor.visit_f32(v),
Double(v) => visitor.visit_f64(v),
VarChar(v) => visitor.visit_borrowed_str(v),
NChar(v) => match v {
Cow::Borrowed(v) => visitor.visit_borrowed_str(v),
Cow::Owned(v) => visitor.visit_string(v),
},
Json(v) => match v {
Cow::Borrowed(v) => serde_json::Deserializer::from_slice(v)
.deserialize_any(visitor)
.map_err(<Self::Error as de::Error>::custom),
Cow::Owned(v) => serde_json::from_slice::<serde_json::Value>(&v)
.map_err(<Self::Error as de::Error>::custom)?
.into_deserializer()
.deserialize_any(visitor)
.map_err(<Self::Error as de::Error>::custom),
},
Timestamp(v) => visitor.visit_i64(v.as_raw_i64()),
VarBinary(v) | Blob(v) | MediumBlob(v) => visitor.visit_borrowed_bytes(v),
_ => Err(<Self::Error as de::Error>::custom(
"un supported type to deserialize",
)),
}
}
forward_to_deserialize_any! {bool i8 u8 i16 u16 i32 u32 i64 u64 f32 f64 char}
forward_to_deserialize_any! {
bytes byte_buf
tuple identifier
}
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
use BorrowedValue::*;
match self {
Null(_) => visitor.visit_borrowed_str(""), Bool(v) => visitor.visit_string(format!("{v}")),
TinyInt(v) => visitor.visit_string(format!("{v}")),
SmallInt(v) => visitor.visit_string(format!("{v}")),
Int(v) => visitor.visit_string(format!("{v}")),
BigInt(v) => visitor.visit_string(format!("{v}")),
UTinyInt(v) => visitor.visit_string(format!("{v}")),
USmallInt(v) => visitor.visit_string(format!("{v}")),
UInt(v) => visitor.visit_string(format!("{v}")),
UBigInt(v) => visitor.visit_string(format!("{v}")),
Float(v) => visitor.visit_string(format!("{v}")),
Double(v) => visitor.visit_string(format!("{v}")),
Json(v) => match v {
Cow::Borrowed(v) => std::str::from_utf8(v)
.map_err(<Self::Error as serde::de::Error>::custom)
.and_then(|s| visitor.visit_borrowed_str(s)),
Cow::Owned(v) => String::from_utf8(v)
.map_err(<Self::Error as serde::de::Error>::custom)
.and_then(|s| visitor.visit_string(s)),
},
VarChar(v) => visitor.visit_borrowed_str(v),
NChar(v) => match v {
Cow::Borrowed(v) => visitor.visit_borrowed_str(v),
Cow::Owned(v) => visitor.visit_str(&v),
},
Timestamp(v) => visitor.visit_string(v.to_datetime_with_tz().to_rfc3339()),
_ => Err(<Self::Error as de::Error>::custom(
"unsupported type to deserialize",
)),
}
}
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
self.deserialize_str(visitor)
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
if self.is_null() {
visitor.visit_none()
} else {
visitor.visit_some(self)
}
}
fn deserialize_newtype_struct<V>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
use BorrowedValue::*;
macro_rules! _v_ {
($v:expr) => {
visitor.visit_newtype_struct($v.into_deserializer())
};
}
match self {
Null(_) => visitor.visit_none(),
Bool(v) => _v_!(v),
TinyInt(v) => _v_!(v),
SmallInt(v) => _v_!(v),
Int(v) => _v_!(v),
BigInt(v) => _v_!(v),
UTinyInt(v) => _v_!(v),
USmallInt(v) => _v_!(v),
UInt(v) => _v_!(v),
UBigInt(v) => _v_!(v),
Float(v) => _v_!(v),
Double(v) => _v_!(v),
VarChar(v) => _v_!(v),
NChar(v) => _v_!(v),
Json(v) => match v {
Cow::Borrowed(v) => serde_json::Deserializer::from_slice(v)
.deserialize_newtype_struct(_name, visitor)
.map_err(<Self::Error as de::Error>::custom),
Cow::Owned(v) => serde_json::from_slice::<serde_json::Value>(&v)
.map_err(<Self::Error as de::Error>::custom)?
.into_deserializer()
.deserialize_newtype_struct(_name, visitor)
.map_err(<Self::Error as de::Error>::custom),
},
Timestamp(v) => visitor.visit_i64(v.as_raw_i64()),
VarBinary(v) | Blob(v) | MediumBlob(v) => visitor.visit_borrowed_bytes(v),
_ => Err(<Self::Error as de::Error>::custom(
"un supported type to deserialize",
)),
}
}
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
self.deserialize_any(visitor)
}
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: serde::de::Visitor<'de>,
{
use BorrowedValue::*;
match self {
Null(_) => Vec::<u8>::new()
.into_deserializer()
.deserialize_seq(visitor),
Json(v) => v.to_vec().into_deserializer().deserialize_seq(visitor),
Timestamp(_) => todo!(),
VarChar(v) => v
.as_bytes()
.to_vec()
.into_deserializer()
.deserialize_seq(visitor),
NChar(v) => v
.as_bytes()
.to_vec()
.into_deserializer()
.deserialize_seq(visitor),
VarBinary(v) | Blob(v) | MediumBlob(v) => {
v.to_vec().into_deserializer().deserialize_seq(visitor)
}
_ => todo!(),
}
}
fn deserialize_enum<V>(
self,
name: &'static str,
variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
if name == "Timestamp" && variants == TIMESTAMP_VARIANTS {
return visitor.visit_enum(EnumTimestampDeserializer { value: self });
}
if name == "Value" && variants == VALUE_VARIANTS {
return visitor.visit_enum(EnumValueDeserializer {
value: self,
});
}
visitor.visit_enum(self)
}
fn deserialize_struct<V>(
self,
name: &'static str,
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self {
BorrowedValue::Json(v) => match v {
Cow::Borrowed(v) => serde_json::Deserializer::from_slice(v)
.deserialize_struct(name, fields, visitor)
.map_err(<Self::Error as serde::de::Error>::custom),
Cow::Owned(v) => serde_json::from_slice::<serde_json::Value>(&v)
.map_err(<Self::Error as de::Error>::custom)?
.into_deserializer()
.deserialize_struct(name, fields, visitor)
.map_err(<Self::Error as de::Error>::custom),
},
_ => self.deserialize_any(visitor),
}
}
fn deserialize_tuple_struct<V>(
self,
name: &'static str,
len: usize,
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
match self {
BorrowedValue::Json(v) => match v {
Cow::Borrowed(v) => serde_json::Deserializer::from_slice(v)
.deserialize_tuple_struct(name, len, visitor)
.map_err(<Self::Error as serde::de::Error>::custom),
Cow::Owned(v) => serde_json::from_slice::<serde_json::Value>(&v)
.map_err(<Self::Error as de::Error>::custom)?
.into_deserializer()
.deserialize_tuple_struct(name, len, visitor)
.map_err(<Self::Error as de::Error>::custom),
},
_ => self.deserialize_any(visitor),
}
}
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
visitor.visit_unit()
}
fn deserialize_unit_struct<V>(
self,
_: &'static str,
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
visitor.visit_unit()
}
fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
visitor.visit_unit()
}
}
impl<'de> serde::de::IntoDeserializer<'de, Error> for BorrowedValue<'de> {
type Deserializer = Self;
fn into_deserializer(self) -> Self::Deserializer {
self
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn de_value_as_inner() {
use BorrowedValue::*;
macro_rules! _de_value {
($($v:expr, $ty:ty, $tv:expr) *) => {
$(
{
let d = <$ty>::deserialize($v.into_deserializer()).expect("");
assert_eq!(d, $tv);
}
)*
}
}
_de_value!(
Null(Ty::UTinyInt), Option<u8>, None
TinyInt(-1), i8, -1
SmallInt(-1), i16, -1
Int(0x0fff_ffff), i32, 0x0fff_ffff
BigInt(0xffffffff), i64, 0xffffffff
UTinyInt(0xff), u8, 0xff
USmallInt(0xffff), u16, 0xffff
UInt(0x_ffff_ffff), u32, 0x_ffff_ffff
UBigInt(0x_ffff_ffff_ffff_ffff), u64, 0x_ffff_ffff_ffff_ffff
Float(1.0), f32, 1.0
Double(f64::MAX), f64, f64::MAX
VarChar(""), String, "".to_string()
NChar("".into()), String, "".to_string()
Timestamp(crate::Timestamp::Milliseconds(1)), crate::Timestamp, crate::Timestamp::Milliseconds(1)
VarBinary(&[0, 1,2]), Vec<u8>, vec![0, 1, 2]
Blob(&[0, 1,2]), Vec<u8>, vec![0, 1, 2]
MediumBlob(&[0, 1,2]), Vec<u8>, vec![0, 1, 2]
);
}
#[test]
fn de_borrowed_str() {
use serde_json::json;
use BorrowedValue::*;
macro_rules! _de_str {
($v:expr, is_err) => {
assert!(<&str>::deserialize(($v).into_deserializer()).is_err());
};
($v:expr, $tv:expr) => {
assert_eq!(<&str>::deserialize(($v).into_deserializer()).expect("str"), $tv);
};
($($v:expr, $c:ident) *) => {
$(
{
assert!(<&str>::deserialize(($v).into_deserializer()).$c());
}
)*
};
($($v2:expr, is_err) +; $($v:expr, $tv:expr) + ) => {
$(
_de_str!($v2, is_err);
)*
$(
_de_str!($v, $tv);
)*
}
}
_de_str! {
TinyInt(-1), is_err
SmallInt(-1), is_err
Int(-1), is_err
BigInt(-1), is_err
UTinyInt(1), is_err
USmallInt(1), is_err
UInt(1), is_err
UBigInt(1), is_err
Json(json!({ "name": "abc"}).to_string().into_bytes().into()), is_err
Json(json!(1).to_string().into_bytes().into()), is_err
Json(json!(null).to_string().into_bytes().into()), is_err
Json(json!("abc").to_string().into_bytes().into()), is_err
Timestamp(crate::Timestamp::Milliseconds(0)), is_err
;
Null(Ty::VarChar), ""
VarChar("String"), "String"
VarChar("你好,世界"), "你好,世界"
};
}
#[test]
fn de_string() {
use serde_json::json;
use BorrowedValue::*;
macro_rules! _de_str {
($v:expr, is_err) => {
assert!(String::deserialize(($v).into_deserializer()).is_err());
};
($v:expr, $tv:expr) => {
assert_eq!(String::deserialize(($v).into_deserializer()).expect("str"), $tv);
};
($($v:expr, $tv:expr) *) => {
$(_de_str!($v, $tv);)*
};
($($v2:expr, is_err) *; $($v:expr, $tv:expr) * ) => {
$(
_de_str!($v2, is_err);
)*
$(
_de_str!($v, $tv);
)*
}
}
_de_str! {
Null(Ty::VarChar), ""
TinyInt(-1), "-1"
Timestamp(crate::Timestamp::Milliseconds(0)), "1970-01-01T08:00:00+08:00"
VarChar("String"), "String"
VarChar("你好,世界"), "你好,世界"
Json(json!("abc").to_string().into_bytes().into()), json!("abc").to_string()
Json(json!({ "name": "abc"}).to_string().into_bytes().into()), json!({ "name": "abc"}).to_string()
Json(json!(1).to_string().into_bytes().into()), json!(1).to_string()
Json(json!(null).to_string().into_bytes().into()), json!(null).to_string()
};
}
#[test]
fn de_json() {
use serde_json::json;
use BorrowedValue::*;
macro_rules! _de_json {
($v:expr, $ty:ty, $tv:expr) => {{
let d = <$ty>::deserialize(
Json($v.to_string().into_bytes().into()).into_deserializer(),
)
.expect("de json");
assert_eq!(d, $tv);
}};
}
_de_json!(json!("string"), String, json!("string").to_string());
#[derive(Debug, PartialEq, Eq, Deserialize)]
struct Obj {
name: String,
}
_de_json!(
json!({ "name": "string" }),
Obj,
Obj {
name: "string".to_string()
}
);
#[derive(Debug, PartialEq, Eq, Deserialize)]
struct JsonStr(String);
_de_json!(json!("string"), JsonStr, JsonStr("string".to_string()));
}
#[test]
fn de_newtype_struct() {
use serde_json::json;
use BorrowedValue::*;
macro_rules! _de_ty {
($v:expr, $ty:ty, $tv:expr) => {{
let d = <$ty>::deserialize($v.into_deserializer()).expect("de type");
assert_eq!(d, $tv);
}};
}
#[derive(Debug, PartialEq, Eq, Deserialize)]
struct JsonStr(String);
_de_ty!(
Json(json!("string").to_string().into_bytes().into()),
JsonStr,
JsonStr("string".to_string())
);
#[derive(Debug, PartialEq, Eq, Deserialize)]
struct Primi<T>(T);
_de_ty!(
Json(json!(1).to_string().into_bytes().into()),
Primi<i32>,
Primi(1)
);
_de_ty!(TinyInt(1), Primi<i8>, Primi(1));
_de_ty!(SmallInt(1), Primi<i64>, Primi(1));
_de_ty!(Int(1), Primi<i64>, Primi(1));
_de_ty!(BigInt(1), Primi<i64>, Primi(1));
macro_rules! _de_prim {
($v:ident, $ty:ty, $inner:literal) => {
println!(
"ty: {}, prim: {}",
stringify!($v),
std::any::type_name::<$ty>()
);
_de_ty!($v($inner), Primi<$ty>, Primi($inner));
};
}
macro_rules! _de_prim_cross {
($($vty:ident) +, $tt:ty) => {
$(
_de_prim!($vty, $tt, 1);
)*
};
($($ty:ty) +) => {
$(
_de_prim_cross!(TinyInt SmallInt Int BigInt UTinyInt USmallInt UInt UBigInt, $ty);
)*
};
() => {
_de_prim_cross!(i8 i16 i32 i64 u8 u16 u32 u64);
};
}
_de_prim_cross!();
}
}