Skip to content

Commit

Permalink
Assume PROTOBUF_WRAPPED_IN_ANY if format is unspecified
Browse files Browse the repository at this point in the history
UMessage::deserialize_protobuf_bytes has been adapted to interpret
UPayloadFormat::UPAYLOAD_FORMAT_UNSPECIFIED as
UPayloadFormat::UPAYLOAD_FORMAT_PROTOBUF_WRAPPED_IN_ANY as mandated
by the uProtocol specification.
  • Loading branch information
sophokles73 committed Aug 20, 2024
1 parent f4109d1 commit 73af010
Showing 1 changed file with 41 additions and 20 deletions.
61 changes: 41 additions & 20 deletions src/umessage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,22 @@ impl UMessage {

/// Deserializes a protobuf message from a byte array.
///
/// Will only succeed if payload format is one of
/// - `UPayloadFormat::UPAYLOAD_FORMAT_PROTOBUF`
/// - `UPayloadFormat::UPAYLOAD_FORMAT_PROTOBUF_WRAPPED_IN_ANY`
/// # Arguments
///
/// * `payload` - The payload data.
/// * `payload_format` - The format/encoding of the data. Must be one of
/// - `UPayloadFormat::UPAYLOAD_FORMAT_PROTOBUF`
/// - `UPayloadFormat::UPAYLOAD_FORMAT_PROTOBUF_WRAPPED_IN_ANY`
/// - `UPayloadFormat::UPAYLOAD_FORMAT_UNSPECIFIED`
///
/// `UPayloadFormat::UPAYLOAD_FORMAT_UNSPECIFIED` is interpreted as
/// `UPayloadFormat::UPAYLOAD_FORMAT_PROTOBUF_WRAPPED_IN_ANY` according to the uProtocol
/// specification.
///
/// # Errors
///
/// Returns an error if the payload format is unsupported or if the data is can not be deserialized
/// based on the given format.
pub(crate) fn deserialize_protobuf_bytes<T: MessageFull + Default>(
payload: &Bytes,
payload_format: &UPayloadFormat,
Expand All @@ -201,17 +214,16 @@ pub(crate) fn deserialize_protobuf_bytes<T: MessageFull + Default>(
UPayloadFormat::UPAYLOAD_FORMAT_PROTOBUF => {
T::parse_from_tokio_bytes(payload).map_err(UMessageError::DataSerializationError)
}
UPayloadFormat::UPAYLOAD_FORMAT_PROTOBUF_WRAPPED_IN_ANY => {
Any::parse_from_tokio_bytes(payload)
.map_err(UMessageError::DataSerializationError)
.and_then(|any| match any.unpack() {
Ok(Some(v)) => Ok(v),
Ok(None) => Err(UMessageError::PayloadError(
"cannot deserialize payload, message type mismatch".to_string(),
)),
Err(e) => Err(UMessageError::DataSerializationError(e)),
})
}
UPayloadFormat::UPAYLOAD_FORMAT_PROTOBUF_WRAPPED_IN_ANY
| UPayloadFormat::UPAYLOAD_FORMAT_UNSPECIFIED => Any::parse_from_tokio_bytes(payload)
.map_err(UMessageError::DataSerializationError)
.and_then(|any| match any.unpack() {
Ok(Some(v)) => Ok(v),
Ok(None) => Err(UMessageError::PayloadError(
"cannot deserialize payload, message type mismatch".to_string(),
)),
Err(e) => Err(UMessageError::DataSerializationError(e)),
}),
_ => Err(UMessageError::from(
"Unknown/invalid/unsupported payload format",
)),
Expand All @@ -223,6 +235,7 @@ mod test {
use std::io;

use protobuf::well_known_types::{any::Any, duration::Duration, wrappers::StringValue};
use test_case::test_case;

use crate::{UAttributes, UStatus};

Expand All @@ -235,6 +248,12 @@ mod test {
let any = Any::pack(&data.clone()).unwrap();
let buf: Bytes = any.write_to_bytes().unwrap().into();

let result = deserialize_protobuf_bytes::<StringValue>(
&buf,
&UPayloadFormat::UPAYLOAD_FORMAT_UNSPECIFIED,
);
assert!(result.is_ok_and(|v| v.value == *"hello world"));

let result = deserialize_protobuf_bytes::<StringValue>(
&buf,
&UPayloadFormat::UPAYLOAD_FORMAT_PROTOBUF_WRAPPED_IN_ANY,
Expand All @@ -261,12 +280,14 @@ mod test {
assert!(result.is_err_and(|e| matches!(e, UMessageError::PayloadError(_))));
}

#[test]
fn test_deserialize_protobuf_bytes_fails_for_unsupported_format() {
let result = deserialize_protobuf_bytes::<UStatus>(
&"hello".into(),
&UPayloadFormat::UPAYLOAD_FORMAT_TEXT,
);
#[test_case(UPayloadFormat::UPAYLOAD_FORMAT_JSON; "JSON format")]
#[test_case(UPayloadFormat::UPAYLOAD_FORMAT_RAW; "RAW format")]
#[test_case(UPayloadFormat::UPAYLOAD_FORMAT_SHM; "SHM format")]
#[test_case(UPayloadFormat::UPAYLOAD_FORMAT_SOMEIP; "SOMEIP format")]
#[test_case(UPayloadFormat::UPAYLOAD_FORMAT_SOMEIP_TLV; "SOMEIP TLV format")]
#[test_case(UPayloadFormat::UPAYLOAD_FORMAT_TEXT; "TEXT format")]
fn test_deserialize_protobuf_bytes_fails_for_(format: UPayloadFormat) {
let result = deserialize_protobuf_bytes::<UStatus>(&"hello".into(), &format);
assert!(result.is_err_and(|e| matches!(e, UMessageError::PayloadError(_))));
}

Expand Down

0 comments on commit 73af010

Please sign in to comment.