#![allow(clippy::cast_lossless, clippy::trivially_copy_pass_by_ref)]

use serde::de::{self, MapAccess, Unexpected, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};

use std::prelude::v1::*;
use std::collections::{BTreeMap, HashMap};
use std::fmt;
use std::marker::PhantomData;

use serde_test::{
    assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, assert_ser_tokens_error,
    assert_tokens, Token,
};

trait MyDefault: Sized {
    fn my_default() -> Self;
}

trait ShouldSkip: Sized {
    fn should_skip(&self) -> bool;
}

trait SerializeWith: Sized {
    fn serialize_with<S>(&self, ser: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer;
}

trait DeserializeWith: Sized {
    fn deserialize_with<'de, D>(de: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>;
}

impl MyDefault for i32 {
    fn my_default() -> Self {
        123
    }
}

impl ShouldSkip for i32 {
    fn should_skip(&self) -> bool {
        *self == 123
    }
}

impl SerializeWith for i32 {
    fn serialize_with<S>(&self, ser: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        if *self == 123 {
            true.serialize(ser)
        } else {
            false.serialize(ser)
        }
    }
}

impl DeserializeWith for i32 {
    fn deserialize_with<'de, D>(de: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        if Deserialize::deserialize(de)? {
            Ok(123)
        } else {
            Ok(2)
        }
    }
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct DefaultStruct<A, B, C, D, E>
where
    C: MyDefault,
    E: MyDefault,
{
    a1: A,
    #[serde(default)]
    a2: B,
    #[serde(default = "MyDefault::my_default")]
    a3: C,
    #[serde(skip_deserializing)]
    a4: D,
    #[serde(skip_deserializing, default = "MyDefault::my_default")]
    a5: E,
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct DefaultTupleStruct<A, B, C>(
    A,
    #[serde(default)] B,
    #[serde(default = "MyDefault::my_default")] C,
)
where
    C: MyDefault;

#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct CollectOther {
    a: u32,
    b: u32,
    #[serde(flatten)]
    extra: HashMap<String, u32>,
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct FlattenStructEnumWrapper {
    #[serde(flatten)]
    data: FlattenStructEnum,
    #[serde(flatten)]
    extra: HashMap<String, String>,
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
enum FlattenStructEnum {
    InsertInteger { index: u32, value: u32 },
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct FlattenStructTagContentEnumWrapper {
    outer: u32,
    #[serde(flatten)]
    data: FlattenStructTagContentEnumNewtype,
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct FlattenStructTagContentEnumNewtype(pub FlattenStructTagContentEnum);

#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case", tag = "type", content = "value")]
enum FlattenStructTagContentEnum {
    InsertInteger { index: u32, value: u32 },
    NewtypeVariant(FlattenStructTagContentEnumNewtypeVariant),
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct FlattenStructTagContentEnumNewtypeVariant {
    value: u32,
}

//#[test]
pub fn test_default_struct() {
    assert_de_tokens(
        &DefaultStruct {
            a1: 1,
            a2: 2,
            a3: 3,
            a4: 0,
            a5: 123,
        },
        &[
            Token::Struct {
                name: "DefaultStruct",
                len: 3,
            },
            Token::Str("a1"),
            Token::I32(1),
            Token::Str("a2"),
            Token::I32(2),
            Token::Str("a3"),
            Token::I32(3),
            Token::Str("a4"),
            Token::I32(4),
            Token::Str("a5"),
            Token::I32(5),
            Token::StructEnd,
        ],
    );

    assert_de_tokens(
        &DefaultStruct {
            a1: 1,
            a2: 0,
            a3: 123,
            a4: 0,
            a5: 123,
        },
        &[
            Token::Struct {
                name: "DefaultStruct",
                len: 3,
            },
            Token::Str("a1"),
            Token::I32(1),
            Token::StructEnd,
        ],
    );
}

//#[test]
pub fn test_default_tuple() {
    assert_de_tokens(
        &DefaultTupleStruct(1, 2, 3),
        &[
            Token::TupleStruct {
                name: "DefaultTupleStruct",
                len: 3,
            },
            Token::I32(1),
            Token::I32(2),
            Token::I32(3),
            Token::TupleStructEnd,
        ],
    );

    assert_de_tokens(
        &DefaultTupleStruct(1, 0, 123),
        &[
            Token::TupleStruct {
                name: "DefaultTupleStruct",
                len: 3,
            },
            Token::I32(1),
            Token::TupleStructEnd,
        ],
    );
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
enum DefaultStructVariant<A, B, C, D, E>
where
    C: MyDefault,
    E: MyDefault,
{
    Struct {
        a1: A,
        #[serde(default)]
        a2: B,
        #[serde(default = "MyDefault::my_default")]
        a3: C,
        #[serde(skip_deserializing)]
        a4: D,
        #[serde(skip_deserializing, default = "MyDefault::my_default")]
        a5: E,
    },
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
enum DefaultTupleVariant<A, B, C>
where
    C: MyDefault,
{
    Tuple(
        A,
        #[serde(default)] B,
        #[serde(default = "MyDefault::my_default")] C,
    ),
}

//#[test]
pub fn test_default_struct_variant() {
    assert_de_tokens(
        &DefaultStructVariant::Struct {
            a1: 1,
            a2: 2,
            a3: 3,
            a4: 0,
            a5: 123,
        },
        &[
            Token::StructVariant {
                name: "DefaultStructVariant",
                variant: "Struct",
                len: 3,
            },
            Token::Str("a1"),
            Token::I32(1),
            Token::Str("a2"),
            Token::I32(2),
            Token::Str("a3"),
            Token::I32(3),
            Token::Str("a4"),
            Token::I32(4),
            Token::Str("a5"),
            Token::I32(5),
            Token::StructVariantEnd,
        ],
    );

    assert_de_tokens(
        &DefaultStructVariant::Struct {
            a1: 1,
            a2: 0,
            a3: 123,
            a4: 0,
            a5: 123,
        },
        &[
            Token::StructVariant {
                name: "DefaultStructVariant",
                variant: "Struct",
                len: 3,
            },
            Token::Str("a1"),
            Token::I32(1),
            Token::StructVariantEnd,
        ],
    );
}

//#[test]
pub fn test_default_tuple_variant() {
    assert_de_tokens(
        &DefaultTupleVariant::Tuple(1, 2, 3),
        &[
            Token::TupleVariant {
                name: "DefaultTupleVariant",
                variant: "Tuple",
                len: 3,
            },
            Token::I32(1),
            Token::I32(2),
            Token::I32(3),
            Token::TupleVariantEnd,
        ],
    );

    assert_de_tokens(
        &DefaultTupleVariant::Tuple(1, 0, 123),
        &[
            Token::TupleVariant {
                name: "DefaultTupleVariant",
                variant: "Tuple",
                len: 3,
            },
            Token::I32(1),
            Token::TupleVariantEnd,
        ],
    );
}

// Does not implement std::default::Default.
#[derive(Debug, PartialEq, Deserialize)]
struct NoStdDefault(i8);

impl MyDefault for NoStdDefault {
    fn my_default() -> Self {
        NoStdDefault(123)
    }
}

#[derive(Debug, PartialEq, Deserialize)]
struct ContainsNoStdDefault<A: MyDefault> {
    #[serde(default = "MyDefault::my_default")]
    a: A,
}

// Tests that a struct field does not need to implement std::default::Default if
// it is annotated with `default=...`.
//#[test]
pub fn test_no_std_default() {
    assert_de_tokens(
        &ContainsNoStdDefault {
            a: NoStdDefault(123),
        },
        &[
            Token::Struct {
                name: "ContainsNoStdDefault",
                len: 1,
            },
            Token::StructEnd,
        ],
    );

    assert_de_tokens(
        &ContainsNoStdDefault { a: NoStdDefault(8) },
        &[
            Token::Struct {
                name: "ContainsNoStdDefault",
                len: 1,
            },
            Token::Str("a"),
            Token::NewtypeStruct {
                name: "NoStdDefault",
            },
            Token::I8(8),
            Token::StructEnd,
        ],
    );
}

// Does not implement Deserialize.
#[derive(Debug, PartialEq)]
struct NotDeserializeStruct(i8);

impl Default for NotDeserializeStruct {
    fn default() -> Self {
        NotDeserializeStruct(123)
    }
}

impl DeserializeWith for NotDeserializeStruct {
    fn deserialize_with<'de, D>(_: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        panic!()
    }
}

// Does not implement Deserialize.
#[derive(Debug, PartialEq)]
enum NotDeserializeEnum {
    Trouble,
}

impl MyDefault for NotDeserializeEnum {
    fn my_default() -> Self {
        NotDeserializeEnum::Trouble
    }
}

#[derive(Debug, PartialEq, Deserialize)]
struct ContainsNotDeserialize<A, B, C: DeserializeWith, E: MyDefault> {
    #[serde(skip_deserializing)]
    a: A,
    #[serde(skip_deserializing, default)]
    b: B,
    #[serde(deserialize_with = "DeserializeWith::deserialize_with", default)]
    c: C,
    #[serde(skip_deserializing, default = "MyDefault::my_default")]
    e: E,
}

// Tests that a struct field does not need to implement Deserialize if it is
// annotated with skip_deserializing, whether using the std Default or a
// custom default.
//#[test]
pub fn test_elt_not_deserialize() {
    assert_de_tokens(
        &ContainsNotDeserialize {
            a: NotDeserializeStruct(123),
            b: NotDeserializeStruct(123),
            c: NotDeserializeStruct(123),
            e: NotDeserializeEnum::Trouble,
        },
        &[
            Token::Struct {
                name: "ContainsNotDeserialize",
                len: 1,
            },
            Token::StructEnd,
        ],
    );
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
struct DenyUnknown {
    a1: i32,
}

//#[test]
pub fn test_ignore_unknown() {
    // 'Default' allows unknown. Basic smoke test of ignore...
    assert_de_tokens(
        &DefaultStruct {
            a1: 1,
            a2: 2,
            a3: 3,
            a4: 0,
            a5: 123,
        },
        &[
            Token::Struct {
                name: "DefaultStruct",
                len: 3,
            },
            Token::Str("whoops1"),
            Token::I32(2),
            Token::Str("a1"),
            Token::I32(1),
            Token::Str("whoops2"),
            Token::Seq { len: Some(1) },
            Token::I32(2),
            Token::SeqEnd,
            Token::Str("a2"),
            Token::I32(2),
            Token::Str("whoops3"),
            Token::I32(2),
            Token::Str("a3"),
            Token::I32(3),
            Token::StructEnd,
        ],
    );

    assert_de_tokens_error::<DenyUnknown>(
        &[
            Token::Struct {
                name: "DenyUnknown",
                len: 1,
            },
            Token::Str("a1"),
            Token::I32(1),
            Token::Str("whoops"),
        ],
        "unknown field `whoops`, expected `a1`",
    );
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename = "Superhero")]
struct RenameStruct {
    a1: i32,
    #[serde(rename = "a3")]
    a2: i32,
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename(serialize = "SuperheroSer", deserialize = "SuperheroDe"))]
struct RenameStructSerializeDeserialize {
    a1: i32,
    #[serde(rename(serialize = "a4", deserialize = "a5"))]
    a2: i32,
}

#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
struct AliasStruct {
    a1: i32,
    #[serde(alias = "a3")]
    a2: i32,
    #[serde(alias = "a5", rename = "a6")]
    a4: i32,
}

//#[test]
pub fn test_rename_struct() {
    assert_tokens(
        &RenameStruct { a1: 1, a2: 2 },
        &[
            Token::Struct {
                name: "Superhero",
                len: 2,
            },
            Token::Str("a1"),
            Token::I32(1),
            Token::Str("a3"),
            Token::I32(2),
            Token::StructEnd,
        ],
    );

    assert_ser_tokens(
        &RenameStructSerializeDeserialize { a1: 1, a2: 2 },
        &[
            Token::Struct {
                name: "SuperheroSer",
                len: 2,
            },
            Token::Str("a1"),
            Token::I32(1),
            Token::Str("a4"),
            Token::I32(2),
            Token::StructEnd,
        ],
    );

    assert_de_tokens(
        &RenameStructSerializeDeserialize { a1: 1, a2: 2 },
        &[
            Token::Struct {
                name: "SuperheroDe",
                len: 2,
            },
            Token::Str("a1"),
            Token::I32(1),
            Token::Str("a5"),
            Token::I32(2),
            Token::StructEnd,
        ],
    );

    assert_de_tokens(
        &AliasStruct {
            a1: 1,
            a2: 2,
            a4: 3,
        },
        &[
            Token::Struct {
                name: "AliasStruct",
                len: 3,
            },
            Token::Str("a1"),
            Token::I32(1),
            Token::Str("a2"),
            Token::I32(2),
            Token::Str("a5"),
            Token::I32(3),
            Token::StructEnd,
        ],
    );

    assert_de_tokens(
        &AliasStruct {
            a1: 1,
            a2: 2,
            a4: 3,
        },
        &[
            Token::Struct {
                name: "AliasStruct",
                len: 3,
            },
            Token::Str("a1"),
            Token::I32(1),
            Token::Str("a3"),
            Token::I32(2),
            Token::Str("a6"),
            Token::I32(3),
            Token::StructEnd,
        ],
    );
}

//#[test]
pub fn test_unknown_field_rename_struct() {
    assert_de_tokens_error::<AliasStruct>(
        &[
            Token::Struct {
                name: "AliasStruct",
                len: 3,
            },
            Token::Str("a1"),
            Token::I32(1),
            Token::Str("a3"),
            Token::I32(2),
            Token::Str("a4"),
            Token::I32(3),
        ],
        "unknown field `a4`, expected one of `a1`, `a2`, `a6`",
    );
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename = "Superhero")]
enum RenameEnum {
    #[serde(rename = "bruce_wayne")]
    Batman,
    #[serde(rename = "clark_kent")]
    Superman(i8),
    #[serde(rename = "diana_prince")]
    WonderWoman(i8, i8),
    #[serde(rename = "barry_allan")]
    Flash {
        #[serde(rename = "b")]
        a: i32,
    },
}

#[derive(Debug, PartialEq, Deserialize, Serialize)]
#[serde(rename(serialize = "SuperheroSer", deserialize = "SuperheroDe"))]
enum RenameEnumSerializeDeserialize<A> {
    #[serde(rename(serialize = "dick_grayson", deserialize = "jason_todd"))]
    Robin {
        a: i8,
        #[serde(rename(serialize = "c"))]
        #[serde(rename(deserialize = "d"))]
        b: A,
    },
}

#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
enum AliasEnum {
    #[serde(rename = "sailor_moon", alias = "usagi_tsukino")]
    SailorMoon {
        a: i8,
        #[serde(alias = "c")]
        b: i8,
        #[serde(alias = "e", rename = "f")]
        d: i8,
    },
}

//#[test]
pub fn test_rename_enum() {
    assert_tokens(
        &RenameEnum::Batman,
        &[Token::UnitVariant {
            name: "Superhero",
            variant: "bruce_wayne",
        }],
    );

    assert_tokens(
        &RenameEnum::Superman(0),
        &[
            Token::NewtypeVariant {
                name: "Superhero",
                variant: "clark_kent",
            },
            Token::I8(0),
        ],
    );

    assert_tokens(
        &RenameEnum::WonderWoman(0, 1),
        &[
            Token::TupleVariant {
                name: "Superhero",
                variant: "diana_prince",
                len: 2,
            },
            Token::I8(0),
            Token::I8(1),
            Token::TupleVariantEnd,
        ],
    );

    assert_tokens(
        &RenameEnum::Flash { a: 1 },
        &[
            Token::StructVariant {
                name: "Superhero",
                variant: "barry_allan",
                len: 1,
            },
            Token::Str("b"),
            Token::I32(1),
            Token::StructVariantEnd,
        ],
    );

    assert_ser_tokens(
        &RenameEnumSerializeDeserialize::Robin {
            a: 0,
            b: String::new(),
        },
        &[
            Token::StructVariant {
                name: "SuperheroSer",
                variant: "dick_grayson",
                len: 2,
            },
            Token::Str("a"),
            Token::I8(0),
            Token::Str("c"),
            Token::Str(""),
            Token::StructVariantEnd,
        ],
    );

    assert_de_tokens(
        &RenameEnumSerializeDeserialize::Robin {
            a: 0,
            b: String::new(),
        },
        &[
            Token::StructVariant {
                name: "SuperheroDe",
                variant: "jason_todd",
                len: 2,
            },
            Token::Str("a"),
            Token::I8(0),
            Token::Str("d"),
            Token::Str(""),
            Token::StructVariantEnd,
        ],
    );

    assert_de_tokens(
        &AliasEnum::SailorMoon { a: 0, b: 1, d: 2 },
        &[
            Token::StructVariant {
                name: "AliasEnum",
                variant: "sailor_moon",
                len: 3,
            },
            Token::Str("a"),
            Token::I8(0),
            Token::Str("b"),
            Token::I8(1),
            Token::Str("e"),
            Token::I8(2),
            Token::StructVariantEnd,
        ],
    );

    assert_de_tokens(
        &AliasEnum::SailorMoon { a: 0, b: 1, d: 2 },
        &[
            Token::StructVariant {
                name: "AliasEnum",
                variant: "usagi_tsukino",
                len: 3,
            },
            Token::Str("a"),
            Token::I8(0),
            Token::Str("c"),
            Token::I8(1),
            Token::Str("f"),
            Token::I8(2),
            Token::StructVariantEnd,
        ],
    );
}

//#[test]
pub fn test_unknown_field_rename_enum() {
    assert_de_tokens_error::<AliasEnum>(
        &[Token::StructVariant {
            name: "AliasEnum",
            variant: "SailorMoon",
            len: 3,
        }],
        "unknown variant `SailorMoon`, expected `sailor_moon`",
    );

    assert_de_tokens_error::<AliasEnum>(
        &[
            Token::StructVariant {
                name: "AliasEnum",
                variant: "usagi_tsukino",
                len: 3,
            },
            Token::Str("a"),
            Token::I8(0),
            Token::Str("c"),
            Token::I8(1),
            Token::Str("d"),
            Token::I8(2),
        ],
        "unknown field `d`, expected one of `a`, `b`, `f`",
    );
}

#[derive(Debug, PartialEq, Serialize)]
struct SkipSerializingStruct<'a, B, C>
where
    C: ShouldSkip,
{
    a: &'a i8,
    #[serde(skip_serializing)]
    b: B,
    #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
    c: C,
}

//#[test]
pub fn test_skip_serializing_struct() {
    let a = 1;
    assert_ser_tokens(
        &SkipSerializingStruct { a: &a, b: 2, c: 3 },
        &[
            Token::Struct {
                name: "SkipSerializingStruct",
                len: 2,
            },
            Token::Str("a"),
            Token::I8(1),
            Token::Str("c"),
            Token::I32(3),
            Token::StructEnd,
        ],
    );

    assert_ser_tokens(
        &SkipSerializingStruct {
            a: &a,
            b: 2,
            c: 123,
        },
        &[
            Token::Struct {
                name: "SkipSerializingStruct",
                len: 1,
            },
            Token::Str("a"),
            Token::I8(1),
            Token::StructEnd,
        ],
    );
}

#[derive(Debug, PartialEq, Serialize)]
struct SkipSerializingTupleStruct<'a, B, C>(
    &'a i8,
    #[serde(skip_serializing)] B,
    #[serde(skip_serializing_if = "ShouldSkip::should_skip")] C,
)
where
    C: ShouldSkip;

//#[test]
pub fn test_skip_serializing_tuple_struct() {
    let a = 1;
    assert_ser_tokens(
        &SkipSerializingTupleStruct(&a, 2, 3),
        &[
            Token::TupleStruct {
                name: "SkipSerializingTupleStruct",
                len: 2,
            },
            Token::I8(1),
            Token::I32(3),
            Token::TupleStructEnd,
        ],
    );

    assert_ser_tokens(
        &SkipSerializingTupleStruct(&a, 2, 123),
        &[
            Token::TupleStruct {
                name: "SkipSerializingTupleStruct",
                len: 1,
            },
            Token::I8(1),
            Token::TupleStructEnd,
        ],
    );
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct SkipStruct<B> {
    a: i8,
    #[serde(skip)]
    b: B,
}

//#[test]
pub fn test_skip_struct() {
    assert_ser_tokens(
        &SkipStruct { a: 1, b: 2 },
        &[
            Token::Struct {
                name: "SkipStruct",
                len: 1,
            },
            Token::Str("a"),
            Token::I8(1),
            Token::StructEnd,
        ],
    );

    assert_de_tokens(
        &SkipStruct { a: 1, b: 0 },
        &[
            Token::Struct {
                name: "SkipStruct",
                len: 1,
            },
            Token::Str("a"),
            Token::I8(1),
            Token::StructEnd,
        ],
    );
}

#[derive(Debug, PartialEq, Serialize)]
enum SkipSerializingEnum<'a, B, C>
where
    C: ShouldSkip,
{
    Struct {
        a: &'a i8,
        #[serde(skip_serializing)]
        _b: B,
        #[serde(skip_serializing_if = "ShouldSkip::should_skip")]
        c: C,
    },
    Tuple(
        &'a i8,
        #[serde(skip_serializing)] B,
        #[serde(skip_serializing_if = "ShouldSkip::should_skip")] C,
    ),
}

//#[test]
pub fn test_skip_serializing_enum() {
    let a = 1;
    assert_ser_tokens(
        &SkipSerializingEnum::Struct { a: &a, _b: 2, c: 3 },
        &[
            Token::StructVariant {
                name: "SkipSerializingEnum",
                variant: "Struct",
                len: 2,
            },
            Token::Str("a"),
            Token::I8(1),
            Token::Str("c"),
            Token::I32(3),
            Token::StructVariantEnd,
        ],
    );

    assert_ser_tokens(
        &SkipSerializingEnum::Struct {
            a: &a,
            _b: 2,
            c: 123,
        },
        &[
            Token::StructVariant {
                name: "SkipSerializingEnum",
                variant: "Struct",
                len: 1,
            },
            Token::Str("a"),
            Token::I8(1),
            Token::StructVariantEnd,
        ],
    );

    assert_ser_tokens(
        &SkipSerializingEnum::Tuple(&a, 2, 3),
        &[
            Token::TupleVariant {
                name: "SkipSerializingEnum",
                variant: "Tuple",
                len: 2,
            },
            Token::I8(1),
            Token::I32(3),
            Token::TupleVariantEnd,
        ],
    );

    assert_ser_tokens(
        &SkipSerializingEnum::Tuple(&a, 2, 123),
        &[
            Token::TupleVariant {
                name: "SkipSerializingEnum",
                variant: "Tuple",
                len: 1,
            },
            Token::I8(1),
            Token::TupleVariantEnd,
        ],
    );
}

#[derive(Debug, PartialEq)]
struct NotSerializeStruct(i8);

#[derive(Debug, PartialEq)]
enum NotSerializeEnum {
    Trouble,
}

impl SerializeWith for NotSerializeEnum {
    fn serialize_with<S>(&self, ser: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        "trouble".serialize(ser)
    }
}

#[derive(Debug, PartialEq, Serialize)]
struct ContainsNotSerialize<'a, B, C, D>
where
    B: 'a,
    D: SerializeWith,
{
    a: &'a Option<i8>,
    #[serde(skip_serializing)]
    b: &'a B,
    #[serde(skip_serializing)]
    c: Option<C>,
    #[serde(serialize_with = "SerializeWith::serialize_with")]
    d: D,
}

//#[test]
pub fn test_elt_not_serialize() {
    let a = 1;
    assert_ser_tokens(
        &ContainsNotSerialize {
            a: &Some(a),
            b: &NotSerializeStruct(2),
            c: Some(NotSerializeEnum::Trouble),
            d: NotSerializeEnum::Trouble,
        },
        &[
            Token::Struct {
                name: "ContainsNotSerialize",
                len: 2,
            },
            Token::Str("a"),
            Token::Some,
            Token::I8(1),
            Token::Str("d"),
            Token::Str("trouble"),
            Token::StructEnd,
        ],
    );
}

#[derive(Debug, PartialEq, Serialize)]
struct SerializeWithStruct<'a, B>
where
    B: SerializeWith,
{
    a: &'a i8,
    #[serde(serialize_with = "SerializeWith::serialize_with")]
    b: B,
}

//#[test]
pub fn test_serialize_with_struct() {
    let a = 1;
    assert_ser_tokens(
        &SerializeWithStruct { a: &a, b: 2 },
        &[
            Token::Struct {
                name: "SerializeWithStruct",
                len: 2,
            },
            Token::Str("a"),
            Token::I8(1),
            Token::Str("b"),
            Token::Bool(false),
            Token::StructEnd,
        ],
    );

    assert_ser_tokens(
        &SerializeWithStruct { a: &a, b: 123 },
        &[
            Token::Struct {
                name: "SerializeWithStruct",
                len: 2,
            },
            Token::Str("a"),
            Token::I8(1),
            Token::Str("b"),
            Token::Bool(true),
            Token::StructEnd,
        ],
    );
}

#[derive(Debug, PartialEq, Serialize)]
enum SerializeWithEnum<'a, B>
where
    B: SerializeWith,
{
    Struct {
        a: &'a i8,
        #[serde(serialize_with = "SerializeWith::serialize_with")]
        b: B,
    },
}

//#[test]
pub fn test_serialize_with_enum() {
    let a = 1;
    assert_ser_tokens(
        &SerializeWithEnum::Struct { a: &a, b: 2 },
        &[
            Token::StructVariant {
                name: "SerializeWithEnum",
                variant: "Struct",
                len: 2,
            },
            Token::Str("a"),
            Token::I8(1),
            Token::Str("b"),
            Token::Bool(false),
            Token::StructVariantEnd,
        ],
    );

    assert_ser_tokens(
        &SerializeWithEnum::Struct { a: &a, b: 123 },
        &[
            Token::StructVariant {
                name: "SerializeWithEnum",
                variant: "Struct",
                len: 2,
            },
            Token::Str("a"),
            Token::I8(1),
            Token::Str("b"),
            Token::Bool(true),
            Token::StructVariantEnd,
        ],
    );
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
enum WithVariant {
    #[serde(serialize_with = "serialize_unit_variant_as_i8")]
    #[serde(deserialize_with = "deserialize_i8_as_unit_variant")]
    Unit,

    #[serde(serialize_with = "SerializeWith::serialize_with")]
    #[serde(deserialize_with = "DeserializeWith::deserialize_with")]
    Newtype(i32),

    #[serde(serialize_with = "serialize_variant_as_string")]
    #[serde(deserialize_with = "deserialize_string_as_variant")]
    Tuple(String, u8),

    #[serde(serialize_with = "serialize_variant_as_string")]
    #[serde(deserialize_with = "deserialize_string_as_variant")]
    Struct { f1: String, f2: u8 },
}

fn serialize_unit_variant_as_i8<S>(serializer: S) -> Result<S::Ok, S::Error>
where
    S: Serializer,
{
    serializer.serialize_i8(0)
}

fn deserialize_i8_as_unit_variant<'de, D>(deserializer: D) -> Result<(), D::Error>
where
    D: Deserializer<'de>,
{
    let n = i8::deserialize(deserializer)?;
    match n {
        0 => Ok(()),
        _ => Err(de::Error::invalid_value(Unexpected::Signed(n as i64), &"0")),
    }
}

fn serialize_variant_as_string<S>(f1: &str, f2: &u8, serializer: S) -> Result<S::Ok, S::Error>
where
    S: Serializer,
{
    serializer.serialize_str(format!("{};{:?}", f1, f2).as_str())
}

fn deserialize_string_as_variant<'de, D>(deserializer: D) -> Result<(String, u8), D::Error>
where
    D: Deserializer<'de>,
{
    let s = String::deserialize(deserializer)?;
    let mut pieces = s.split(';');
    let f1 = match pieces.next() {
        Some(x) => x,
        None => return Err(de::Error::invalid_length(0, &"2")),
    };
    let f2 = match pieces.next() {
        Some(x) => x,
        None => return Err(de::Error::invalid_length(1, &"2")),
    };
    let f2 = match f2.parse() {
        Ok(n) => n,
        Err(_) => {
            return Err(de::Error::invalid_value(
                Unexpected::Str(f2),
                &"an 8-bit signed integer",
            ));
        }
    };
    Ok((f1.into(), f2))
}

//#[test]
pub fn test_serialize_with_variant() {
    assert_ser_tokens(
        &WithVariant::Unit,
        &[
            Token::NewtypeVariant {
                name: "WithVariant",
                variant: "Unit",
            },
            Token::I8(0),
        ],
    );

    assert_ser_tokens(
        &WithVariant::Newtype(123),
        &[
            Token::NewtypeVariant {
                name: "WithVariant",
                variant: "Newtype",
            },
            Token::Bool(true),
        ],
    );

    assert_ser_tokens(
        &WithVariant::Tuple("hello".into(), 0),
        &[
            Token::NewtypeVariant {
                name: "WithVariant",
                variant: "Tuple",
            },
            Token::Str("hello;0"),
        ],
    );

    assert_ser_tokens(
        &WithVariant::Struct {
            f1: "world".into(),
            f2: 1,
        },
        &[
            Token::NewtypeVariant {
                name: "WithVariant",
                variant: "Struct",
            },
            Token::Str("world;1"),
        ],
    );
}

//#[test]
pub fn test_deserialize_with_variant() {
    assert_de_tokens(
        &WithVariant::Unit,
        &[
            Token::NewtypeVariant {
                name: "WithVariant",
                variant: "Unit",
            },
            Token::I8(0),
        ],
    );

    assert_de_tokens(
        &WithVariant::Newtype(123),
        &[
            Token::NewtypeVariant {
                name: "WithVariant",
                variant: "Newtype",
            },
            Token::Bool(true),
        ],
    );

    assert_de_tokens(
        &WithVariant::Tuple("hello".into(), 0),
        &[
            Token::NewtypeVariant {
                name: "WithVariant",
                variant: "Tuple",
            },
            Token::Str("hello;0"),
        ],
    );

    assert_de_tokens(
        &WithVariant::Struct {
            f1: "world".into(),
            f2: 1,
        },
        &[
            Token::NewtypeVariant {
                name: "WithVariant",
                variant: "Struct",
            },
            Token::Str("world;1"),
        ],
    );
}

#[derive(Debug, PartialEq, Deserialize)]
struct DeserializeWithStruct<B>
where
    B: DeserializeWith,
{
    a: i8,
    #[serde(deserialize_with = "DeserializeWith::deserialize_with")]
    b: B,
}

//#[test]
pub fn test_deserialize_with_struct() {
    assert_de_tokens(
        &DeserializeWithStruct { a: 1, b: 2 },
        &[
            Token::Struct {
                name: "DeserializeWithStruct",
                len: 2,
            },
            Token::Str("a"),
            Token::I8(1),
            Token::Str("b"),
            Token::Bool(false),
            Token::StructEnd,
        ],
    );

    assert_de_tokens(
        &DeserializeWithStruct { a: 1, b: 123 },
        &[
            Token::Struct {
                name: "DeserializeWithStruct",
                len: 2,
            },
            Token::Str("a"),
            Token::I8(1),
            Token::Str("b"),
            Token::Bool(true),
            Token::StructEnd,
        ],
    );
}

#[derive(Debug, PartialEq, Deserialize)]
enum DeserializeWithEnum<B>
where
    B: DeserializeWith,
{
    Struct {
        a: i8,
        #[serde(deserialize_with = "DeserializeWith::deserialize_with")]
        b: B,
    },
}

//#[test]
pub fn test_deserialize_with_enum() {
    assert_de_tokens(
        &DeserializeWithEnum::Struct { a: 1, b: 2 },
        &[
            Token::StructVariant {
                name: "DeserializeWithEnum",
                variant: "Struct",
                len: 2,
            },
            Token::Str("a"),
            Token::I8(1),
            Token::Str("b"),
            Token::Bool(false),
            Token::StructVariantEnd,
        ],
    );

    assert_de_tokens(
        &DeserializeWithEnum::Struct { a: 1, b: 123 },
        &[
            Token::StructVariant {
                name: "DeserializeWithEnum",
                variant: "Struct",
                len: 2,
            },
            Token::Str("a"),
            Token::I8(1),
            Token::Str("b"),
            Token::Bool(true),
            Token::StructVariantEnd,
        ],
    );
}

//#[test]
pub fn test_missing_renamed_field_struct() {
    assert_de_tokens_error::<RenameStruct>(
        &[
            Token::Struct {
                name: "Superhero",
                len: 2,
            },
            Token::Str("a1"),
            Token::I32(1),
            Token::StructEnd,
        ],
        "missing field `a3`",
    );

    assert_de_tokens_error::<RenameStructSerializeDeserialize>(
        &[
            Token::Struct {
                name: "SuperheroDe",
                len: 2,
            },
            Token::Str("a1"),
            Token::I32(1),
            Token::StructEnd,
        ],
        "missing field `a5`",
    );
}

//#[test]
pub fn test_missing_renamed_field_enum() {
    assert_de_tokens_error::<RenameEnum>(
        &[
            Token::StructVariant {
                name: "Superhero",
                variant: "barry_allan",
                len: 1,
            },
            Token::StructVariantEnd,
        ],
        "missing field `b`",
    );

    assert_de_tokens_error::<RenameEnumSerializeDeserialize<i8>>(
        &[
            Token::StructVariant {
                name: "SuperheroDe",
                variant: "jason_todd",
                len: 2,
            },
            Token::Str("a"),
            Token::I8(0),
            Token::StructVariantEnd,
        ],
        "missing field `d`",
    );
}

#[derive(Debug, PartialEq, Deserialize)]
enum InvalidLengthEnum {
    A(i32, i32, i32),
    B(#[serde(skip_deserializing)] i32, i32, i32),
}

//#[test]
pub fn test_invalid_length_enum() {
    assert_de_tokens_error::<InvalidLengthEnum>(
        &[
            Token::TupleVariant {
                name: "InvalidLengthEnum",
                variant: "A",
                len: 3,
            },
            Token::I32(1),
            Token::TupleVariantEnd,
        ],
        "invalid length 1, expected tuple variant InvalidLengthEnum::A with 3 elements",
    );
    assert_de_tokens_error::<InvalidLengthEnum>(
        &[
            Token::TupleVariant {
                name: "InvalidLengthEnum",
                variant: "B",
                len: 3,
            },
            Token::I32(1),
            Token::TupleVariantEnd,
        ],
        "invalid length 1, expected tuple variant InvalidLengthEnum::B with 2 elements",
    );
}

#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
#[serde(into = "EnumToU32", from = "EnumToU32")]
struct StructFromEnum(Option<u32>);

impl Into<EnumToU32> for StructFromEnum {
    fn into(self) -> EnumToU32 {
        match self {
            StructFromEnum(v) => v.into(),
        }
    }
}

impl From<EnumToU32> for StructFromEnum {
    fn from(v: EnumToU32) -> Self {
        StructFromEnum(v.into())
    }
}

#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
#[serde(into = "Option<u32>", from = "Option<u32>")]
enum EnumToU32 {
    One,
    Two,
    Three,
    Four,
    Nothing,
}

impl Into<Option<u32>> for EnumToU32 {
    fn into(self) -> Option<u32> {
        match self {
            EnumToU32::One => Some(1),
            EnumToU32::Two => Some(2),
            EnumToU32::Three => Some(3),
            EnumToU32::Four => Some(4),
            EnumToU32::Nothing => None,
        }
    }
}

impl From<Option<u32>> for EnumToU32 {
    fn from(v: Option<u32>) -> Self {
        match v {
            Some(1) => EnumToU32::One,
            Some(2) => EnumToU32::Two,
            Some(3) => EnumToU32::Three,
            Some(4) => EnumToU32::Four,
            _ => EnumToU32::Nothing,
        }
    }
}

//#[test]
pub fn test_from_into_traits() {
    assert_ser_tokens::<EnumToU32>(&EnumToU32::One, &[Token::Some, Token::U32(1)]);
    assert_ser_tokens::<EnumToU32>(&EnumToU32::Nothing, &[Token::None]);
    assert_de_tokens::<EnumToU32>(&EnumToU32::Two, &[Token::Some, Token::U32(2)]);
    assert_ser_tokens::<StructFromEnum>(&StructFromEnum(Some(5)), &[Token::None]);
    assert_ser_tokens::<StructFromEnum>(&StructFromEnum(None), &[Token::None]);
    assert_de_tokens::<StructFromEnum>(&StructFromEnum(Some(2)), &[Token::Some, Token::U32(2)]);
}

//#[test]
pub fn test_collect_other() {
    let mut extra = HashMap::new();
    extra.insert("c".into(), 3);
    assert_tokens(
        &CollectOther { a: 1, b: 2, extra },
        &[
            Token::Map { len: None },
            Token::Str("a"),
            Token::U32(1),
            Token::Str("b"),
            Token::U32(2),
            Token::Str("c"),
            Token::U32(3),
            Token::MapEnd,
        ],
    );
}

//#[test]
pub fn test_flatten_struct_enum() {
    let mut extra = HashMap::new();
    extra.insert("extra_key".into(), "extra value".into());
    let change_request = FlattenStructEnumWrapper {
        data: FlattenStructEnum::InsertInteger {
            index: 0,
            value: 42,
        },
        extra,
    };
    assert_de_tokens(
        &change_request,
        &[
            Token::Map { len: None },
            Token::Str("insert_integer"),
            Token::Map { len: None },
            Token::Str("index"),
            Token::U32(0),
            Token::Str("value"),
            Token::U32(42),
            Token::MapEnd,
            Token::Str("extra_key"),
            Token::Str("extra value"),
            Token::MapEnd,
        ],
    );
    assert_ser_tokens(
        &change_request,
        &[
            Token::Map { len: None },
            Token::Str("insert_integer"),
            Token::Struct {
                len: 2,
                name: "insert_integer",
            },
            Token::Str("index"),
            Token::U32(0),
            Token::Str("value"),
            Token::U32(42),
            Token::StructEnd,
            Token::Str("extra_key"),
            Token::Str("extra value"),
            Token::MapEnd,
        ],
    );
}

//#[test]
pub fn test_flatten_struct_tag_content_enum() {
    let change_request = FlattenStructTagContentEnumWrapper {
        outer: 42,
        data: FlattenStructTagContentEnumNewtype(FlattenStructTagContentEnum::InsertInteger {
            index: 0,
            value: 42,
        }),
    };
    assert_de_tokens(
        &change_request,
        &[
            Token::Map { len: None },
            Token::Str("outer"),
            Token::U32(42),
            Token::Str("type"),
            Token::Str("insert_integer"),
            Token::Str("value"),
            Token::Map { len: None },
            Token::Str("index"),
            Token::U32(0),
            Token::Str("value"),
            Token::U32(42),
            Token::MapEnd,
            Token::MapEnd,
        ],
    );
    assert_ser_tokens(
        &change_request,
        &[
            Token::Map { len: None },
            Token::Str("outer"),
            Token::U32(42),
            Token::Str("type"),
            Token::Str("insert_integer"),
            Token::Str("value"),
            Token::Struct {
                len: 2,
                name: "insert_integer",
            },
            Token::Str("index"),
            Token::U32(0),
            Token::Str("value"),
            Token::U32(42),
            Token::StructEnd,
            Token::MapEnd,
        ],
    );
}

//#[test]
pub fn test_flatten_struct_tag_content_enum_newtype() {
    let change_request = FlattenStructTagContentEnumWrapper {
        outer: 42,
        data: FlattenStructTagContentEnumNewtype(FlattenStructTagContentEnum::NewtypeVariant(
            FlattenStructTagContentEnumNewtypeVariant { value: 23 },
        )),
    };
    assert_de_tokens(
        &change_request,
        &[
            Token::Map { len: None },
            Token::Str("outer"),
            Token::U32(42),
            Token::Str("type"),
            Token::Str("newtype_variant"),
            Token::Str("value"),
            Token::Map { len: None },
            Token::Str("value"),
            Token::U32(23),
            Token::MapEnd,
            Token::MapEnd,
        ],
    );
    assert_ser_tokens(
        &change_request,
        &[
            Token::Map { len: None },
            Token::Str("outer"),
            Token::U32(42),
            Token::Str("type"),
            Token::Str("newtype_variant"),
            Token::Str("value"),
            Token::Struct {
                len: 1,
                name: "FlattenStructTagContentEnumNewtypeVariant",
            },
            Token::Str("value"),
            Token::U32(23),
            Token::StructEnd,
            Token::MapEnd,
        ],
    );
}

//#[test]
pub fn test_unknown_field_in_flatten() {
    #[derive(Debug, PartialEq, Serialize, Deserialize)]
    #[serde(deny_unknown_fields)]
    struct Outer {
        dummy: String,
        #[serde(flatten)]
        inner: Inner,
    }

    #[derive(Debug, PartialEq, Serialize, Deserialize)]
    struct Inner {
        foo: HashMap<String, u32>,
    }

    assert_de_tokens_error::<Outer>(
        &[
            Token::Struct {
                name: "Outer",
                len: 1,
            },
            Token::Str("dummy"),
            Token::Str("23"),
            Token::Str("foo"),
            Token::Map { len: None },
            Token::Str("a"),
            Token::U32(1),
            Token::Str("b"),
            Token::U32(2),
            Token::MapEnd,
            Token::Str("bar"),
            Token::U32(23),
            Token::StructEnd,
        ],
        "unknown field `bar`",
    );
}

//#[test]
pub fn test_complex_flatten() {
    #[derive(Debug, PartialEq, Serialize, Deserialize)]
    struct Outer {
        y: u32,
        #[serde(flatten)]
        first: First,
        #[serde(flatten)]
        second: Second,
        z: u32,
    }

    #[derive(Debug, PartialEq, Serialize, Deserialize)]
    struct First {
        a: u32,
        b: bool,
        c: Vec<String>,
        d: String,
        e: Option<u64>,
    }

    #[derive(Debug, PartialEq, Serialize, Deserialize)]
    struct Second {
        f: u32,
    }

    assert_de_tokens(
        &Outer {
            y: 0,
            first: First {
                a: 1,
                b: true,
                c: vec!["a".into(), "b".into()],
                d: "c".into(),
                e: Some(2),
            },
            second: Second { f: 3 },
            z: 4,
        },
        &[
            Token::Map { len: None },
            Token::Str("y"),
            Token::U32(0),
            Token::Str("a"),
            Token::U32(1),
            Token::Str("b"),
            Token::Bool(true),
            Token::Str("c"),
            Token::Seq { len: Some(2) },
            Token::Str("a"),
            Token::Str("b"),
            Token::SeqEnd,
            Token::Str("d"),
            Token::Str("c"),
            Token::Str("e"),
            Token::U64(2),
            Token::Str("f"),
            Token::U32(3),
            Token::Str("z"),
            Token::U32(4),
            Token::MapEnd,
        ],
    );

    assert_ser_tokens(
        &Outer {
            y: 0,
            first: First {
                a: 1,
                b: true,
                c: vec!["a".into(), "b".into()],
                d: "c".into(),
                e: Some(2),
            },
            second: Second { f: 3 },
            z: 4,
        },
        &[
            Token::Map { len: None },
            Token::Str("y"),
            Token::U32(0),
            Token::Str("a"),
            Token::U32(1),
            Token::Str("b"),
            Token::Bool(true),
            Token::Str("c"),
            Token::Seq { len: Some(2) },
            Token::Str("a"),
            Token::Str("b"),
            Token::SeqEnd,
            Token::Str("d"),
            Token::Str("c"),
            Token::Str("e"),
            Token::Some,
            Token::U64(2),
            Token::Str("f"),
            Token::U32(3),
            Token::Str("z"),
            Token::U32(4),
            Token::MapEnd,
        ],
    );
}

//#[test]
pub fn test_flatten_map_twice() {
    #[derive(Debug, PartialEq, Deserialize)]
    struct Outer {
        #[serde(flatten)]
        first: BTreeMap<String, String>,
        #[serde(flatten)]
        between: Inner,
        #[serde(flatten)]
        second: BTreeMap<String, String>,
    }

    #[derive(Debug, PartialEq, Deserialize)]
    struct Inner {
        y: String,
    }

    assert_de_tokens(
        &Outer {
            first: {
                let mut first = BTreeMap::new();
                first.insert("x".to_owned(), "X".to_owned());
                first.insert("y".to_owned(), "Y".to_owned());
                first
            },
            between: Inner { y: "Y".to_owned() },
            second: {
                let mut second = BTreeMap::new();
                second.insert("x".to_owned(), "X".to_owned());
                second
            },
        },
        &[
            Token::Map { len: None },
            Token::Str("x"),
            Token::Str("X"),
            Token::Str("y"),
            Token::Str("Y"),
            Token::MapEnd,
        ],
    );
}

//#[test]
pub fn test_flatten_unsupported_type() {
    #[derive(Debug, PartialEq, Serialize, Deserialize)]
    struct Outer {
        outer: String,
        #[serde(flatten)]
        inner: String,
    }

    assert_ser_tokens_error(
        &Outer {
            outer: "foo".into(),
            inner: "bar".into(),
        },
        &[
            Token::Map { len: None },
            Token::Str("outer"),
            Token::Str("foo"),
        ],
        "can only flatten structs and maps (got a string)",
    );
    assert_de_tokens_error::<Outer>(
        &[
            Token::Map { len: None },
            Token::Str("outer"),
            Token::Str("foo"),
            Token::Str("a"),
            Token::Str("b"),
            Token::MapEnd,
        ],
        "can only flatten structs and maps",
    );
}

//#[test]
pub fn test_non_string_keys() {
    #[derive(Debug, PartialEq, Serialize, Deserialize)]
    struct TestStruct {
        name: String,
        age: u32,
        #[serde(flatten)]
        mapping: HashMap<u32, u32>,
    }

    let mut mapping = HashMap::new();
    mapping.insert(0, 42);
    assert_tokens(
        &TestStruct {
            name: "peter".into(),
            age: 3,
            mapping,
        },
        &[
            Token::Map { len: None },
            Token::Str("name"),
            Token::Str("peter"),
            Token::Str("age"),
            Token::U32(3),
            Token::U32(0),
            Token::U32(42),
            Token::MapEnd,
        ],
    );
}

//#[test]
pub fn test_lifetime_propagation_for_flatten() {
    #[derive(Deserialize, Serialize, Debug, PartialEq)]
    struct A<T> {
        #[serde(flatten)]
        t: T,
    }

    #[derive(Deserialize, Serialize, Debug, PartialEq)]
    struct B<'a> {
        #[serde(flatten, borrow)]
        t: HashMap<&'a str, u32>,
    }

    #[derive(Deserialize, Serialize, Debug, PartialEq)]
    struct C<'a> {
        #[serde(flatten, borrow)]
        t: HashMap<&'a [u8], u32>,
    }

    let mut owned_map = HashMap::new();
    owned_map.insert("x".to_string(), 42u32);
    assert_tokens(
        &A { t: owned_map },
        &[
            Token::Map { len: None },
            Token::Str("x"),
            Token::U32(42),
            Token::MapEnd,
        ],
    );

    let mut borrowed_map = HashMap::new();
    borrowed_map.insert("x", 42u32);
    assert_ser_tokens(
        &B {
            t: borrowed_map.clone(),
        },
        &[
            Token::Map { len: None },
            Token::BorrowedStr("x"),
            Token::U32(42),
            Token::MapEnd,
        ],
    );

    assert_de_tokens(
        &B { t: borrowed_map },
        &[
            Token::Map { len: None },
            Token::BorrowedStr("x"),
            Token::U32(42),
            Token::MapEnd,
        ],
    );

    let mut borrowed_map = HashMap::new();
    borrowed_map.insert(&b"x"[..], 42u32);
    assert_ser_tokens(
        &C {
            t: borrowed_map.clone(),
        },
        &[
            Token::Map { len: None },
            Token::Seq { len: Some(1) },
            Token::U8(120),
            Token::SeqEnd,
            Token::U32(42),
            Token::MapEnd,
        ],
    );

    assert_de_tokens(
        &C { t: borrowed_map },
        &[
            Token::Map { len: None },
            Token::BorrowedBytes(b"x"),
            Token::U32(42),
            Token::MapEnd,
        ],
    );
}

//#[test]
pub fn test_flatten_enum_newtype() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct S {
        #[serde(flatten)]
        flat: E,
    }

    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    enum E {
        Q(HashMap<String, String>),
    }

    let e = E::Q({
        let mut map = HashMap::new();
        map.insert("k".to_owned(), "v".to_owned());
        map
    });
    let s = S { flat: e };

    assert_tokens(
        &s,
        &[
            Token::Map { len: None },
            Token::Str("Q"),
            Token::Map { len: Some(1) },
            Token::Str("k"),
            Token::Str("v"),
            Token::MapEnd,
            Token::MapEnd,
        ],
    );
}

//#[test]
pub fn test_flatten_internally_tagged() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct S {
        #[serde(flatten)]
        x: X,
        #[serde(flatten)]
        y: Y,
    }

    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    #[serde(tag = "typeX")]
    enum X {
        A { a: i32 },
        B { b: i32 },
    }

    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    #[serde(tag = "typeY")]
    enum Y {
        C { c: i32 },
        D { d: i32 },
    }

    let s = S {
        x: X::B { b: 1 },
        y: Y::D { d: 2 },
    };

    assert_tokens(
        &s,
        &[
            Token::Map { len: None },
            Token::Str("typeX"),
            Token::Str("B"),
            Token::Str("b"),
            Token::I32(1),
            Token::Str("typeY"),
            Token::Str("D"),
            Token::Str("d"),
            Token::I32(2),
            Token::MapEnd,
        ],
    );
}

//#[test]
pub fn test_externally_tagged_enum_containing_flatten() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    enum Data {
        A {
            a: i32,
            #[serde(flatten)]
            flat: Flat,
        },
    }

    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Flat {
        b: i32,
    }

    let data = Data::A {
        a: 0,
        flat: Flat { b: 0 },
    };

    assert_tokens(
        &data,
        &[
            Token::NewtypeVariant {
                name: "Data",
                variant: "A",
            },
            Token::Map { len: None },
            Token::Str("a"),
            Token::I32(0),
            Token::Str("b"),
            Token::I32(0),
            Token::MapEnd,
        ],
    );
}

//#[test]
pub fn test_internally_tagged_enum_containing_flatten() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    #[serde(tag = "t")]
    enum Data {
        A {
            a: i32,
            #[serde(flatten)]
            flat: Flat,
        },
    }

    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Flat {
        b: i32,
    }

    let data = Data::A {
        a: 0,
        flat: Flat { b: 0 },
    };

    assert_tokens(
        &data,
        &[
            Token::Map { len: None },
            Token::Str("t"),
            Token::Str("A"),
            Token::Str("a"),
            Token::I32(0),
            Token::Str("b"),
            Token::I32(0),
            Token::MapEnd,
        ],
    );
}

//#[test]
pub fn test_adjacently_tagged_enum_containing_flatten() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    #[serde(tag = "t", content = "c")]
    enum Data {
        A {
            a: i32,
            #[serde(flatten)]
            flat: Flat,
        },
    }

    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Flat {
        b: i32,
    }

    let data = Data::A {
        a: 0,
        flat: Flat { b: 0 },
    };

    assert_tokens(
        &data,
        &[
            Token::Struct {
                name: "Data",
                len: 2,
            },
            Token::Str("t"),
            Token::Str("A"),
            Token::Str("c"),
            Token::Map { len: None },
            Token::Str("a"),
            Token::I32(0),
            Token::Str("b"),
            Token::I32(0),
            Token::MapEnd,
            Token::StructEnd,
        ],
    );
}

//#[test]
pub fn test_untagged_enum_containing_flatten() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    #[serde(untagged)]
    enum Data {
        A {
            a: i32,
            #[serde(flatten)]
            flat: Flat,
        },
    }

    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Flat {
        b: i32,
    }

    let data = Data::A {
        a: 0,
        flat: Flat { b: 0 },
    };

    assert_tokens(
        &data,
        &[
            Token::Map { len: None },
            Token::Str("a"),
            Token::I32(0),
            Token::Str("b"),
            Token::I32(0),
            Token::MapEnd,
        ],
    );
}

//#[test]
pub fn test_flatten_untagged_enum() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Outer {
        #[serde(flatten)]
        inner: Inner,
    }

    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    #[serde(untagged)]
    enum Inner {
        Variant { a: i32 },
    }

    let data = Outer {
        inner: Inner::Variant { a: 0 },
    };

    assert_tokens(
        &data,
        &[
            Token::Map { len: None },
            Token::Str("a"),
            Token::I32(0),
            Token::MapEnd,
        ],
    );
}

//#[test]
pub fn test_flatten_option() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Outer {
        #[serde(flatten)]
        inner1: Option<Inner1>,
        #[serde(flatten)]
        inner2: Option<Inner2>,
    }

    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Inner1 {
        inner1: i32,
    }

    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    struct Inner2 {
        inner2: i32,
    }

    assert_tokens(
        &Outer {
            inner1: Some(Inner1 { inner1: 1 }),
            inner2: Some(Inner2 { inner2: 2 }),
        },
        &[
            Token::Map { len: None },
            Token::Str("inner1"),
            Token::I32(1),
            Token::Str("inner2"),
            Token::I32(2),
            Token::MapEnd,
        ],
    );

    assert_tokens(
        &Outer {
            inner1: Some(Inner1 { inner1: 1 }),
            inner2: None,
        },
        &[
            Token::Map { len: None },
            Token::Str("inner1"),
            Token::I32(1),
            Token::MapEnd,
        ],
    );

    assert_tokens(
        &Outer {
            inner1: None,
            inner2: Some(Inner2 { inner2: 2 }),
        },
        &[
            Token::Map { len: None },
            Token::Str("inner2"),
            Token::I32(2),
            Token::MapEnd,
        ],
    );

    assert_tokens(
        &Outer {
            inner1: None,
            inner2: None,
        },
        &[Token::Map { len: None }, Token::MapEnd],
    );
}

//#[test]
pub fn test_transparent_struct() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    #[serde(transparent)]
    struct Transparent {
        #[serde(skip)]
        a: bool,
        b: u32,
        #[serde(skip)]
        c: bool,
        d: PhantomData<()>,
    }

    assert_tokens(
        &Transparent {
            a: false,
            b: 1,
            c: false,
            d: PhantomData,
        },
        &[Token::U32(1)],
    );
}

//#[test]
pub fn test_transparent_tuple_struct() {
    #[derive(Serialize, Deserialize, PartialEq, Debug)]
    #[serde(transparent)]
    struct Transparent(
        #[serde(skip)] bool,
        u32,
        #[serde(skip)] bool,
        PhantomData<()>,
    );

    assert_tokens(&Transparent(false, 1, false, PhantomData), &[Token::U32(1)]);
}

//#[test]
pub fn test_internally_tagged_unit_enum_with_unknown_fields() {
    #[derive(Deserialize, PartialEq, Debug)]
    #[serde(tag = "t")]
    enum Data {
        A,
    }

    let data = Data::A;

    assert_de_tokens(
        &data,
        &[
            Token::Map { len: None },
            Token::Str("t"),
            Token::Str("A"),
            Token::Str("b"),
            Token::I32(0),
            Token::MapEnd,
        ],
    );
}

//#[test]
pub fn test_flattened_internally_tagged_unit_enum_with_unknown_fields() {
    #[derive(Deserialize, PartialEq, Debug)]
    struct S {
        #[serde(flatten)]
        x: X,
        #[serde(flatten)]
        y: Y,
    }

    #[derive(Deserialize, PartialEq, Debug)]
    #[serde(tag = "typeX")]
    enum X {
        A,
    }

    #[derive(Deserialize, PartialEq, Debug)]
    #[serde(tag = "typeY")]
    enum Y {
        B { c: u32 },
    }

    let s = S {
        x: X::A,
        y: Y::B { c: 0 },
    };

    assert_de_tokens(
        &s,
        &[
            Token::Map { len: None },
            Token::Str("typeX"),
            Token::Str("A"),
            Token::Str("typeY"),
            Token::Str("B"),
            Token::Str("c"),
            Token::I32(0),
            Token::MapEnd,
        ],
    );
}

//#[test]
pub fn test_flatten_any_after_flatten_struct() {
    #[derive(PartialEq, Debug)]
    struct Any;

    impl<'de> Deserialize<'de> for Any {
        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where
            D: Deserializer<'de>,
        {
            struct AnyVisitor;

            impl<'de> Visitor<'de> for AnyVisitor {
                type Value = Any;

                fn expecting(&self, _formatter: &mut fmt::Formatter) -> fmt::Result {
                    unimplemented!()
                }

                fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
                where
                    M: MapAccess<'de>,
                {
                    while let Some((Any, Any)) = map.next_entry()? {}
                    Ok(Any)
                }
            }

            deserializer.deserialize_any(AnyVisitor)
        }
    }

    #[derive(Deserialize, PartialEq, Debug)]
    struct Outer {
        #[serde(flatten)]
        inner: Inner,
        #[serde(flatten)]
        extra: Any,
    }

    #[derive(Deserialize, PartialEq, Debug)]
    struct Inner {
        inner: i32,
    }

    let s = Outer {
        inner: Inner { inner: 0 },
        extra: Any,
    };

    assert_de_tokens(
        &s,
        &[
            Token::Map { len: None },
            Token::Str("inner"),
            Token::I32(0),
            Token::MapEnd,
        ],
    );
}
