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