Skip to content

Commit

Permalink
Add non-compliant JSON serialization for Any
Browse files Browse the repository at this point in the history
  • Loading branch information
romac committed Jul 30, 2024
1 parent 965b255 commit cd3b9f0
Showing 1 changed file with 125 additions and 28 deletions.
153 changes: 125 additions & 28 deletions proto/src/google/protobuf/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Copyright 2022 Dan Burkert & Tokio Contributors

use prost::{DecodeError, EncodeError, Message, Name};
use subtle_encoding::base64;

use crate::prelude::*;

Expand Down Expand Up @@ -33,37 +34,18 @@ use super::PACKAGE;
///
/// # JSON
///
/// > JSON serialization of Any cannot be made compatible with the specification,
/// > and is therefore left unimplemented at the moment.
/// > See <https://github.com/influxdata/pbjson/issues/2> for more information.
/// JSON serialization of Any cannot be made compatible with the specification.
/// See <https://github.com/influxdata/pbjson/issues/2> for more information.
///
/// The JSON representation of an `Any` value uses the regular
/// representation of the deserialized, embedded message, with an
/// additional field `@type` which contains the type URL. Example:
/// At the moment, an `Any` struct will be serialized as a JSON object with two fields:
/// - `typeUrl` (string): the type URL of the message
/// - `value` (string): the base64-encoded serialized message
///
/// ```text
/// package google.profile;
/// message Person {
/// string first_name = 1;
/// string last_name = 2;
/// }
///
/// {
/// "@type": "type.googleapis.com/google.profile.Person",
/// "firstName": <string>,
/// "lastName": <string>
/// }
/// ```
///
/// If the embedded message type is well-known and has a custom JSON
/// representation, that representation will be embedded adding a field
/// `value` which holds the custom JSON in addition to the `@type`
/// field. Example (for message \[google.protobuf.Duration\]\[\]):
///
/// ```text
/// For example:
/// ```json
/// {
/// "@type": "type.googleapis.com/google.protobuf.Duration",
/// "value": "1.212s"
/// "typeUrl": "type.googleapis.com/google.protobuf.Duration",
/// "value": "Cg0KB2NvcnA="
/// }
/// ```
#[derive(Clone, PartialEq, Eq, ::prost::Message)]
Expand Down Expand Up @@ -148,3 +130,118 @@ impl Name for Any {
type_url_for::<Self>()
}
}

impl serde::Serialize for Any {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>

Check failure on line 135 in proto/src/google/protobuf/any.rs

View workflow job for this annotation

GitHub Actions / clippy

[clippy] proto/src/google/protobuf/any.rs#L135

error[E0433]: failed to resolve: use of undeclared crate or module `std` --> /home/runner/work/tendermint-rs/tendermint-rs/proto/src/google/protobuf/any.rs:135:46 | 135 | fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> | ^^^ use of undeclared crate or module `std` | help: consider importing this module | 4 + use core::result; | help: if you import `result`, refer to it directly | 135 - fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> 135 + fn serialize<S>(&self, serializer: S) -> result::Result<S::Ok, S::Error> |
Raw output
/home/runner/work/tendermint-rs/tendermint-rs/proto/src/google/protobuf/any.rs:135:46:e:error[E0433]: failed to resolve: use of undeclared crate or module `std`
   --> /home/runner/work/tendermint-rs/tendermint-rs/proto/src/google/protobuf/any.rs:135:46
    |
135 |     fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
    |                                              ^^^ use of undeclared crate or module `std`
    |
help: consider importing this module
    |
4   + use core::result;
    |
help: if you import `result`, refer to it directly
    |
135 -     fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
135 +     fn serialize<S>(&self, serializer: S) -> result::Result<S::Ok, S::Error>
    |


__END__
where
S: serde::Serializer,
{
use serde::ser::SerializeStruct;
let mut len = 0;
if !self.type_url.is_empty() {
len += 1;
}
if !self.value.is_empty() {
len += 1;
}
let mut struct_ser = serializer.serialize_struct("google.protobuf.Any", len)?;
if !self.type_url.is_empty() {
struct_ser.serialize_field("typeUrl", &self.type_url)?;
}
if !self.value.is_empty() {
// NOTE: A base64 string is always valid UTF-8.
struct_ser.serialize_field(
"value",
&String::from_utf8_lossy(&base64::encode(&self.value)),
)?;
}
struct_ser.end()
}
}
impl<'de> serde::Deserialize<'de> for Any {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>

Check failure on line 162 in proto/src/google/protobuf/any.rs

View workflow job for this annotation

GitHub Actions / clippy

[clippy] proto/src/google/protobuf/any.rs#L162

error[E0433]: failed to resolve: use of undeclared crate or module `std` --> /home/runner/work/tendermint-rs/tendermint-rs/proto/src/google/protobuf/any.rs:162:43 | 162 | fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error> | ^^^ use of undeclared crate or module `std` | help: consider importing this module | 4 + use core::result; | help: if you import `result`, refer to it directly | 162 - fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error> 162 + fn deserialize<D>(deserializer: D) -> result::Result<Self, D::Error> |
Raw output
/home/runner/work/tendermint-rs/tendermint-rs/proto/src/google/protobuf/any.rs:162:43:e:error[E0433]: failed to resolve: use of undeclared crate or module `std`
   --> /home/runner/work/tendermint-rs/tendermint-rs/proto/src/google/protobuf/any.rs:162:43
    |
162 |     fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
    |                                           ^^^ use of undeclared crate or module `std`
    |
help: consider importing this module
    |
4   + use core::result;
    |
help: if you import `result`, refer to it directly
    |
162 -     fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
162 +     fn deserialize<D>(deserializer: D) -> result::Result<Self, D::Error>
    |


__END__
where
D: serde::Deserializer<'de>,
{
const FIELDS: &[&str] = &["type_url", "typeUrl", "value"];

#[allow(clippy::enum_variant_names)]
enum GeneratedField {
TypeUrl,
Value,
}
impl<'de> serde::Deserialize<'de> for GeneratedField {
fn deserialize<D>(deserializer: D) -> std::result::Result<GeneratedField, D::Error>

Check failure on line 174 in proto/src/google/protobuf/any.rs

View workflow job for this annotation

GitHub Actions / clippy

[clippy] proto/src/google/protobuf/any.rs#L174

error[E0433]: failed to resolve: use of undeclared crate or module `std` --> /home/runner/work/tendermint-rs/tendermint-rs/proto/src/google/protobuf/any.rs:174:51 | 174 | fn deserialize<D>(deserializer: D) -> std::result::Result<GeneratedField, D::Error> | ^^^ use of undeclared crate or module `std` | help: consider importing this module | 4 + use core::result; | help: if you import `result`, refer to it directly | 174 - fn deserialize<D>(deserializer: D) -> std::result::Result<GeneratedField, D::Error> 174 + fn deserialize<D>(deserializer: D) -> result::Result<GeneratedField, D::Error> |
Raw output
/home/runner/work/tendermint-rs/tendermint-rs/proto/src/google/protobuf/any.rs:174:51:e:error[E0433]: failed to resolve: use of undeclared crate or module `std`
   --> /home/runner/work/tendermint-rs/tendermint-rs/proto/src/google/protobuf/any.rs:174:51
    |
174 |             fn deserialize<D>(deserializer: D) -> std::result::Result<GeneratedField, D::Error>
    |                                                   ^^^ use of undeclared crate or module `std`
    |
help: consider importing this module
    |
4   + use core::result;
    |
help: if you import `result`, refer to it directly
    |
174 -             fn deserialize<D>(deserializer: D) -> std::result::Result<GeneratedField, D::Error>
174 +             fn deserialize<D>(deserializer: D) -> result::Result<GeneratedField, D::Error>
    |


__END__
where
D: serde::Deserializer<'de>,
{
struct GeneratedVisitor;

impl<'de> serde::de::Visitor<'de> for GeneratedVisitor {
type Value = GeneratedField;

fn expecting(
&self,
formatter: &mut std::fmt::Formatter<'_>,

Check failure on line 185 in proto/src/google/protobuf/any.rs

View workflow job for this annotation

GitHub Actions / clippy

[clippy] proto/src/google/protobuf/any.rs#L185

error[E0433]: failed to resolve: use of undeclared crate or module `std` --> /home/runner/work/tendermint-rs/tendermint-rs/proto/src/google/protobuf/any.rs:185:41 | 185 | formatter: &mut std::fmt::Formatter<'_>, | ^^^ use of undeclared crate or module `std` | help: consider importing one of these items | 4 + use alloc::fmt; | 4 + use core::fmt; | help: if you import `fmt`, refer to it directly | 185 - formatter: &mut std::fmt::Formatter<'_>, 185 + formatter: &mut fmt::Formatter<'_>, |
Raw output
/home/runner/work/tendermint-rs/tendermint-rs/proto/src/google/protobuf/any.rs:185:41:e:error[E0433]: failed to resolve: use of undeclared crate or module `std`
   --> /home/runner/work/tendermint-rs/tendermint-rs/proto/src/google/protobuf/any.rs:185:41
    |
185 |                         formatter: &mut std::fmt::Formatter<'_>,
    |                                         ^^^ use of undeclared crate or module `std`
    |
help: consider importing one of these items
    |
4   + use alloc::fmt;
    |
4   + use core::fmt;
    |
help: if you import `fmt`, refer to it directly
    |
185 -                         formatter: &mut std::fmt::Formatter<'_>,
185 +                         formatter: &mut fmt::Formatter<'_>,
    |


__END__
) -> std::fmt::Result {

Check failure on line 186 in proto/src/google/protobuf/any.rs

View workflow job for this annotation

GitHub Actions / clippy

[clippy] proto/src/google/protobuf/any.rs#L186

error[E0433]: failed to resolve: use of undeclared crate or module `std` --> /home/runner/work/tendermint-rs/tendermint-rs/proto/src/google/protobuf/any.rs:186:26 | 186 | ) -> std::fmt::Result { | ^^^ use of undeclared crate or module `std` | help: consider importing one of these items | 4 + use alloc::fmt; | 4 + use core::fmt; | help: if you import `fmt`, refer to it directly | 186 - ) -> std::fmt::Result { 186 + ) -> fmt::Result { |
Raw output
/home/runner/work/tendermint-rs/tendermint-rs/proto/src/google/protobuf/any.rs:186:26:e:error[E0433]: failed to resolve: use of undeclared crate or module `std`
   --> /home/runner/work/tendermint-rs/tendermint-rs/proto/src/google/protobuf/any.rs:186:26
    |
186 |                     ) -> std::fmt::Result {
    |                          ^^^ use of undeclared crate or module `std`
    |
help: consider importing one of these items
    |
4   + use alloc::fmt;
    |
4   + use core::fmt;
    |
help: if you import `fmt`, refer to it directly
    |
186 -                     ) -> std::fmt::Result {
186 +                     ) -> fmt::Result {
    |


__END__
write!(formatter, "expected one of: {:?}", &FIELDS)
}

#[allow(unused_variables)]
fn visit_str<E>(self, value: &str) -> std::result::Result<GeneratedField, E>

Check failure on line 191 in proto/src/google/protobuf/any.rs

View workflow job for this annotation

GitHub Actions / clippy

[clippy] proto/src/google/protobuf/any.rs#L191

error[E0433]: failed to resolve: use of undeclared crate or module `std` --> /home/runner/work/tendermint-rs/tendermint-rs/proto/src/google/protobuf/any.rs:191:59 | 191 | fn visit_str<E>(self, value: &str) -> std::result::Result<GeneratedField, E> | ^^^ use of undeclared crate or module `std` | help: consider importing this module | 4 + use core::result; | help: if you import `result`, refer to it directly | 191 - fn visit_str<E>(self, value: &str) -> std::result::Result<GeneratedField, E> 191 + fn visit_str<E>(self, value: &str) -> result::Result<GeneratedField, E> |
Raw output
/home/runner/work/tendermint-rs/tendermint-rs/proto/src/google/protobuf/any.rs:191:59:e:error[E0433]: failed to resolve: use of undeclared crate or module `std`
   --> /home/runner/work/tendermint-rs/tendermint-rs/proto/src/google/protobuf/any.rs:191:59
    |
191 |                     fn visit_str<E>(self, value: &str) -> std::result::Result<GeneratedField, E>
    |                                                           ^^^ use of undeclared crate or module `std`
    |
help: consider importing this module
    |
4   + use core::result;
    |
help: if you import `result`, refer to it directly
    |
191 -                     fn visit_str<E>(self, value: &str) -> std::result::Result<GeneratedField, E>
191 +                     fn visit_str<E>(self, value: &str) -> result::Result<GeneratedField, E>
    |


__END__
where
E: serde::de::Error,
{
match value {
"typeUrl" | "type_url" => Ok(GeneratedField::TypeUrl),
"value" => Ok(GeneratedField::Value),
_ => Err(serde::de::Error::unknown_field(value, FIELDS)),
}
}
}
deserializer.deserialize_identifier(GeneratedVisitor)
}
}
struct GeneratedVisitor;
impl<'de> serde::de::Visitor<'de> for GeneratedVisitor {
type Value = Any;

fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {

Check failure on line 209 in proto/src/google/protobuf/any.rs

View workflow job for this annotation

GitHub Actions / clippy

[clippy] proto/src/google/protobuf/any.rs#L209

error[E0433]: failed to resolve: use of undeclared crate or module `std` --> /home/runner/work/tendermint-rs/tendermint-rs/proto/src/google/protobuf/any.rs:209:49 | 209 | fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ^^^ use of undeclared crate or module `std` | help: consider importing one of these items | 4 + use alloc::fmt; | 4 + use core::fmt; | help: if you import `fmt`, refer to it directly | 209 - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 209 + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> std::fmt::Result { |
Raw output
/home/runner/work/tendermint-rs/tendermint-rs/proto/src/google/protobuf/any.rs:209:49:e:error[E0433]: failed to resolve: use of undeclared crate or module `std`
   --> /home/runner/work/tendermint-rs/tendermint-rs/proto/src/google/protobuf/any.rs:209:49
    |
209 |             fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    |                                                 ^^^ use of undeclared crate or module `std`
    |
help: consider importing one of these items
    |
4   + use alloc::fmt;
    |
4   + use core::fmt;
    |
help: if you import `fmt`, refer to it directly
    |
209 -             fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
209 +             fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> std::fmt::Result {
    |


__END__

Check failure on line 209 in proto/src/google/protobuf/any.rs

View workflow job for this annotation

GitHub Actions / clippy

[clippy] proto/src/google/protobuf/any.rs#L209

error[E0433]: failed to resolve: use of undeclared crate or module `std` --> /home/runner/work/tendermint-rs/tendermint-rs/proto/src/google/protobuf/any.rs:209:77 | 209 | fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ^^^ use of undeclared crate or module `std` | help: consider importing one of these items | 4 + use alloc::fmt; | 4 + use core::fmt; | help: if you import `fmt`, refer to it directly | 209 - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 209 + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> fmt::Result { |
Raw output
/home/runner/work/tendermint-rs/tendermint-rs/proto/src/google/protobuf/any.rs:209:77:e:error[E0433]: failed to resolve: use of undeclared crate or module `std`
   --> /home/runner/work/tendermint-rs/tendermint-rs/proto/src/google/protobuf/any.rs:209:77
    |
209 |             fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    |                                                                             ^^^ use of undeclared crate or module `std`
    |
help: consider importing one of these items
    |
4   + use alloc::fmt;
    |
4   + use core::fmt;
    |
help: if you import `fmt`, refer to it directly
    |
209 -             fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
209 +             fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> fmt::Result {
    |


__END__
formatter.write_str("struct google.protobuf.Any")
}

fn visit_map<V>(self, mut map_: V) -> std::result::Result<Any, V::Error>

Check failure on line 213 in proto/src/google/protobuf/any.rs

View workflow job for this annotation

GitHub Actions / clippy

[clippy] proto/src/google/protobuf/any.rs#L213

error[E0433]: failed to resolve: use of undeclared crate or module `std` --> /home/runner/work/tendermint-rs/tendermint-rs/proto/src/google/protobuf/any.rs:213:51 | 213 | fn visit_map<V>(self, mut map_: V) -> std::result::Result<Any, V::Error> | ^^^ use of undeclared crate or module `std` | help: consider importing this module | 4 + use core::result; | help: if you import `result`, refer to it directly | 213 - fn visit_map<V>(self, mut map_: V) -> std::result::Result<Any, V::Error> 213 + fn visit_map<V>(self, mut map_: V) -> result::Result<Any, V::Error> |
Raw output
/home/runner/work/tendermint-rs/tendermint-rs/proto/src/google/protobuf/any.rs:213:51:e:error[E0433]: failed to resolve: use of undeclared crate or module `std`
   --> /home/runner/work/tendermint-rs/tendermint-rs/proto/src/google/protobuf/any.rs:213:51
    |
213 |             fn visit_map<V>(self, mut map_: V) -> std::result::Result<Any, V::Error>
    |                                                   ^^^ use of undeclared crate or module `std`
    |
help: consider importing this module
    |
4   + use core::result;
    |
help: if you import `result`, refer to it directly
    |
213 -             fn visit_map<V>(self, mut map_: V) -> std::result::Result<Any, V::Error>
213 +             fn visit_map<V>(self, mut map_: V) -> result::Result<Any, V::Error>
    |


__END__
where
V: serde::de::MapAccess<'de>,
{
let mut type_url__ = None;
let mut value__ = None;
while let Some(k) = map_.next_key()? {
match k {
GeneratedField::TypeUrl => {
if type_url__.is_some() {
return Err(serde::de::Error::duplicate_field("typeUrl"));
}
type_url__ = Some(map_.next_value()?);
},
GeneratedField::Value => {
if value__.is_some() {
return Err(serde::de::Error::duplicate_field("value"));
}
let b64_str = map_.next_value::<String>()?;
let value = base64::decode(b64_str.as_bytes()).map_err(|e| {
serde::de::Error::custom(format!("base64 decode error: {e}"))
})?;
value__ = Some(value);
},
}
}
Ok(Any {
type_url: type_url__.unwrap_or_default(),
value: value__.unwrap_or_default(),
})
}
}
deserializer.deserialize_struct("google.protobuf.Any", FIELDS, GeneratedVisitor)
}
}

0 comments on commit cd3b9f0

Please sign in to comment.