use super::{Error, Kind, Result, Serialize, SerializeArray, SerializerTrait};
use crate::{Bignum, NumCast};
use std::{
cell::{Cell, RefCell},
collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque},
ffi::{CStr, CString},
hash::{BuildHasher, Hash},
num::{
NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128,
NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize,
},
sync::atomic::{
AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicU16, AtomicU32,
AtomicU64, AtomicU8, AtomicUsize, Ordering,
},
};
macro_rules! primitive_int_impl {
($($primitive:ty),* $(,)?) => {
$(impl Serialize for $primitive {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok>
where
S: SerializerTrait
{
if let Some(fixnum) = NumCast::from(*self) {
serializer.serialize_fixnum(fixnum)
} else {
serializer.serialize_bignum(<Bignum as NumCast>::from(*self).unwrap().as_ref())
}
}
})*
};
}
primitive_int_impl! {
u8,
u16,
u32,
u64,
u128,
usize,
i8,
i16,
i32,
i64,
i128,
isize,
}
impl Serialize for f32 {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok>
where
S: SerializerTrait,
{
serializer.serialize_f64((*self).into())
}
}
impl Serialize for f64 {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok>
where
S: SerializerTrait,
{
serializer.serialize_f64(*self)
}
}
impl Serialize for bool {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok>
where
S: SerializerTrait,
{
serializer.serialize_bool(*self)
}
}
impl Serialize for char {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok>
where
S: SerializerTrait,
{
serializer.serialize_rust_string(self.encode_utf8(&mut [0; 4]))
}
}
impl Serialize for str {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok>
where
S: SerializerTrait,
{
serializer.serialize_rust_string(self)
}
}
impl Serialize for String {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok>
where
S: SerializerTrait,
{
serializer.serialize_rust_string(self)
}
}
impl Serialize for CStr {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok>
where
S: SerializerTrait,
{
serializer.serialize_string(self.to_bytes())
}
}
impl Serialize for CString {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok>
where
S: SerializerTrait,
{
serializer.serialize_string(self.to_bytes())
}
}
impl<T> Serialize for Option<T>
where
T: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok>
where
S: SerializerTrait,
{
match self {
Some(value) => value.serialize(serializer),
None => serializer.serialize_nil(),
}
}
}
macro_rules! tuple_impls {
($($len:expr => ($($n:tt $name:ident)+))+) => {
$(
impl<$($name),+> Serialize for ($($name,)+)
where
$($name: Serialize,)+
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok>
where
S: SerializerTrait,
{
let mut array = serializer.serialize_array($len)?;
$(
array.serialize_element(&self.$n)?;
)+
array.end()
}
}
)+
}
}
impl Serialize for () {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok>
where
S: SerializerTrait,
{
serializer.serialize_nil()
}
}
tuple_impls! {
1 => (0 T0)
2 => (0 T0 1 T1)
3 => (0 T0 1 T1 2 T2)
4 => (0 T0 1 T1 2 T2 3 T3)
5 => (0 T0 1 T1 2 T2 3 T3 4 T4)
6 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5)
7 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6)
8 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7)
9 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8)
10 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9)
11 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10)
12 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11)
13 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12)
14 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13)
15 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14)
16 => (0 T0 1 T1 2 T2 3 T3 4 T4 5 T5 6 T6 7 T7 8 T8 9 T9 10 T10 11 T11 12 T12 13 T13 14 T14 15 T15)
}
macro_rules! array_impl {
(
$(#[$attr:meta])*
<$($desc:tt)+
) => {
$(#[$attr])*
impl <$($desc)+
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok>
where
S: SerializerTrait,
{
serializer.collect_array(self)
}
}
};
}
array_impl!(<T> Serialize for [T] where T: Serialize);
array_impl!(<T, const SIZE: usize> Serialize for [T; SIZE] where T: Serialize);
array_impl!(<T> Serialize for Vec<T> where T: Serialize);
array_impl!(<T> Serialize for BinaryHeap<T> where T: Serialize + Ord);
array_impl!(<T> Serialize for BTreeSet<T> where T: Serialize + Ord);
array_impl!(<T, H> Serialize for HashSet<T, H> where T: Serialize + Hash, H: BuildHasher + Default);
array_impl!(<T, H> Serialize for indexmap::IndexSet<T, H> where T: Serialize + Hash, H: BuildHasher);
array_impl!(<T> Serialize for LinkedList<T> where T: Serialize);
array_impl!(<T> Serialize for VecDeque<T> where T: Serialize);
macro_rules! map_impl {
(
$(#[$attr:meta])*
<$($desc:tt)+
) => {
$(#[$attr])*
impl <$($desc)+
{
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok>
where
S: SerializerTrait,
{
serializer.collect_hash(self)
}
}
}
}
map_impl!(<K, V> Serialize for BTreeMap<K, V> where K: Ord + Serialize, V: Serialize);
map_impl!(<K, V, H> Serialize for HashMap<K, V, H> where K: Hash + Serialize, V: Serialize, H: BuildHasher);
map_impl!(<K, V, H> Serialize for indexmap::IndexMap<K, V, H> where K: Hash + Serialize, V: Serialize, H: BuildHasher);
macro_rules! deref_impl {
(
$(#[$attr:meta])*
<$($desc:tt)+
) => {
$(#[$attr])*
impl <$($desc)+ {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok>
where
S: SerializerTrait,
{
(**self).serialize(serializer)
}
}
};
}
deref_impl! {
<'a, T: ?Sized> Serialize for &'a T where T: Serialize
}
deref_impl! {
<'a, T: ?Sized> Serialize for &'a mut T where T: Serialize
}
deref_impl! {
<'a, T: ?Sized> Serialize for std::borrow::Cow<'a, T> where T: Serialize + ToOwned
}
deref_impl! {
<T: ?Sized> Serialize for Box<T> where T: Serialize
}
deref_impl! {
<T: ?Sized> Serialize for std::rc::Rc<T> where T: Serialize
}
deref_impl! {
<T: ?Sized> Serialize for std::sync::Arc<T> where T: Serialize
}
impl<T: ?Sized> Serialize for std::rc::Weak<T>
where
T: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok>
where
S: SerializerTrait,
{
self.upgrade().serialize(serializer)
}
}
impl<T: ?Sized> Serialize for std::sync::Weak<T>
where
T: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok>
where
S: SerializerTrait,
{
self.upgrade().serialize(serializer)
}
}
macro_rules! nonzero_integers {
($($T:ident,)+) => {
$(
impl Serialize for $T {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok>
where
S: SerializerTrait,
{
self.get().serialize(serializer)
}
}
)+
}
}
nonzero_integers! {
NonZeroI8,
NonZeroI16,
NonZeroI32,
NonZeroI64,
NonZeroI128,
NonZeroIsize,
NonZeroU8,
NonZeroU16,
NonZeroU32,
NonZeroU64,
NonZeroU128,
NonZeroUsize,
}
impl<T: Copy> Serialize for Cell<T>
where
T: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok>
where
S: SerializerTrait,
{
self.get().serialize(serializer)
}
}
impl<T: ?Sized> Serialize for RefCell<T>
where
T: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok>
where
S: SerializerTrait,
{
match self.try_borrow() {
Ok(v) => v.serialize(serializer),
Err(_) => Err(Error {
kind: Kind::Message("already mutably borrowed".to_string()),
}),
}
}
}
macro_rules! atomic_impl {
($($ty:ident $size:expr)*) => {
$(
#[cfg(any(target_has_atomic = $size))]
impl Serialize for $ty {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok>
where
S: SerializerTrait,
{
self.load(Ordering::Relaxed).serialize(serializer)
}
}
)*
}
}
atomic_impl! {
AtomicBool "8"
AtomicI8 "8"
AtomicI16 "16"
AtomicI32 "32"
AtomicI64 "64"
AtomicIsize "ptr"
AtomicU8 "8"
AtomicU16 "16"
AtomicU32 "32"
AtomicU64 "64"
AtomicUsize "ptr"
}