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
use crate::ser::Value;
use crate::Data;
use crate::Error;
use crate::Serializer;
use alloc::borrow::Cow;
use alloc::boxed::Box;
use serde::ser;
use serde::ser::SerializeMap;
use serde::ser::SerializeStruct;
use serde::ser::SerializeTupleStruct;

use super::to_static_str;

pub struct Struct<'a> {
    r#struct: crate::Struct<'a>,
    human_readable: bool,
}

impl<'a> Struct<'a> {
    pub(super) const fn new(r#struct: crate::Struct<'a>, human_readable: bool) -> Self {
        Self {
            r#struct,
            human_readable,
        }
    }
}

impl<'a> ser::Serialize for crate::Struct<'a> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: ser::Serializer,
    {
        match &self.data {
            Data::Unit => match &self.name {
                Cow::Borrowed(name) => serializer.serialize_unit_struct(name),
                Cow::Owned(_) => serializer.serialize_unit(),
            },
            Data::NewType { value } => match &self.name {
                Cow::Borrowed(name) => serializer.serialize_newtype_struct(name, value),
                Cow::Owned(_) => value.serialize(serializer),
            },
            Data::Tuple { values } => match &self.name {
                Cow::Borrowed(name) => {
                    let mut tup = serializer.serialize_tuple_struct(name, values.len())?;
                    for value in values {
                        tup.serialize_field(value)?;
                    }
                    tup.end()
                }
                Cow::Owned(_) => values.serialize(serializer),
            },
            Data::Struct { fields } => match &self.name {
                Cow::Borrowed(name) => {
                    let mut map = serializer.serialize_struct(name, fields.len())?;
                    for (key, value) in fields {
                        let key = to_static_str(key)?;
                        map.serialize_field(key, value)?;
                    }
                    map.end()
                }
                Cow::Owned(_) => {
                    let mut map = serializer.serialize_map(Some(fields.len()))?;
                    for (key, value) in fields {
                        map.serialize_entry(key, value)?;
                    }
                    map.end()
                }
            },
        }
    }
}

impl<'a> ser::SerializeStruct for Struct<'a> {
    type Ok = Value<'a>;
    type Error = Error;

    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Error>
    where
        T: ?Sized + ser::Serialize,
    {
        if let Data::Struct { fields } = &mut self.r#struct.data {
            let value = value.serialize(Serializer::with_human_readable(self.human_readable))?;
            fields.push((Cow::Borrowed(key), value));
        }
        Ok(())
    }

    fn end(self) -> Result<Self::Ok, Error> {
        Ok(Value::Struct(Box::new(self.r#struct)))
    }
}

impl<'a> ser::SerializeTupleStruct for Struct<'a> {
    type Ok = Value<'a>;
    type Error = Error;

    fn serialize_field<T>(&mut self, value: &T) -> Result<(), Error>
    where
        T: ?Sized + ser::Serialize,
    {
        if let Data::Tuple { values } = &mut self.r#struct.data {
            let value = value.serialize(Serializer::with_human_readable(self.human_readable))?;
            values.push(value);
        }
        Ok(())
    }

    fn end(self) -> Result<Self::Ok, Error> {
        Ok(Value::Struct(Box::new(self.r#struct)))
    }
}