up_rust/umessage/
umessagetype.rs

1/********************************************************************************
2 * Copyright (c) 2023 Contributors to the Eclipse Foundation
3 *
4 * See the NOTICE file(s) distributed with this work for additional
5 * information regarding copyright ownership.
6 *
7 * This program and the accompanying materials are made available under the
8 * terms of the Apache License Version 2.0 which is available at
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * SPDX-License-Identifier: Apache-2.0
12 ********************************************************************************/
13
14use protobuf::EnumFull;
15
16use crate::uattributes::UAttributesError;
17pub use crate::up_core_api::uattributes::UMessageType;
18use crate::up_core_api::uoptions::exts::ce_name;
19
20impl UMessageType {
21    /// Gets this message type's CloudEvent type name.
22    ///
23    /// # Returns
24    ///
25    /// The value to use for the *type* property when mapping to a CloudEvent.
26    pub fn to_cloudevent_type(&self) -> String {
27        let desc = self.descriptor();
28        let desc_proto = desc.proto();
29        ce_name
30            .get(desc_proto.options.get_or_default())
31            .unwrap_or_default()
32    }
33
34    /// Gets the message type for a CloudEvent type name.
35    ///
36    /// # Errors
37    ///
38    /// Returns a [`UAttributesError::ParsingError`] if the given name does not match
39    /// any of the supported message types.
40    pub fn try_from_cloudevent_type<S: Into<String>>(value: S) -> Result<Self, UAttributesError> {
41        let type_string = value.into();
42
43        Self::enum_descriptor()
44            .values()
45            .find_map(|desc| {
46                let proto_desc = desc.proto();
47
48                ce_name
49                    .get(proto_desc.options.get_or_default())
50                    .and_then(|prio_option_value| {
51                        if prio_option_value.eq(type_string.as_str()) {
52                            desc.cast::<Self>()
53                        } else {
54                            None
55                        }
56                    })
57            })
58            .ok_or_else(|| {
59                UAttributesError::parsing_error(format!("unknown message type: {type_string}"))
60            })
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use test_case::test_case;
67
68    use crate::{UAttributesError, UMessageType};
69
70    const TYPE_PUBLISH: &str = "up-pub.v1";
71    const TYPE_NOTIFICATION: &str = "up-not.v1";
72    const TYPE_REQUEST: &str = "up-req.v1";
73    const TYPE_RESPONSE: &str = "up-res.v1";
74
75    #[test_case(UMessageType::UMESSAGE_TYPE_PUBLISH, TYPE_PUBLISH; "for PUBLISH")]
76    #[test_case(UMessageType::UMESSAGE_TYPE_NOTIFICATION, TYPE_NOTIFICATION; "for NOTIFICATION")]
77    #[test_case(UMessageType::UMESSAGE_TYPE_REQUEST, TYPE_REQUEST; "for REQUEST")]
78    #[test_case(UMessageType::UMESSAGE_TYPE_RESPONSE, TYPE_RESPONSE; "for RESPONSE")]
79    fn test_to_cloudevent_type(message_type: UMessageType, expected_ce_name: &str) {
80        assert_eq!(message_type.to_cloudevent_type(), expected_ce_name);
81    }
82
83    #[test_case(TYPE_PUBLISH, Some(UMessageType::UMESSAGE_TYPE_PUBLISH); "succeeds for PUBLISH")]
84    #[test_case(TYPE_NOTIFICATION, Some(UMessageType::UMESSAGE_TYPE_NOTIFICATION); "succeeds for NOTIFICATION")]
85    #[test_case(TYPE_REQUEST, Some(UMessageType::UMESSAGE_TYPE_REQUEST); "succeeds for REQUEST")]
86    #[test_case(TYPE_RESPONSE, Some(UMessageType::UMESSAGE_TYPE_RESPONSE); "succeeds for RESPONSE")]
87    #[test_case("foo.bar", None; "fails for unknown type")]
88    fn test_try_from_cloudevent_type(
89        cloudevent_type: &str,
90        expected_message_type: Option<UMessageType>,
91    ) {
92        let result = UMessageType::try_from_cloudevent_type(cloudevent_type);
93        assert!(result.is_ok() == expected_message_type.is_some());
94        if expected_message_type.is_some() {
95            assert_eq!(result.unwrap(), expected_message_type.unwrap())
96        } else {
97            assert!(matches!(
98                result.unwrap_err(),
99                UAttributesError::ParsingError(_msg)
100            ))
101        }
102    }
103}