open_protocol_codec/
encode.rs

1use chrono::{DateTime, Datelike, Local, Timelike};
2use thiserror;
3use crate::{FieldNumber, FIELD_NUMBER_LEN};
4
5pub trait Encode {
6    fn encode(&self, encoder: &mut Encoder) -> Result<()>;
7
8    fn encode_sized(&self , encoder: &mut Encoder, _size: usize) -> Result<()> {
9        self.encode(encoder)
10    }
11}
12
13#[derive(Debug, Eq, PartialEq, thiserror::Error)]
14pub enum Error {
15    #[error("This feature is not implemented yet")]
16    NotImplemented,
17    #[error("Cannot write this as {0} characters")]
18    InvalidSize(usize),
19    #[error("Unsized encode is not allowed for this type.")]
20    UnsizedEncodeNotAllowed,
21    #[error("Character is a non-ASCII character, which is required.")]
22    NonAsciiCharacter(char)
23}
24
25pub type Result<T> = std::result::Result<T, Error>;
26
27
28#[derive(Debug, Clone)]
29pub struct Encoder {
30    bytes: Vec<u8>,
31}
32
33impl Encoder {
34    pub fn new() -> Self {
35        Self { bytes: vec![] }
36    }
37
38    pub fn write_byte(&mut self, byte: &u8) -> Result<()> {
39        self.bytes.push(*byte);
40        Ok(())
41    }
42
43    pub fn write_bytes(&mut self, bytes: &[u8]) -> Result<()> {
44        for byte_char in bytes {
45            self.write_byte(byte_char)?;
46        }
47        Ok(())
48    }
49
50    pub fn write_sized_field<T: Encode>(&mut self, item: &T, size: usize) -> Result<()> {
51        item.encode_sized(self, size)?;
52        Ok(())
53    }
54
55    pub fn write_numbered_sized_field<T: Encode>(&mut self, item: &T, number: FieldNumber, size: usize) -> Result<()> {
56        number.encode_sized(self, FIELD_NUMBER_LEN)?;
57        item.encode_sized(self, size)?;
58        Ok(())
59    }
60
61    pub fn write_numbered_sized_optional_field<T: Encode>(&mut self, item: &Option<T>, number: FieldNumber, size: usize) -> Result<()> {
62        match item {
63            Some(content) => {
64                number.encode_sized(self, FIELD_NUMBER_LEN)?;
65                content.encode_sized(self, size)?;
66            },
67            None => {},
68        };
69        Ok(())
70    }
71
72    pub fn write_numbered_field<T: Encode>(&mut self, item: &T, number: FieldNumber) -> Result<()> {
73        number.encode_sized(self, FIELD_NUMBER_LEN)?;
74        item.encode(self)?;
75        Ok(())
76    }
77
78    pub fn write_numbered_optional_field<T: Encode>(&mut self, item: &Option<T>, number: FieldNumber) -> Result<()> {
79        match item {
80            Some(content) => {
81                number.encode_sized(self, FIELD_NUMBER_LEN)?;
82                content.encode(self)?;
83            },
84            None => {},
85        }
86        Ok(())
87    }
88
89    pub fn write_sized_list<T: Encode>(&mut self, list: &Vec<T>, item_size: usize, amount: usize) -> Result<()> {
90        for index in 0..amount {
91            let item = &list[index];
92            self.write_sized_field(item, item_size)?;
93        }
94
95        Ok(())
96    }
97
98    pub fn write_list<T: Encode>(&mut self, list: &Vec<T>, amount: usize) -> Result<()> {
99        for index in 0..amount {
100            let item = &list[index];
101            item.encode(self)?
102        }
103
104        Ok(())
105    }
106
107    pub fn to_string(&self) -> String {
108        let bytes = self.bytes.clone();
109        String::from_utf8(bytes).unwrap()
110    }
111
112    pub fn len(&self) -> usize {
113        self.bytes.len()
114    }
115
116    pub fn as_slice(&self) -> &[u8] {
117        self.bytes.as_slice()
118    }
119
120    pub fn append(&mut self, bytes: &[u8]) {
121        self.bytes.extend_from_slice(bytes);
122    }
123}
124
125pub fn encode<T: Encode>(item: &T) -> Result<String> {
126    let mut encoder = Encoder::new();
127    item.encode(&mut encoder)?;
128    Ok(encoder.to_string())
129}
130
131impl Encode for u8 {
132    fn encode(&self, _: &mut Encoder) -> Result<()> {
133        Err(Error::UnsizedEncodeNotAllowed)
134    }
135
136    fn encode_sized(&self, encoder: &mut Encoder, size: usize) -> Result<()> {
137        for i in (0..size).rev() {
138            let digit_byte = (self / 10u8.pow(i as u32)) % 10 + b'0';
139            encoder.write_byte(&digit_byte)?;
140        }
141        Ok(())
142    }
143}
144
145impl Encode for u16 {
146    fn encode(&self, _: &mut Encoder) -> Result<()> {
147        Err(Error::UnsizedEncodeNotAllowed)
148    }
149
150    fn encode_sized(&self, encoder: &mut Encoder, size: usize) -> Result<()> {
151        for i in (0..size).rev() {
152            let digit_byte = ((self / 10u16.pow(i as u32)) % 10) as u8 + b'0';
153            encoder.write_byte(&digit_byte)?;
154        }
155
156        Ok(())
157    }
158}
159
160impl Encode for u32 {
161    fn encode(&self, _: &mut Encoder) -> Result<()> {
162        Err(Error::UnsizedEncodeNotAllowed)
163    }
164
165    fn encode_sized(&self, encoder: &mut Encoder, size: usize) -> Result<()> {
166        for i in (0..size).rev() {
167            let digit_byte = ((self / 10u32.pow(i as u32)) % 10) as u8 + b'0';
168            encoder.write_byte(&digit_byte)?;
169        }
170
171        Ok(())
172    }
173}
174
175impl Encode for u64 {
176    fn encode(&self, _: &mut Encoder) -> Result<()> {
177        Err(Error::UnsizedEncodeNotAllowed)
178    }
179
180    fn encode_sized(&self, encoder: &mut Encoder, size: usize) -> Result<()> {
181        for i in (0..size).rev() {
182            let digit_byte = ((self / 10u64.pow(i as u32)) % 10) as u8 + b'0';
183            encoder.write_byte(&digit_byte)?;
184        }
185
186        Ok(())
187    }
188}
189
190impl Encode for char {
191    fn encode(&self, encoder: &mut Encoder) -> Result<()> {
192        if !self.is_ascii() {
193            return Err(Error::NonAsciiCharacter(*self));
194        }
195
196        encoder.write_byte(&u8::try_from(u32::from(*self)).unwrap())?;
197        Ok(())
198    }
199}
200
201impl Encode for String {
202    fn encode(&self, encoder: &mut Encoder) -> Result<()> {
203        for char in self.chars() {
204            char.encode(encoder)?;
205        }
206
207        Ok(())
208    }
209
210    fn encode_sized(&self, encoder: &mut Encoder, size: usize) -> Result<()> {
211        if self.len() > size {
212            return Err(Error::InvalidSize(size));
213        }
214
215        for char in self.chars() {
216            char.encode(encoder)?;
217        }
218
219        for _ in 0..(size - self.len()) {
220            ' '.encode(encoder)?;
221        }
222
223        Ok(())
224    }
225}
226
227impl Encode for bool {
228    fn encode(&self, encoder: &mut Encoder) -> Result<()> {
229        match *self {
230            true => '1'.encode(encoder),
231            false => '0'.encode(encoder),
232        }
233    }
234
235    fn encode_sized(&self, encoder: &mut Encoder, size: usize) -> Result<()> {
236        if size != 1 {
237            return Err(Error::InvalidSize(size));
238        }
239
240        self.encode(encoder)
241    }
242}
243
244impl<T: Encode> Encode for Option<T> {
245    fn encode(&self, _: &mut Encoder) -> Result<()> {
246        Err(Error::UnsizedEncodeNotAllowed)
247    }
248
249    fn encode_sized(&self, encoder: &mut Encoder, size: usize) -> Result<()> {
250        match self {
251            None => {
252                for char in std::iter::repeat(' ').take(size) {
253                    char.encode(encoder)?;
254                }
255            },
256            Some(item) => {
257                item.encode_sized(encoder, size)?
258            },
259        };
260
261        Ok(())
262    }
263}
264
265impl Encode for DateTime<Local> {
266    fn encode(&self, encoder: &mut Encoder) -> Result<()> {
267        (self.year() as u32).encode_sized(encoder, 4)?;
268        '-'.encode(encoder)?;
269        self.month().encode_sized(encoder, 2)?;
270        '-'.encode(encoder)?;
271        self.day().encode_sized(encoder, 2)?;
272        ':'.encode(encoder)?;
273        self.hour().encode_sized(encoder, 2)?;
274        ':'.encode(encoder)?;
275        self.minute().encode_sized(encoder, 2)?;
276        ':'.encode(encoder)?;
277        self.second().encode_sized(encoder, 2)?;
278
279        Ok(())
280    }
281}