up_rust/ustatus.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 std::error::Error;
15
16pub use crate::up_core_api::ucode::UCode;
17pub use crate::up_core_api::ustatus::UStatus;
18
19impl UStatus {
20 /// Creates a status representing a success.
21 ///
22 /// # Examples
23 ///
24 /// ```rust
25 /// use up_rust::{UCode, UStatus};
26 ///
27 /// let status = UStatus::ok();
28 /// assert_eq!(status.code.unwrap(), UCode::OK);
29 /// ```
30 pub fn ok() -> Self {
31 UStatus {
32 code: UCode::OK.into(),
33 ..Default::default()
34 }
35 }
36
37 /// Creates a status representing a failure.
38 ///
39 /// # Examples
40 ///
41 /// ```rust
42 /// use up_rust::UStatus;
43 ///
44 /// let status = UStatus::fail("something went wrong");
45 /// assert_eq!(status.message.unwrap(), "something went wrong");
46 /// ```
47 pub fn fail<M: Into<String>>(msg: M) -> Self {
48 UStatus {
49 code: UCode::UNKNOWN.into(),
50 message: Some(msg.into()),
51 ..Default::default()
52 }
53 }
54
55 /// Creates a status representing a failure.
56 ///
57 /// # Examples
58 ///
59 /// ```rust
60 /// use up_rust::{UCode, UStatus};
61 ///
62 /// let status = UStatus::fail_with_code(UCode::DATA_LOSS, "something went wrong");
63 /// assert_eq!(status.code.unwrap(), UCode::DATA_LOSS);
64 /// assert_eq!(status.message.unwrap(), "something went wrong");
65 /// ```
66 pub fn fail_with_code<M: Into<String>>(code: UCode, msg: M) -> Self {
67 UStatus {
68 code: code.into(),
69 message: Some(msg.into()),
70 ..Default::default()
71 }
72 }
73
74 /// Checks if this status represents a failure.
75 ///
76 /// # Examples
77 ///
78 /// ```rust
79 /// use up_rust::UStatus;
80 ///
81 /// let failed_status = UStatus::fail("something went wrong");
82 /// assert!(failed_status.is_failed());
83 ///
84 /// let succeeded_status = UStatus::ok();
85 /// assert!(!succeeded_status.is_failed());
86 /// ```
87 pub fn is_failed(&self) -> bool {
88 self.get_code() != UCode::OK
89 }
90
91 /// Checks if this status represents a success.
92 ///
93 /// # Examples
94 ///
95 /// ```rust
96 /// use up_rust::UStatus;
97 ///
98 /// let succeeded_status = UStatus::ok();
99 /// assert!(succeeded_status.is_success());
100 ///
101 /// let failed_status = UStatus::fail("something went wrong");
102 /// assert!(!failed_status.is_success());
103 /// ```
104 pub fn is_success(&self) -> bool {
105 self.get_code() == UCode::OK
106 }
107
108 /// Gets this status' error message.
109 ///
110 /// # Returns
111 ///
112 /// an empty string if this instance has been created without a message,
113 /// i.e. not using one of its factory functions.
114 ///
115 /// # Examples
116 ///
117 /// ```rust
118 /// use up_rust::UStatus;
119 ///
120 /// let failed_status = UStatus::fail("my error message");
121 /// assert_eq!(failed_status.get_message(), "my error message");
122 ///
123 /// let succeeded_status = UStatus::ok();
124 /// assert!(succeeded_status.get_message().is_empty());
125 /// ```
126 pub fn get_message(&self) -> String {
127 match self.message.as_ref() {
128 Some(msg) => msg.to_owned(),
129 None => String::default(),
130 }
131 }
132
133 /// Gets this status' error code.
134 ///
135 /// # Returns
136 ///
137 /// [`UCode::UNKNOWN`] if this status has been created without providing an error code.
138 ///
139 /// # Examples
140 ///
141 /// ```rust
142 /// use up_rust::{UCode, UStatus};
143 ///
144 /// let status = UStatus::fail("my error message");
145 /// assert_eq!(status.get_code(), UCode::UNKNOWN);
146 ///
147 /// let status_with_code = UStatus::fail_with_code(UCode::INTERNAL, "my error message");
148 /// assert_eq!(status_with_code.get_code(), UCode::INTERNAL);
149 /// ```
150 pub fn get_code(&self) -> UCode {
151 self.code.enum_value_or_default()
152 }
153}
154
155impl Error for UStatus {}
156
157#[cfg(test)]
158mod tests {
159 use super::*;
160
161 use protobuf::{well_known_types::any::Any, Enum, EnumOrUnknown, Message};
162
163 #[test]
164 // [utest->req~ustatus-data-model-impl~1]
165 fn test_ustatus_fail_with_code() {
166 let details = vec![Any {
167 type_url: "type.googleapis.com/google.protobuf.Timestamp".to_string(),
168 ..Default::default()
169 }];
170 UCode::VALUES.iter().for_each(|code| {
171 let mut ustatus = UStatus::fail_with_code(*code, "the message");
172 // just make sure that the field exists and we can assign a value to it
173 ustatus.details = details.clone();
174 assert!(
175 ustatus.code.enum_value().is_ok_and(|v| v == *code)
176 && ustatus.message.is_some_and(|v| v == "the message")
177 );
178 });
179 }
180
181 #[test]
182 // [utest->req~ustatus-data-model-proto~1]
183 fn test_proto_serialization() {
184 let ustatus = UStatus {
185 code: UCode::CANCELLED.into(),
186 message: Some("the message".to_string()),
187 details: vec![Any {
188 type_url: "type.googleapis.com/google.protobuf.Timestamp".to_string(),
189 ..Default::default()
190 }],
191 ..Default::default()
192 };
193 let proto = ustatus
194 .write_to_bytes()
195 .expect("failed to serialize to protobuf");
196 let deserialized_status =
197 UStatus::parse_from_bytes(proto.as_slice()).expect("failed to deserialize protobuf");
198 assert_eq!(ustatus, deserialized_status);
199 }
200
201 #[test]
202 fn test_is_failed() {
203 assert!(!UStatus {
204 ..Default::default()
205 }
206 .is_failed());
207 UCode::VALUES.iter().for_each(|code| {
208 let ustatus = UStatus {
209 code: EnumOrUnknown::from(*code),
210 ..Default::default()
211 };
212 assert_eq!(ustatus.is_failed(), *code != UCode::OK);
213 });
214 }
215
216 #[test]
217 fn test_is_success() {
218 assert!(UStatus {
219 ..Default::default()
220 }
221 .is_success());
222 UCode::VALUES.iter().for_each(|code| {
223 let ustatus = UStatus {
224 code: EnumOrUnknown::from(*code),
225 ..Default::default()
226 };
227 assert_eq!(ustatus.is_success(), *code == UCode::OK);
228 });
229 }
230}