hermes_protobuf_encoding_components/impls/
any.rs1use core::fmt::Display;
2use core::marker::PhantomData;
3
4use cgp::prelude::*;
5use hermes_encoding_components::traits::convert::Converter;
6use hermes_encoding_components::traits::decode::Decoder;
7use hermes_encoding_components::traits::encode::Encoder;
8use hermes_encoding_components::traits::schema::HasSchema;
9use hermes_encoding_components::traits::types::encoded::HasEncodedType;
10use prost::{DecodeError, Message};
11use prost_types::Any;
12
13#[derive(Debug)]
14pub struct TypeUrlMismatchError {
15 pub expected_url: String,
16 pub actual_url: String,
17}
18
19pub struct EncodeAsAnyProtobuf<InStrategy, InEncoder>(pub PhantomData<(InStrategy, InEncoder)>);
20
21pub struct DecodeAsAnyProtobuf<InStrategy, InEncoder>(pub PhantomData<(InStrategy, InEncoder)>);
22
23impl<InEncoder, Encoding, Strategy, InStrategy, Value> Encoder<Encoding, Strategy, Value>
24 for EncodeAsAnyProtobuf<InStrategy, InEncoder>
25where
26 Encoding: HasEncodedType<Encoded = Vec<u8>> + HasSchema<Value> + HasErrorType,
27 InEncoder: Encoder<Encoding, InStrategy, Value>,
28 Encoding::Schema: Display,
29 Self: Converter<Encoding, Value, Any>,
30{
31 fn encode(encoding: &Encoding, value: &Value) -> Result<Vec<u8>, Encoding::Error> {
32 let any = Self::convert(encoding, value)?;
33
34 Ok(any.encode_to_vec())
35 }
36}
37
38impl<InEncoder, Encoding, InStrategy, Value> Converter<Encoding, Value, Any>
39 for EncodeAsAnyProtobuf<InStrategy, InEncoder>
40where
41 Encoding: HasEncodedType<Encoded = Vec<u8>> + HasSchema<Value> + HasErrorType,
42 InEncoder: Encoder<Encoding, InStrategy, Value>,
43 Encoding::Schema: Display,
44 InStrategy: Async,
45{
46 fn convert(encoding: &Encoding, value: &Value) -> Result<Any, Encoding::Error> {
47 let encoded = InEncoder::encode(encoding, value)?;
48 let type_url = encoding.schema(PhantomData::<Value>);
49
50 let any = Any {
51 value: encoded,
52 type_url: type_url.to_string(),
53 };
54
55 Ok(any)
56 }
57}
58
59impl<InEncoder, Encoding, Strategy, InStrategy, Value> Decoder<Encoding, Strategy, Value>
60 for DecodeAsAnyProtobuf<InStrategy, InEncoder>
61where
62 Encoding: HasEncodedType<Encoded = Vec<u8>> + CanRaiseError<DecodeError>,
63 Self: Converter<Encoding, Any, Value>,
64{
65 fn decode(encoding: &Encoding, encoded: &Vec<u8>) -> Result<Value, Encoding::Error> {
66 let any: Any = Message::decode(encoded.as_ref()).map_err(Encoding::raise_error)?;
67
68 Self::convert(encoding, &any)
69 }
70}
71
72impl<InEncoder, Encoding, InStrategy, Value> Converter<Encoding, Any, Value>
73 for DecodeAsAnyProtobuf<InStrategy, InEncoder>
74where
75 Encoding:
76 HasEncodedType<Encoded = Vec<u8>> + HasSchema<Value> + CanRaiseError<TypeUrlMismatchError>,
77 InEncoder: Decoder<Encoding, InStrategy, Value>,
78 Encoding::Schema: Display,
79 InStrategy: Async,
80{
81 fn convert(encoding: &Encoding, any: &Any) -> Result<Value, Encoding::Error> {
82 let type_url = encoding.schema(PhantomData::<Value>).to_string();
83
84 if any.type_url != type_url {
85 return Err(Encoding::raise_error(TypeUrlMismatchError {
86 expected_url: type_url,
87 actual_url: any.type_url.clone(),
88 }));
89 }
90
91 InEncoder::decode(encoding, &any.value)
92 }
93}