net_core_api/api/result/
result.rs1use ion_rs;
2
3use ion_rs::IonReader;
4use ion_rs::IonType;
5use ion_rs::IonWriter;
6
7use ion_rs::ReaderBuilder;
8
9use crate::core::api::API;
10use crate::core::decoder_api::Decoder;
11use crate::core::encoder_api::Encoder;
12use crate::core::typed_api::Typed;
13
14use crate::api::envelope::envelope::Envelope;
15
16
17const DATA_TYPE: &str = "result";
18
19#[derive(Debug, PartialEq, Eq, Clone)]
20pub struct ResultDTO {
21 is_ok: bool,
22 description: Option<String>,
23 value: Option<Envelope>,
24}
25impl API for ResultDTO { }
26
27impl ResultDTO {
28
29 pub fn new(
30 is_ok: bool,
31 description: Option<&str>,
32 value: Option<Envelope>
33 ) -> Self {
34 Self {
35 is_ok,
36 description: description.map(|id| id.into()),
37 value
38 }
39 }
40
41 pub fn is_ok(&self) -> bool {
42 self.is_ok
43 }
44
45 pub fn get_description(&self) -> Result<&str, &str> {
46 self.description
47 .as_deref()
48 .map_or_else(|| Err("There is no description provided"), Ok)
49 }
50
51 pub fn into_inner(self) -> Option<Envelope> {
52 self.value
53 }
54}
55
56impl Encoder for ResultDTO {
57 fn encode(&self) -> Vec<u8> {
58 let buffer: Vec<u8> = Vec::new();
59
60 let binary_writer_builder = ion_rs::BinaryWriterBuilder::new();
61 let mut writer = binary_writer_builder.build(buffer.clone()).unwrap();
62
63 writer.step_in(IonType::Struct).expect("Error while creating an ion struct");
64
65 writer.set_field_name("is_ok");
66 writer.write_bool(self.is_ok).unwrap();
67
68 writer.set_field_name("description");
69 match &self.description {
70 Some(description) => writer.write_string(description).unwrap(),
71 None => writer.write_null(ion_rs::IonType::String).unwrap(),
72 };
73
74 writer.set_field_name("value");
75 match &self.value {
76 Some(value) => writer.write_blob(value.encode()).unwrap(),
77 None => writer.write_null(ion_rs::IonType::Blob).unwrap(),
78 };
79
80 writer.step_out().unwrap();
81 writer.flush().unwrap();
82
83 writer.output().as_slice().into()
84 }
85}
86
87impl Decoder for ResultDTO {
88 fn decode(data: &[u8]) -> Self {
89
90 let mut binary_user_reader = ReaderBuilder::new().build(data).unwrap();
91 binary_user_reader.next().unwrap();
92 binary_user_reader.step_in().unwrap();
93
94 binary_user_reader.next().unwrap();
95 let is_ok = binary_user_reader.read_bool().unwrap();
96
97 let binding;
98 binary_user_reader.next().unwrap();
99 let description = match binary_user_reader.current() {
100 ion_rs::StreamItem::Value(_) => {
101 binding = binary_user_reader.read_string().unwrap();
102 Some(binding.text())
103 },
104 ion_rs::StreamItem::Null(_) => {
105 None
106 },
107 ion_rs::StreamItem::Nothing => todo!(),
109 };
110
111 binary_user_reader.next().unwrap();
112 let value = match binary_user_reader.current() {
113 ion_rs::StreamItem::Value(_) => {
114 Some(Envelope::decode(binary_user_reader.read_blob().unwrap().as_slice()))
115 },
116 ion_rs::StreamItem::Null(_) => {
117 None
118 },
119 ion_rs::StreamItem::Nothing => todo!(),
121 };
122
123 binary_user_reader.step_out().unwrap();
124
125 ResultDTO::new(
126 is_ok,
127 description,
128 value
129 )
130 }
131}
132
133impl Typed for ResultDTO {
134 fn get_data_type() -> &'static str {
135 DATA_TYPE
136 }
137
138 fn get_type(&self) -> &str {
139 Self::get_data_type()
140 }
141}
142
143
144#[cfg(test)]
145mod tests {
146 use ion_rs::IonType;
147 use ion_rs::IonReader;
148 use ion_rs::ReaderBuilder;
149 use ion_rs::StreamItem;
150
151 use crate::core::decoder_api::Decoder;
152 use crate::core::encoder_api::Encoder;
153 use crate::core::typed_api::Typed;
154
155 use crate::api::envelope::envelope::Envelope;
156
157 use crate::api::result::result::ResultDTO;
158
159
160 #[test]
161 fn reader_correctly_read_encoded_result() {
162 const IS_OK: bool = true;
163 const DESCRIPTION: Option<&str> = Some("DESCRIPTION");
164
165 const TENANT_ID: &str = "TENANT_ID";
166 const ENVELOPE_TYPE: &str = "ENVELOPE_TYPE";
167 const ENVELOPE_DATA: &[u8] = "ENVELOPE_DATA".as_bytes();
168 let inner_value: Option<Envelope> = Some(
169 Envelope::new(
170 TENANT_ID,
171 ENVELOPE_TYPE,
172 ENVELOPE_DATA
173 )
174 );
175
176 let request_result = ResultDTO::new(
177 IS_OK,
178 DESCRIPTION,
179 inner_value.clone()
180 );
181 let mut binary_user_reader = ReaderBuilder::new().build(request_result.encode()).unwrap();
182
183 assert_eq!(StreamItem::Value(IonType::Struct), binary_user_reader.next().unwrap());
184 binary_user_reader.step_in().unwrap();
185
186 assert_eq!(StreamItem::Value(IonType::Bool), binary_user_reader.next().unwrap());
187 assert_eq!("is_ok", binary_user_reader.field_name().unwrap());
188 assert_eq!(IS_OK, binary_user_reader.read_bool().unwrap());
189
190 assert_eq!(StreamItem::Value(IonType::String), binary_user_reader.next().unwrap());
191 assert_eq!("description", binary_user_reader.field_name().unwrap());
192 assert_eq!(DESCRIPTION.unwrap(), binary_user_reader.read_string().unwrap().text());
193
194 assert_eq!(StreamItem::Value(IonType::Blob), binary_user_reader.next().unwrap());
195 assert_eq!("value", binary_user_reader.field_name().unwrap());
196 assert_eq!(inner_value.unwrap(), Envelope::decode(binary_user_reader.read_blob().unwrap().as_slice()));
197
198 binary_user_reader.step_out().unwrap();
199 }
200
201 #[test]
202 fn endec_result() {
203 const IS_OK: bool = true;
204 const DESCRIPTION: Option<&str> = Some("DESCRIPTION");
205
206 const TENANT_ID: &str = "TENANT_ID";
207 const ENVELOPE_TYPE: &str = "ENVELOPE_TYPE";
208 const ENVELOPE_DATA: &[u8] = "ENVELOPE_DATA".as_bytes();
209 let inner_value: Option<Envelope> = Some(
210 Envelope::new(
211 TENANT_ID,
212 ENVELOPE_TYPE,
213 ENVELOPE_DATA
214 )
215 );
216
217 let request_result = ResultDTO::new(
218 IS_OK,
219 DESCRIPTION,
220 inner_value.clone()
221 );
222 assert_eq!(request_result, ResultDTO::decode(&request_result.encode()));
223 }
224
225 #[test]
226 fn test_getting_data_types() {
227 const IS_OK: bool = true;
228 const DESCRIPTION: Option<&str> = Some("DESCRIPTION");
229
230 const TENANT_ID: &str = "TENANT_ID";
231 const ENVELOPE_TYPE: &str = "ENVELOPE_TYPE";
232 const ENVELOPE_DATA: &[u8] = "ENVELOPE_DATA".as_bytes();
233 let inner_value: Option<Envelope> = Some(
234 Envelope::new(
235 TENANT_ID,
236 ENVELOPE_TYPE,
237 ENVELOPE_DATA
238 )
239 );
240
241 let request_result = ResultDTO::new(
242 IS_OK,
243 DESCRIPTION,
244 inner_value.clone()
245 );
246 assert_eq!(request_result.get_type(), ResultDTO::get_data_type());
247 assert_eq!(request_result.get_type(), super::DATA_TYPE);
248 }
249}
250