open_protocol_codec/
encode.rs1use 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}