@@ -15,7 +15,7 @@ mod umessagebuilder;
1515mod umessagetype;
1616
1717use bytes:: Bytes ;
18- use protobuf:: { well_known_types:: any:: Any , Message , MessageFull } ;
18+ use protobuf:: { well_known_types:: any:: Any , Enum , Message , MessageFull } ;
1919
2020pub use umessagebuilder:: * ;
2121
@@ -345,54 +345,46 @@ impl UMessage {
345345 . is_some_and ( |attribs| attribs. is_notification ( ) )
346346 }
347347
348- /// If `UMessage` payload is available, deserialize it as a protobuf `Message`.
349- ///
350- /// This function is used to extract strongly-typed data from a `UMessage` object,
351- /// taking into account the payload format (will only succeed if payload format is
352- /// `UPayloadFormat::UPAYLOAD_FORMAT_PROTOBUF` or `UPayloadFormat::UPAYLOAD_FORMAT_PROTOBUF_WRAPPED_IN_ANY`)
348+ /// Deserializes this message's protobuf payload into a type.
353349 ///
354350 /// # Type Parameters
355351 ///
356352 /// * `T`: The target type of the data to be unpacked.
357353 ///
358- /// # Returns
359- ///
360- /// * `Ok(T)`: The deserialized protobuf message contained in the payload.
361- ///
362354 /// # Errors
363355 ///
364- /// * Err(`UMessageError`) if the unpacking process fails, for example if the payload could
365- /// not be deserialized into the target type `T`.
356+ /// Returns an error if the message payload format is neither [UPayloadFormat::UPAYLOAD_FORMAT_PROTOBUF]
357+ /// nor [UPayloadFormat::UPAYLOAD_FORMAT_PROTOBUF_WRAPPED_IN_ANY] or if the bytes in the
358+ /// payload cannot be deserialized into the target type.
366359 pub fn extract_protobuf < T : MessageFull + Default > ( & self ) -> Result < T , UMessageError > {
367- if let Some ( payload) = & self . payload {
360+ if let Some ( payload) = self . payload . as_ref ( ) {
368361 let payload_format = self . attributes . payload_format . enum_value_or_default ( ) ;
369362 deserialize_protobuf_bytes ( payload, & payload_format)
370363 } else {
371364 Err ( UMessageError :: PayloadError (
372- "No embedded payload" . to_string ( ) ,
365+ "Message has no payload" . to_string ( ) ,
373366 ) )
374367 }
375368 }
376369}
377370
378371/// Deserializes a protobuf message from a byte array.
379372///
373+ /// # Type Parameters
374+ ///
375+ /// * `T`: The target type of the data to be unpacked.
376+ ///
380377/// # Arguments
381378///
382379/// * `payload` - The payload data.
383380/// * `payload_format` - The format/encoding of the data. Must be one of
384381/// - `UPayloadFormat::UPAYLOAD_FORMAT_PROTOBUF`
385382/// - `UPayloadFormat::UPAYLOAD_FORMAT_PROTOBUF_WRAPPED_IN_ANY`
386- /// - `UPayloadFormat::UPAYLOAD_FORMAT_UNSPECIFIED`
387- ///
388- /// `UPayloadFormat::UPAYLOAD_FORMAT_UNSPECIFIED` is interpreted as
389- /// `UPayloadFormat::UPAYLOAD_FORMAT_PROTOBUF_WRAPPED_IN_ANY` according to the uProtocol
390- /// specification.
391383///
392384/// # Errors
393385///
394- /// Returns an error if the payload format is unsupported or if the data is can not be deserialized
395- /// based on the given format.
386+ /// Returns an error if the payload format is unsupported or if the data can not be deserialized
387+ /// into the target type based on the given format.
396388pub ( crate ) fn deserialize_protobuf_bytes < T : MessageFull + Default > (
397389 payload : & Bytes ,
398390 payload_format : & UPayloadFormat ,
@@ -401,22 +393,24 @@ pub(crate) fn deserialize_protobuf_bytes<T: MessageFull + Default>(
401393 UPayloadFormat :: UPAYLOAD_FORMAT_PROTOBUF => {
402394 T :: parse_from_tokio_bytes ( payload) . map_err ( UMessageError :: DataSerializationError )
403395 }
404- UPayloadFormat :: UPAYLOAD_FORMAT_PROTOBUF_WRAPPED_IN_ANY
405- | UPayloadFormat :: UPAYLOAD_FORMAT_UNSPECIFIED => Any :: parse_from_tokio_bytes ( payload)
406- . map_err ( UMessageError :: DataSerializationError )
407- . and_then ( |any| match any. unpack ( ) {
408- Ok ( Some ( v) ) => Ok ( v) ,
409- Ok ( None ) => Err ( UMessageError :: PayloadError (
410- "cannot deserialize payload, message type mismatch" . to_string ( ) ,
411- ) ) ,
412- Err ( e) => Err ( UMessageError :: DataSerializationError ( e) ) ,
413- } ) ,
414- _ => Err ( UMessageError :: from ( format ! (
415- "Unknown/invalid/unsupported payload format: {}" ,
416- payload_format
417- . to_media_type( )
418- . unwrap_or( "unknown" . to_string( ) )
419- ) ) ) ,
396+ UPayloadFormat :: UPAYLOAD_FORMAT_PROTOBUF_WRAPPED_IN_ANY => {
397+ Any :: parse_from_tokio_bytes ( payload)
398+ . map_err ( UMessageError :: DataSerializationError )
399+ . and_then ( |any| match any. unpack ( ) {
400+ Ok ( Some ( v) ) => Ok ( v) ,
401+ Ok ( None ) => Err ( UMessageError :: PayloadError (
402+ "cannot deserialize payload, message type mismatch" . to_string ( ) ,
403+ ) ) ,
404+ Err ( e) => Err ( UMessageError :: DataSerializationError ( e) ) ,
405+ } )
406+ }
407+ _ => {
408+ let detail_msg = payload_format. to_media_type ( ) . map_or_else (
409+ || format ! ( "Unknown payload format: {}" , payload_format. value( ) ) ,
410+ |mt| format ! ( "Invalid/unsupported payload format: {mt}" ) ,
411+ ) ;
412+ Err ( UMessageError :: from ( detail_msg) )
413+ }
420414 }
421415}
422416
@@ -438,12 +432,6 @@ mod test {
438432 let any = Any :: pack ( & data. clone ( ) ) . unwrap ( ) ;
439433 let buf: Bytes = any. write_to_bytes ( ) . unwrap ( ) . into ( ) ;
440434
441- let result = deserialize_protobuf_bytes :: < StringValue > (
442- & buf,
443- & UPayloadFormat :: UPAYLOAD_FORMAT_UNSPECIFIED ,
444- ) ;
445- assert ! ( result. is_ok_and( |v| v. value == * "hello world" ) ) ;
446-
447435 let result = deserialize_protobuf_bytes :: < StringValue > (
448436 & buf,
449437 & UPayloadFormat :: UPAYLOAD_FORMAT_PROTOBUF_WRAPPED_IN_ANY ,
@@ -476,6 +464,7 @@ mod test {
476464 #[ test_case( UPayloadFormat :: UPAYLOAD_FORMAT_SOMEIP ; "SOMEIP format" ) ]
477465 #[ test_case( UPayloadFormat :: UPAYLOAD_FORMAT_SOMEIP_TLV ; "SOMEIP TLV format" ) ]
478466 #[ test_case( UPayloadFormat :: UPAYLOAD_FORMAT_TEXT ; "TEXT format" ) ]
467+ #[ test_case( UPayloadFormat :: UPAYLOAD_FORMAT_UNSPECIFIED ; "UNSPECIFIED format" ) ]
479468 fn test_deserialize_protobuf_bytes_fails_for_ ( format : UPayloadFormat ) {
480469 let result = deserialize_protobuf_bytes :: < UStatus > ( & "hello" . into ( ) , & format) ;
481470 assert ! ( result. is_err_and( |e| matches!( e, UMessageError :: PayloadError ( _) ) ) ) ;
0 commit comments