prost_reflect/dynamic/serde/ser/
mod.rs

1mod wkt;
2
3use base64::{display::Base64Display, prelude::BASE64_STANDARD};
4
5use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer};
6
7use crate::{
8    descriptor::Kind,
9    dynamic::{fields::ValueAndDescriptor, serde::SerializeOptions, DynamicMessage, MapKey, Value},
10    ReflectMessage,
11};
12
13struct SerializeWrapper<'a, T> {
14    value: &'a T,
15    options: &'a SerializeOptions,
16}
17
18pub(super) fn serialize_message<S>(
19    message: &DynamicMessage,
20    serializer: S,
21    options: &SerializeOptions,
22) -> Result<S::Ok, S::Error>
23where
24    S: Serializer,
25{
26    SerializeWrapper {
27        value: message,
28        options,
29    }
30    .serialize(serializer)
31}
32
33impl Serialize for SerializeWrapper<'_, DynamicMessage> {
34    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
35    where
36        S: Serializer,
37    {
38        let message_desc = self.value.descriptor();
39        if let Some(serialize) = wkt::get_well_known_type_serializer(message_desc.full_name()) {
40            serialize(self.value, serializer, self.options)
41        } else {
42            let mut map = serializer.serialize_map(None)?;
43            serialize_dynamic_message_fields(&mut map, self.value, self.options)?;
44            map.end()
45        }
46    }
47}
48
49fn serialize_dynamic_message_fields<S>(
50    map: &mut S,
51    value: &DynamicMessage,
52    options: &SerializeOptions,
53) -> Result<(), S::Error>
54where
55    S: SerializeMap,
56{
57    let fields = value
58        .fields
59        .iter(&value.desc, !options.skip_default_fields, false);
60
61    for field in fields {
62        let (name, value, ref kind) = match field {
63            ValueAndDescriptor::Field(value, ref field_desc) => {
64                let name = if options.use_proto_field_name {
65                    field_desc.name()
66                } else {
67                    field_desc.json_name()
68                };
69                (name, value, field_desc.kind())
70            }
71            ValueAndDescriptor::Extension(value, ref extension_desc) => {
72                (extension_desc.json_name(), value, extension_desc.kind())
73            }
74            ValueAndDescriptor::Unknown(_) => continue,
75        };
76
77        map.serialize_entry(
78            name,
79            &SerializeWrapper {
80                value: &ValueAndKind {
81                    value: value.as_ref(),
82                    kind,
83                },
84                options,
85            },
86        )?;
87    }
88
89    Ok(())
90}
91
92struct ValueAndKind<'a> {
93    value: &'a Value,
94    kind: &'a Kind,
95}
96
97impl<'a> Serialize for SerializeWrapper<'a, ValueAndKind<'a>> {
98    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
99    where
100        S: Serializer,
101    {
102        match self.value.value {
103            Value::Bool(value) => serializer.serialize_bool(*value),
104            Value::I32(value) => serializer.serialize_i32(*value),
105            Value::I64(value) => {
106                if self.options.stringify_64_bit_integers {
107                    serializer.collect_str(value)
108                } else {
109                    serializer.serialize_i64(*value)
110                }
111            }
112            Value::U32(value) => serializer.serialize_u32(*value),
113            Value::U64(value) => {
114                if self.options.stringify_64_bit_integers {
115                    serializer.collect_str(value)
116                } else {
117                    serializer.serialize_u64(*value)
118                }
119            }
120            Value::F32(value) => {
121                if value.is_finite() {
122                    serializer.serialize_f32(*value)
123                } else if *value == f32::INFINITY {
124                    serializer.serialize_str("Infinity")
125                } else if *value == f32::NEG_INFINITY {
126                    serializer.serialize_str("-Infinity")
127                } else {
128                    debug_assert!(value.is_nan());
129                    serializer.serialize_str("NaN")
130                }
131            }
132            Value::F64(value) => {
133                if value.is_finite() {
134                    serializer.serialize_f64(*value)
135                } else if *value == f64::INFINITY {
136                    serializer.serialize_str("Infinity")
137                } else if *value == f64::NEG_INFINITY {
138                    serializer.serialize_str("-Infinity")
139                } else {
140                    debug_assert!(value.is_nan());
141                    serializer.serialize_str("NaN")
142                }
143            }
144            Value::String(value) => serializer.serialize_str(value),
145            Value::Bytes(value) => {
146                serializer.collect_str(&Base64Display::new(value, &BASE64_STANDARD))
147            }
148            Value::EnumNumber(number) => {
149                let enum_ty = match self.value.kind {
150                    Kind::Enum(enum_ty) => enum_ty,
151                    _ => panic!(
152                        "mismatch between DynamicMessage value {:?} and type {:?}",
153                        self.value.value, self.value.kind
154                    ),
155                };
156
157                if enum_ty.full_name() == "google.protobuf.NullValue" {
158                    serializer.serialize_none()
159                } else if self.options.use_enum_numbers {
160                    serializer.serialize_i32(*number)
161                } else if let Some(enum_value) = enum_ty.get_value(*number) {
162                    serializer.serialize_str(enum_value.name())
163                } else {
164                    serializer.serialize_i32(*number)
165                }
166            }
167            Value::Message(message) => message.serialize_with_options(serializer, self.options),
168            Value::List(values) => {
169                let mut list = serializer.serialize_seq(Some(values.len()))?;
170                for value in values {
171                    list.serialize_element(&SerializeWrapper {
172                        value: &ValueAndKind {
173                            value,
174                            kind: self.value.kind,
175                        },
176                        options: self.options,
177                    })?;
178                }
179                list.end()
180            }
181            Value::Map(values) => {
182                let value_kind = match self.value.kind {
183                    Kind::Message(message) if message.is_map_entry() => {
184                        message.map_entry_value_field().kind()
185                    }
186                    _ => panic!(
187                        "mismatch between DynamicMessage value {:?} and type {:?}",
188                        self.value.value, self.value.kind
189                    ),
190                };
191
192                let mut map = serializer.serialize_map(Some(values.len()))?;
193                for (key, value) in values {
194                    map.serialize_entry(
195                        &SerializeWrapper {
196                            value: key,
197                            options: self.options,
198                        },
199                        &SerializeWrapper {
200                            value: &ValueAndKind {
201                                value,
202                                kind: &value_kind,
203                            },
204                            options: self.options,
205                        },
206                    )?;
207                }
208                map.end()
209            }
210        }
211    }
212}
213
214impl Serialize for SerializeWrapper<'_, MapKey> {
215    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
216    where
217        S: Serializer,
218    {
219        match self.value {
220            MapKey::Bool(value) => serializer.collect_str(value),
221            MapKey::I32(value) => serializer.collect_str(value),
222            MapKey::I64(value) => serializer.collect_str(value),
223            MapKey::U32(value) => serializer.collect_str(value),
224            MapKey::U64(value) => serializer.collect_str(value),
225            MapKey::String(value) => serializer.serialize_str(value),
226        }
227    }
228}