1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use ion_rs;

use ion_rs::IonReader;
use ion_rs::IonType;
use ion_rs::IonWriter;

use ion_rs::ReaderBuilder;

use net_core_api::core::api::API;
use net_core_api::core::encoder_api::Encoder;
use net_core_api::core::decoder_api::Decoder;
use net_core_api::core::typed_api::Typed;


const DATA_TYPE: &str = "data_packet";

#[derive(Debug, PartialEq, Eq)]
pub struct DataPacketDTO {
    data: Vec<u8>
}
impl API for DataPacketDTO { }

impl DataPacketDTO {
    pub fn new (data: &[u8]) -> Self {
        DataPacketDTO {
            data: data.into()
        }
    }

    pub fn get_data(&self) -> &[u8] {
        &self.data
    }
}

impl Encoder for DataPacketDTO {
    fn encode(&self) -> Vec<u8> {
        let buffer: Vec<u8> = Vec::new();

        let binary_writer_builder = ion_rs::BinaryWriterBuilder::new();
        
        let mut writer = binary_writer_builder.build(buffer.clone()).unwrap();
        
        writer.step_in(IonType::Struct).expect("Error while creating an ion struct");

        writer.set_field_name("data");
        writer.write_blob(&self.data).unwrap();

        writer.step_out().unwrap();
        writer.flush().unwrap();

        writer.output().as_slice().into()
    }
}

impl Decoder for DataPacketDTO {
    fn decode(data: &[u8]) -> Self {

        let mut binary_user_reader = ReaderBuilder::new().build(data).unwrap();
        binary_user_reader.next().unwrap();
        binary_user_reader.step_in().unwrap();

        binary_user_reader.next().unwrap();
        let binding = binary_user_reader.read_blob().unwrap();
        let data = binding.as_slice();

        DataPacketDTO::new(
            data
        )
    }
}

impl Typed for DataPacketDTO {
    fn get_data_type() -> &'static str {
        DATA_TYPE
    }

    fn get_type(&self) -> &str {
        Self::get_data_type()
    }
}


#[cfg(test)]
mod tests {
    use ion_rs::IonType;
    use ion_rs::IonReader;
    use ion_rs::ReaderBuilder;
    use ion_rs::StreamItem;

    use net_core_api::core::decoder_api::Decoder;
    use net_core_api::core::encoder_api::Encoder;
    use net_core_api::core::typed_api::Typed;


    use crate::api::data_packet::DataPacketDTO;

    #[test]
    fn reader_correctly_read_encoded_data_packet() {
        const DATA: &[u8] = "SOME_RAW_PCAP".as_bytes();
        let data_packet: DataPacketDTO = DataPacketDTO::new(DATA);
        let mut binary_user_reader = ReaderBuilder::new().build(data_packet.encode()).unwrap();

        assert_eq!(StreamItem::Value(IonType::Struct), binary_user_reader.next().unwrap());
        binary_user_reader.step_in().unwrap();

        assert_eq!(StreamItem::Value(IonType::Blob), binary_user_reader.next().unwrap());
        assert_eq!("data", binary_user_reader.field_name().unwrap());
        assert_eq!(DATA, binary_user_reader.read_blob().unwrap().as_slice());
    }

    #[test]
    fn endec_data_packet() {
        const DATA: &[u8] = "SOME_RAW_PCAP".as_bytes();
        let data_packet: DataPacketDTO = DataPacketDTO::new(DATA);
        assert_eq!(data_packet, DataPacketDTO::decode(&data_packet.encode()));
    }

    #[test]
    fn test_getting_data_types() {
        const DATA: &[u8] = "SOME_RAW_PCAP".as_bytes();
        let data_packet: DataPacketDTO = DataPacketDTO::new(DATA);
        assert_eq!(data_packet.get_type(), DataPacketDTO::get_data_type());
        assert_eq!(data_packet.get_type(), super::DATA_TYPE);
    }
}