1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use super::{
    expression::ExpressionSerializer, BoolSerializer, IdentifierSerializer, OptionSerializer,
};
use crate::{Error, Expression, ForExpr, Identifier, Result};
use serde::ser::{self, Impossible};

pub struct ForExprSerializer;

impl ser::Serializer for ForExprSerializer {
    type Ok = ForExpr;
    type Error = Error;

    type SerializeSeq = Impossible<ForExpr, Error>;
    type SerializeTuple = Impossible<ForExpr, Error>;
    type SerializeTupleStruct = Impossible<ForExpr, Error>;
    type SerializeTupleVariant = Impossible<ForExpr, Error>;
    type SerializeMap = Impossible<ForExpr, Error>;
    type SerializeStruct = SerializeForExprStruct;
    type SerializeStructVariant = Impossible<ForExpr, Error>;

    serialize_unsupported! {
        bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str
        bytes none unit unit_struct unit_variant newtype_variant
        seq tuple tuple_struct tuple_variant map struct_variant
    }
    serialize_self! { some newtype_struct }

    fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
        Ok(SerializeForExprStruct::new())
    }
}

pub struct SerializeForExprStruct {
    key_var: Option<Option<Identifier>>,
    value_var: Option<Identifier>,
    collection_expr: Option<Expression>,
    key_expr: Option<Option<Expression>>,
    value_expr: Option<Expression>,
    grouping: Option<bool>,
    cond_expr: Option<Option<Expression>>,
}

impl SerializeForExprStruct {
    pub fn new() -> Self {
        SerializeForExprStruct {
            key_var: None,
            value_var: None,
            collection_expr: None,
            key_expr: None,
            value_expr: None,
            grouping: None,
            cond_expr: None,
        }
    }
}

impl ser::SerializeStruct for SerializeForExprStruct {
    type Ok = ForExpr;
    type Error = Error;

    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
    where
        T: ?Sized + ser::Serialize,
    {
        match key {
            "key_var" => {
                self.key_var = Some(value.serialize(OptionSerializer::new(IdentifierSerializer))?)
            }
            "value_var" => {
                self.value_var = Some(value.serialize(IdentifierSerializer)?)
            }
            "collection_expr" => {
                self.collection_expr = Some(value.serialize(ExpressionSerializer)?)
            }
            "key_expr" => self.key_expr = Some(value.serialize(OptionSerializer::new(ExpressionSerializer))?),
            "value_expr" => self.value_expr = Some(value.serialize(ExpressionSerializer)?),
            "grouping" => self.grouping = Some(value.serialize(BoolSerializer)?),
            "cond_expr" => self.cond_expr = Some(value.serialize(OptionSerializer::new(ExpressionSerializer))?),
            _ => {
                return Err(ser::Error::custom(
                    "expected struct with fields `key_var`, `value_var`, `collection_expr`, `key_expr`, `value_expr`, `grouping` and `cond_expr`",
                ))
            }
        };

        Ok(())
    }

    fn end(self) -> Result<Self::Ok> {
        match (
            self.key_var,
            self.value_var,
            self.collection_expr,
            self.key_expr,
            self.value_expr,
            self.grouping,
            self.cond_expr
        ) {
            (
                Some(key_var),
                Some(value_var),
                Some(collection_expr),
                Some(key_expr),
                Some(value_expr),
                Some(grouping),
                Some(cond_expr)
            ) => Ok(ForExpr {
                key_var,
                value_var,
                collection_expr,
                key_expr,
                value_expr,
                grouping,
                cond_expr,
            }),
            (_, _, _, _, _, _, _) => Err(ser::Error::custom(
                "expected struct with fields `key_var`, `value_var`, `collection_expr`, `key_expr`, `value_expr`, `grouping` and `cond_expr`",
            )),
        }
    }
}