google_cloud_wkt/
message.rs

1// Copyright 2025 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Define traits required of all messages.
16
17pub(crate) type Map = serde_json::Map<String, serde_json::Value>;
18use crate::AnyError as Error;
19
20/// A trait that must be implemented by all messages.
21///
22/// Messages sent to and received from Google Cloud services may be wrapped in
23/// [Any][crate::any::Any]. `Any` uses a `@type` field to encoding the type
24/// name and then validates extraction and insertion against this type.
25pub trait Message {
26    /// The typename of this message.
27    fn typename() -> &'static str;
28
29    /// Store the value into a JSON object.
30    fn to_map(&self) -> Result<Map, Error>
31    where
32        Self: serde::ser::Serialize + Sized,
33    {
34        to_json_object(self)
35    }
36
37    /// Extract the value from a JSON object.
38    fn from_map(map: &Map) -> Result<Self, Error>
39    where
40        Self: serde::de::DeserializeOwned,
41    {
42        serde_json::from_value::<Self>(serde_json::Value::Object(map.clone())).map_err(Error::deser)
43    }
44}
45
46pub(crate) fn to_json_object<T>(message: &T) -> Result<Map, Error>
47where
48    T: Message + serde::ser::Serialize,
49{
50    use serde_json::Value;
51
52    let value = serde_json::to_value(message).map_err(Error::ser)?;
53    match value {
54        Value::Object(mut map) => {
55            map.insert(
56                "@type".to_string(),
57                Value::String(T::typename().to_string()),
58            );
59            Ok(map)
60        }
61        _ => Err(unexpected_json_type()),
62    }
63}
64
65pub(crate) fn to_json_string<T>(message: &T) -> Result<Map, Error>
66where
67    T: Message + serde::ser::Serialize,
68{
69    use serde_json::Value;
70    let value = serde_json::to_value(message).map_err(Error::ser)?;
71    match value {
72        Value::String(s) => {
73            // Only a few well-known messages are serialized into something
74            // other than a object. In all cases, they are serialized using
75            // a small JSON object, with the string in the `value` field.
76            let map: Map = [("@type", T::typename().to_string()), ("value", s)]
77                .into_iter()
78                .map(|(k, v)| (k.to_string(), Value::String(v)))
79                .collect();
80            Ok(map)
81        }
82        _ => Err(unexpected_json_type()),
83    }
84}
85
86pub(crate) fn from_value<T>(map: &Map) -> Result<T, Error>
87where
88    T: serde::de::DeserializeOwned,
89{
90    map.get("value")
91        .map(|v| serde_json::from_value::<T>(v.clone()))
92        .ok_or_else(missing_value_field)?
93        .map_err(Error::deser)
94}
95
96pub(crate) fn missing_value_field() -> Error {
97    Error::deser("value field is missing")
98}
99
100fn unexpected_json_type() -> Error {
101    Error::ser("unexpected JSON type, only Object and String are supported")
102}