net_core_api/api/result/
result.rs

1use 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            //TODO: Return en error here in future
108            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            //TODO: Return en error here in future
120            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