1use base64::{Engine, engine::general_purpose::STANDARD};
16use serde_with::{DeserializeAs, SerializeAs};
17
18pub type DoubleValue = f64;
28
29pub type FloatValue = f32;
39
40pub type Int64Value = i64;
50
51pub type UInt64Value = u64;
61
62pub type Int32Value = i32;
72
73pub type UInt32Value = u32;
83
84pub type BoolValue = bool;
94
95pub type StringValue = String;
105
106pub type BytesValue = bytes::Bytes;
116
117macro_rules! impl_message {
118 ($t: ty) => {
119 impl crate::message::Message for $t {
120 fn typename() -> &'static str {
121 concat!("type.googleapis.com/google.protobuf.", stringify!($t))
122 }
123
124 #[allow(private_interfaces)]
125 fn serializer() -> impl crate::message::MessageSerializer<Self> {
126 crate::message::ValueSerializer::<Self>::new()
127 }
128 }
129 };
130}
131
132impl_message!(Int32Value);
133impl_message!(UInt32Value);
134impl_message!(BoolValue);
135impl_message!(StringValue);
136
137fn encode_value<T>(value: serde_json::Value) -> Result<crate::message::Map, crate::AnyError>
138where
139 T: crate::message::Message,
140{
141 let map: crate::message::Map = [
142 (
143 "@type",
144 serde_json::Value::String(T::typename().to_string()),
145 ),
146 ("value", value),
147 ]
148 .into_iter()
149 .map(|(k, v)| (k.to_string(), v))
150 .collect();
151 Ok(map)
152}
153
154fn encode_string<T>(value: String) -> Result<crate::message::Map, crate::AnyError>
155where
156 T: crate::message::Message,
157{
158 encode_value::<T>(serde_json::Value::String(value))
159}
160
161impl crate::message::Message for UInt64Value {
162 fn typename() -> &'static str {
163 "type.googleapis.com/google.protobuf.UInt64Value"
164 }
165
166 #[allow(private_interfaces)]
167 fn serializer() -> impl crate::message::MessageSerializer<Self> {
168 UInt64ValueSerializer
169 }
170}
171
172struct UInt64ValueSerializer;
173
174impl crate::message::MessageSerializer<UInt64Value> for UInt64ValueSerializer {
175 fn serialize_to_map(
176 &self,
177 message: &UInt64Value,
178 ) -> Result<crate::message::Map, crate::AnyError> {
179 encode_string::<UInt64Value>(message.to_string())
180 }
181
182 fn deserialize_from_map(
183 &self,
184 map: &crate::message::Map,
185 ) -> Result<UInt64Value, crate::AnyError> {
186 map.get("value")
187 .ok_or_else(crate::message::missing_value_field)?
188 .as_str()
189 .ok_or_else(expected_string_value)?
190 .parse::<UInt64Value>()
191 .map_err(crate::AnyError::deser)
192 }
193}
194
195impl crate::message::Message for Int64Value {
196 fn typename() -> &'static str {
197 "type.googleapis.com/google.protobuf.Int64Value"
198 }
199
200 #[allow(private_interfaces)]
201 fn serializer() -> impl crate::message::MessageSerializer<Self>
202 where
203 Self: Sized + serde::ser::Serialize,
204 {
205 Int64ValueSerializer
206 }
207}
208
209struct Int64ValueSerializer;
210
211impl crate::message::MessageSerializer<Int64Value> for Int64ValueSerializer {
212 fn serialize_to_map(
213 &self,
214 message: &Int64Value,
215 ) -> Result<crate::message::Map, crate::AnyError> {
216 encode_string::<Int64Value>(message.to_string())
217 }
218
219 fn deserialize_from_map(
220 &self,
221 map: &crate::message::Map,
222 ) -> Result<Int64Value, crate::AnyError> {
223 map.get("value")
224 .ok_or_else(crate::message::missing_value_field)?
225 .as_str()
226 .ok_or_else(expected_string_value)?
227 .parse::<Int64Value>()
228 .map_err(crate::AnyError::deser)
229 }
230}
231
232impl crate::message::Message for FloatValue {
233 fn typename() -> &'static str {
234 "type.googleapis.com/google.protobuf.FloatValue"
235 }
236
237 #[allow(private_interfaces)]
238 fn serializer() -> impl crate::message::MessageSerializer<Self>
239 where
240 Self: Sized + serde::ser::Serialize,
241 {
242 FloatValueSerializer
243 }
244}
245
246struct FloatValueSerializer;
247
248impl crate::message::MessageSerializer<FloatValue> for FloatValueSerializer {
249 fn serialize_to_map(
250 &self,
251 message: &FloatValue,
252 ) -> Result<crate::message::Map, crate::AnyError> {
253 let value = crate::internal::F32::serialize_as(message, serde_json::value::Serializer)
254 .map_err(crate::AnyError::ser)?;
255 encode_value::<FloatValue>(value)
256 }
257
258 fn deserialize_from_map(
259 &self,
260 map: &crate::message::Map,
261 ) -> Result<FloatValue, crate::AnyError> {
262 let value = map
263 .get("value")
264 .ok_or_else(crate::message::missing_value_field)?;
265 crate::internal::F32::deserialize_as(value).map_err(crate::AnyError::deser)
266 }
267}
268
269impl crate::message::Message for DoubleValue {
270 fn typename() -> &'static str {
271 "type.googleapis.com/google.protobuf.DoubleValue"
272 }
273
274 #[allow(private_interfaces)]
275 fn serializer() -> impl crate::message::MessageSerializer<Self>
276 where
277 Self: Sized + serde::ser::Serialize,
278 {
279 DoubleValueSerializer
280 }
281}
282
283struct DoubleValueSerializer;
284
285impl crate::message::MessageSerializer<DoubleValue> for DoubleValueSerializer {
286 fn serialize_to_map(
287 &self,
288 message: &DoubleValue,
289 ) -> Result<crate::message::Map, crate::AnyError> {
290 let value = crate::internal::F64::serialize_as(message, serde_json::value::Serializer)
291 .map_err(crate::AnyError::ser)?;
292 encode_value::<DoubleValue>(value)
293 }
294
295 fn deserialize_from_map(
296 &self,
297 map: &crate::message::Map,
298 ) -> Result<DoubleValue, crate::AnyError> {
299 let value = map
300 .get("value")
301 .ok_or_else(crate::message::missing_value_field)?;
302 crate::internal::F64::deserialize_as(value).map_err(crate::AnyError::deser)
303 }
304}
305
306impl crate::message::Message for BytesValue {
307 fn typename() -> &'static str {
308 "type.googleapis.com/google.protobuf.BytesValue"
309 }
310
311 #[allow(private_interfaces)]
312 fn serializer() -> impl crate::message::MessageSerializer<Self> {
313 BytesValueSerializer
314 }
315}
316
317struct BytesValueSerializer;
318
319impl crate::message::MessageSerializer<BytesValue> for BytesValueSerializer {
320 fn serialize_to_map(
321 &self,
322 message: &BytesValue,
323 ) -> Result<crate::message::Map, crate::AnyError> {
324 encode_string::<BytesValue>(STANDARD.encode(message))
325 }
326
327 fn deserialize_from_map(
328 &self,
329 map: &crate::message::Map,
330 ) -> Result<BytesValue, crate::AnyError> {
331 let s = map
332 .get("value")
333 .ok_or_else(crate::message::missing_value_field)?
334 .as_str()
335 .ok_or_else(expected_string_value)?;
336 STANDARD
337 .decode(s)
338 .map(BytesValue::from)
339 .map_err(crate::AnyError::deser)
340 }
341}
342
343fn expected_string_value() -> crate::AnyError {
344 crate::AnyError::deser("expected value field to be a string")
345}
346
347#[cfg(test)]
348mod tests {
349 use super::*;
350 use crate::Any;
351 use crate::message::{Message, MessageSerializer};
352 type Result = std::result::Result<(), Box<dyn std::error::Error>>;
353 use test_case::test_case;
354
355 const HELLO_WORLD_BASE64: &str = "SGVsbG8sIFdvcmxkIQ==";
357
358 #[test_case(1234.5 as DoubleValue, 1234.5, "DoubleValue")]
359 #[test_case(9876.5 as FloatValue, 9876.5, "FloatValue")]
360 #[test_case(-123 as Int64Value, "-123", "Int64Value")]
361 #[test_case(123 as UInt64Value, "123", "UInt64Value")]
362 #[test_case(-123 as Int32Value, -123, "Int32Value")]
363 #[test_case(123 as UInt32Value, 123, "UInt32Value")]
364 #[test_case(true as BoolValue, true, "BoolValue")]
365 #[test_case(StringValue::from("Hello, World!"), "Hello, World!", "StringValue")]
366 #[test_case(BytesValue::from("Hello, World!"), HELLO_WORLD_BASE64, "BytesValue")]
367 fn test_wrapper_in_any<I, V>(input: I, value: V, typename: &str) -> Result
368 where
369 I: crate::message::Message
370 + std::fmt::Debug
371 + PartialEq
372 + serde::de::DeserializeOwned
373 + serde::ser::Serialize,
374 V: serde::ser::Serialize,
375 {
376 let any = Any::from_msg(&input)?;
377 let got = serde_json::to_value(&any)?;
378 let want = serde_json::json!({
379 "@type": format!("type.googleapis.com/google.protobuf.{typename}"),
380 "value": value,
381 });
382 assert_eq!(got, want);
383 let output = any.to_msg::<I>()?;
384 assert_eq!(output, input);
385 Ok(())
386 }
387
388 #[test_case(f32::INFINITY as FloatValue, "Infinity")]
389 #[test_case(f32::NEG_INFINITY as FloatValue, "-Infinity")]
390 #[test_case(f32::NAN as FloatValue, "NaN")]
391 #[test_case(9876.5 as FloatValue, 9876.5)]
392 fn test_wrapper_float<V>(input: FloatValue, value: V) -> Result
393 where
394 V: serde::ser::Serialize,
395 {
396 let any = Any::from_msg(&input)?;
397 let got = serde_json::to_value(&any)?;
398 let want = serde_json::json!({
399 "@type": "type.googleapis.com/google.protobuf.FloatValue",
400 "value": value,
401 });
402 assert_eq!(got, want);
403 let output = any.to_msg::<FloatValue>()?;
404 assert!(
407 output.total_cmp(&input) == std::cmp::Ordering::Equal,
408 "expected: {input}, got: {output}"
409 );
410 Ok(())
411 }
412
413 #[test_case(f64::INFINITY as DoubleValue, "Infinity")]
414 #[test_case(f64::NEG_INFINITY as DoubleValue, "-Infinity")]
415 #[test_case(f64::NAN as DoubleValue, "NaN")]
416 #[test_case(9876.5 as DoubleValue, 9876.5)]
417 fn test_wrapper_double<V>(input: DoubleValue, value: V) -> Result
418 where
419 V: serde::ser::Serialize,
420 {
421 let any = Any::from_msg(&input)?;
422 let got = serde_json::to_value(&any)?;
423 let want = serde_json::json!({
424 "@type": "type.googleapis.com/google.protobuf.DoubleValue",
425 "value": value,
426 });
427 assert_eq!(got, want);
428 let output = any.to_msg::<DoubleValue>()?;
429 assert!(
432 output.total_cmp(&input) == std::cmp::Ordering::Equal,
433 "expected: {input}, got: {output}"
434 );
435 Ok(())
436 }
437
438 #[test_case(Int32Value::default(), DoubleValue::default())]
439 #[test_case(Int32Value::default(), FloatValue::default())]
440 #[test_case(DoubleValue::default(), Int64Value::default())]
441 #[test_case(DoubleValue::default(), UInt64Value::default())]
442 #[test_case(DoubleValue::default(), Int32Value::default())]
443 #[test_case(DoubleValue::default(), UInt32Value::default())]
444 #[test_case(DoubleValue::default(), BoolValue::default())]
445 #[test_case(DoubleValue::default(), StringValue::default())]
446 #[test_case(DoubleValue::default(), BytesValue::default())]
447 fn test_wrapper_in_any_with_bad_typenames<T, U>(from: T, _into: U) -> Result
448 where
449 T: Message + std::fmt::Debug + serde::ser::Serialize + serde::de::DeserializeOwned,
450 U: Message + std::fmt::Debug + serde::ser::Serialize + serde::de::DeserializeOwned,
451 {
452 let any = Any::from_msg(&from)?;
453 assert!(any.to_msg::<U>().is_err());
454 Ok(())
455 }
456
457 #[test_case(Int64Value::default(), "Int64Value")]
458 #[test_case(UInt64Value::default(), "UInt64Value")]
459 fn test_wrapper_bad_encoding<T>(_input: T, typename: &str) -> Result
460 where
461 T: Message + std::fmt::Debug + serde::ser::Serialize + serde::de::DeserializeOwned,
462 {
463 let map = serde_json::json!({
464 "@type": format!("type.googleapis.com/google.protobuf.{typename}"),
465 "value": 0,
466 });
467
468 let serializer = T::serializer();
469 let e = serializer.deserialize_from_map(map.as_object().unwrap());
470
471 assert!(e.is_err());
472 let fmt = format!("{e:?}");
473 assert!(fmt.contains("expected value field to be a string"), "{fmt}");
474 Ok(())
475 }
476
477 #[test]
478 fn test_wrapper_bad_encoding_base64() -> Result {
479 let map = serde_json::json!({
480 "@type": "type.googleapis.com/google.protobuf.BytesValue",
481 "value": "Oops, I forgot to base64 encode this.",
482 });
483
484 let serializer = BytesValue::serializer();
485 assert!(
486 serializer
487 .deserialize_from_map(map.as_object().unwrap())
488 .is_err()
489 );
490
491 Ok(())
492 }
493}