up_rust/uattributes/
upayloadformat.rs1use crate::up_core_api::uattributes::UPayloadFormat;
15use mediatype::MediaType;
16use protobuf::EnumFull;
17
18#[derive(Debug)]
19pub enum UPayloadError {
20 SerializationError(String),
21 MediatypeProblem,
22}
23
24impl UPayloadError {
25 pub fn serialization_error<T>(message: T) -> UPayloadError
26 where
27 T: Into<String>,
28 {
29 Self::SerializationError(message.into())
30 }
31
32 pub fn mediatype_error() -> UPayloadError {
33 Self::MediatypeProblem
34 }
35}
36
37impl std::fmt::Display for UPayloadError {
38 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39 match self {
40 Self::SerializationError(e) => f.write_fmt(format_args!("Serialization error: {}", e)),
41 Self::MediatypeProblem => {
42 f.write_fmt(format_args!("Mediatype problem unsupported or malformed"))
43 }
44 }
45 }
46}
47
48impl std::error::Error for UPayloadError {}
49
50impl UPayloadFormat {
51 pub fn from_media_type(media_type_string: &str) -> Result<Self, UPayloadError> {
70 if let Ok(media_type) = MediaType::parse(media_type_string) {
71 let descriptor = UPayloadFormat::enum_descriptor();
72 return descriptor
73 .values()
74 .find_map(|desc| {
75 let proto_desc = desc.proto();
76
77 crate::up_core_api::uoptions::exts::mime_type
78 .get(proto_desc.options.get_or_default())
79 .and_then(|mime_type_option_value| {
80 if let Ok(enum_mime_type) = MediaType::parse(&mime_type_option_value) {
81 if enum_mime_type.ty == media_type.ty
82 && enum_mime_type.subty == media_type.subty
83 {
84 return desc.cast::<Self>();
85 }
86 }
87 None
88 })
89 })
90 .ok_or(UPayloadError::mediatype_error());
91 }
92 Err(UPayloadError::mediatype_error())
93 }
94
95 pub fn to_media_type(self) -> Option<String> {
110 let desc = self.descriptor();
111 let desc_proto = desc.proto();
112 crate::up_core_api::uoptions::exts::mime_type.get(desc_proto.options.get_or_default())
113 }
114}
115
116#[cfg(test)]
117mod tests {
118 use super::*;
119
120 use test_case::test_case;
121
122 #[test_case("application/json", Ok(UPayloadFormat::UPAYLOAD_FORMAT_JSON); "map from JSON")]
123 #[test_case(
124 "application/json; charset=utf-8",
125 Ok(UPayloadFormat::UPAYLOAD_FORMAT_JSON);
126 "map from JSON with parameter"
127 )]
128 #[test_case("application/protobuf", Ok(UPayloadFormat::UPAYLOAD_FORMAT_PROTOBUF); "map from PROTOBUF")]
129 #[test_case(
130 "application/x-protobuf",
131 Ok(UPayloadFormat::UPAYLOAD_FORMAT_PROTOBUF_WRAPPED_IN_ANY); "map from PROTOBUF_WRAPPED"
132 )]
133 #[test_case("application/octet-stream", Ok(UPayloadFormat::UPAYLOAD_FORMAT_RAW); "map from RAW")]
134 #[test_case("application/x-someip", Ok(UPayloadFormat::UPAYLOAD_FORMAT_SOMEIP); "map from SOMEIP")]
135 #[test_case(
136 "application/x-someip_tlv",
137 Ok(UPayloadFormat::UPAYLOAD_FORMAT_SOMEIP_TLV); "map from SOMEIP_TLV"
138 )]
139 #[test_case("text/plain", Ok(UPayloadFormat::UPAYLOAD_FORMAT_TEXT); "map from TEXT")]
140 #[test_case("application/unsupported; foo=bar", Err(UPayloadError::mediatype_error()); "fail for unsupported media type")]
141 fn test_from_media_type(
142 media_type: &str,
143 expected_format: Result<UPayloadFormat, UPayloadError>,
144 ) {
145 let parsing_result = UPayloadFormat::from_media_type(media_type);
146 assert!(parsing_result.is_ok() == expected_format.is_ok());
147 if let Ok(format) = expected_format {
148 assert_eq!(format, parsing_result.unwrap());
149 }
150 }
151
152 #[test_case(UPayloadFormat::UPAYLOAD_FORMAT_JSON, Some("application/json".to_string()); "map JSON format to media type")]
153 #[test_case(UPayloadFormat::UPAYLOAD_FORMAT_PROTOBUF, Some("application/protobuf".to_string()); "map PROTOBUF format to media type")]
154 #[test_case(UPayloadFormat::UPAYLOAD_FORMAT_PROTOBUF_WRAPPED_IN_ANY, Some("application/x-protobuf".to_string()); "map PROTOBUF_WRAPPED format to media type")]
155 #[test_case(UPayloadFormat::UPAYLOAD_FORMAT_RAW, Some("application/octet-stream".to_string()); "map RAW format to media type")]
156 #[test_case(UPayloadFormat::UPAYLOAD_FORMAT_SOMEIP, Some("application/x-someip".to_string()); "map SOMEIP format to media type")]
157 #[test_case(UPayloadFormat::UPAYLOAD_FORMAT_SOMEIP_TLV, Some("application/x-someip_tlv".to_string()); "map SOMEIP_TLV format to media type")]
158 #[test_case(UPayloadFormat::UPAYLOAD_FORMAT_TEXT, Some("text/plain".to_string()); "map TEXT format to media type")]
159 #[test_case(UPayloadFormat::UPAYLOAD_FORMAT_UNSPECIFIED, None; "map UNSPECIFIED format to None")]
160 fn test_to_media_type(format: UPayloadFormat, expected_media_type: Option<String>) {
161 assert_eq!(format.to_media_type(), expected_media_type);
162 }
163}