1use crate::protocol::consts::{COORD_SEMICIRCLES_CALC, PSEUDO_EPOCH};
2use crate::protocol::get_field_offset::get_field_offset_fn;
3use crate::protocol::get_field_scale::get_field_scale_fn;
4use crate::protocol::get_field_string_value::{
5 get_field_key_from_string, get_field_string_value, FieldType,
6};
7use crate::protocol::get_field_type::get_field_type_fn;
8use crate::protocol::io::{
9 read_i16, read_i32, read_i64, read_i8, read_u16, read_u16_arr, read_u32, read_u32_arr,
10 read_u64, read_u8, read_u8_arr, skip_bytes, write_bin,
11};
12use crate::protocol::message_type::MessageType;
13use crate::protocol::value::Value;
14use crate::protocol::{
15 DefinitionMessage, FieldDefinition, MatchFieldTypeFn, MatchOffsetFn, MatchScaleFn,
16};
17use binrw::{BinResult, Endian};
18use copyless::VecHelper;
19use std::fmt::{Debug, Formatter};
20use std::io::{Read, Seek, Write};
21
22#[derive(Clone, PartialEq)]
23pub struct DataField {
24 pub field_num: u8,
25
26 pub value: Value,
27}
28
29impl Debug for DataField {
30 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
31 write!(f, " {{ t: {:?}, v: {:?} }}", &self.field_num, &self.value)
32 }
33}
34
35impl DataField {
36 pub fn new(fnum: u8, v: Value) -> Self {
37 Self {
38 field_num: fnum,
39 value: v,
40 }
41 }
42
43 #[binrw::parser(reader, endian)]
44 pub fn parse_data_field(
45 message_type: MessageType,
46 fields: &Vec<FieldDefinition>,
47 ) -> BinResult<Vec<DataField>> {
48 let mut values = Vec::with_capacity(fields.len());
49 if message_type == MessageType::None {
50 let size_sum: u8 = fields.iter().map(|field| field.size).sum();
51 println!(
52 "message_type == MessageType::None, skip_bytes: {}",
53 size_sum
54 );
55 skip_bytes(reader, size_sum);
56 } else {
57 for fd in fields.iter() {
58 let data = DataField::read_next_field(fd.size, fd.base_type.val, reader, endian);
59 values
60 .alloc()
61 .init(DataField::new(fd.definition_number, data));
62 }
63 let scales = get_field_scale_fn(message_type);
65 let offsets = get_field_offset_fn(message_type);
66 let fields = get_field_type_fn(message_type);
67 for v in &mut values {
68 DataField::process_read_value(v, fields, scales, offsets);
69 }
70 }
71 Ok(values)
73 }
74
75 #[allow(clippy::cognitive_complexity)]
76 pub fn read_next_field<R>(size: u8, base_type: u8, reader: &mut R, endian: Endian) -> Value
77 where
78 R: Read + Seek,
79 {
80 match base_type {
81 0 | 13 => {
82 if size > 1 {
84 let c = read_u8_arr(reader, size);
85 if c.is_empty() {
86 Value::None
87 } else {
88 Value::ArrU8(c)
89 }
90 } else {
91 match read_u8(reader) {
92 v => Value::U8(v),
93 }
94 }
95 }
96 1 => {
97 if size > 1 {
99 let c = read_u8_arr(reader, size);
100 if c.is_empty() {
101 Value::None
102 } else {
103 Value::ArrU8(c)
104 }
105 } else {
106 match read_i8(reader) {
107 v => Value::I8(v),
108 }
109 }
110 }
111 2 => {
112 if size > 1 {
114 let c = read_u8_arr(reader, size);
115 if c.is_empty() {
116 Value::None
117 } else {
118 Value::ArrU8(c)
119 }
120 } else {
121 match read_u8(reader) {
122 v => Value::U8(v),
123 }
124 }
125 }
126 3 => {
127 let number_of_values = size / 2;
129 if number_of_values > 1 {
130 let c = read_u8_arr(reader, size);
131 if c.is_empty() {
132 Value::None
133 } else {
134 Value::ArrU8(c)
135 }
136 } else {
137 let val = read_i16(reader, endian);
138 Value::I16(val)
139 }
140 }
141 4 => {
142 let number_of_values = size / 2;
144 if number_of_values > 1 {
145 let c = read_u16_arr(reader, endian, number_of_values);
146 if c.is_empty() {
147 Value::None
148 } else {
149 Value::ArrU16(c)
150 }
151 } else {
152 let val = read_u16(reader, endian);
153 Value::U16(val)
154 }
155 }
156 5 => {
157 let number_of_values = size / 4;
159 if number_of_values > 1 {
160 let c = read_u8_arr(reader, size);
161 if c.is_empty() {
162 Value::None
163 } else {
164 Value::ArrU8(c)
165 }
166 } else {
167 let val = read_i32(reader, endian);
168 Value::I32(val)
169 }
170 }
171 6 => {
172 let number_of_values = size / 4;
174 if number_of_values > 1 {
175 let c = read_u32_arr(reader, endian, number_of_values);
176 if c.is_empty() {
177 Value::None
178 } else {
179 Value::ArrU32(c)
180 }
181 } else {
182 let val = read_u32(reader, endian);
183 Value::U32(val)
184 }
185 }
186 7 => {
187 let mut buf: Vec<_> = Vec::with_capacity(size.into());
189 let _ = reader.take(size.into()).read_to_end(&mut buf);
190 if let Ok(string) = String::from_utf8(buf) {
191 Value::String(string)
192 } else {
193 Value::None
194 }
195 }
196 8 => {
197 let number_of_values = size / 4;
199 if number_of_values > 1 {
200 let c = read_u8_arr(reader, size);
201 if c.is_empty() {
202 Value::None
203 } else {
204 Value::ArrU8(c)
205 }
206 } else {
207 let uval = read_u32(reader, endian);
208 let val = f32::from_bits(uval);
209 Value::F32(val)
210 }
211 }
212 9 => {
213 let number_of_values = size / 8;
215 if number_of_values > 1 {
216 let c = read_u8_arr(reader, size);
217 if c.is_empty() {
218 Value::None
219 } else {
220 Value::ArrU8(c)
221 }
222 } else {
223 let uval = read_u64(reader, endian);
224 let val = f64::from_bits(uval);
225 Value::F64(val)
226 }
227 }
228 10 => {
229 if size > 1 {
231 let c = read_u8_arr(reader, size);
232 if c.is_empty() {
233 Value::None
234 } else {
235 Value::ArrU8(c)
236 }
237 } else {
238 let val = read_u8(reader);
239 Value::U8(val)
240 }
241 }
242 11 => {
243 let number_of_values = size / 2;
245 if number_of_values > 1 {
246 let c = read_u8_arr(reader, size);
247 if c.is_empty() {
248 Value::None
249 } else {
250 Value::ArrU8(c)
251 }
252 } else {
253 let val = read_u16(reader, endian);
254 Value::U16(val)
255 }
256 }
257 12 => {
258 let number_of_values = size / 4;
260 if number_of_values > 1 {
261 let c = read_u8_arr(reader, size);
262 if c.is_empty() {
263 Value::None
264 } else {
265 Value::ArrU8(c)
266 }
267 } else {
268 let val = read_u32(reader, endian);
269 Value::U32(val)
270 }
271 }
272 14 => {
273 let number_of_values = size / 8;
275 if number_of_values > 1 {
276 let c = read_u8_arr(reader, size);
277 if c.is_empty() {
278 Value::None
279 } else {
280 Value::ArrU8(c)
281 }
282 } else {
283 let val = read_i64(reader, endian);
284 Value::I64(val)
285 }
286 }
287 15 => {
288 let number_of_values = size / 8;
290 if number_of_values > 1 {
291 let c = read_u8_arr(reader, size);
292 if c.is_empty() {
293 Value::None
294 } else {
295 Value::ArrU8(c)
296 }
297 } else {
298 let val = read_u64(reader, endian);
299 Value::U64(val)
300 }
301 }
302 16 => {
303 let number_of_values = size / 8;
305 if number_of_values > 1 {
306 let c = read_u8_arr(reader, size);
307 if c.is_empty() {
308 Value::None
309 } else {
310 Value::ArrU8(c)
311 }
312 } else {
313 let val = read_u64(reader, endian);
314 Value::U64(val)
315 }
316 }
317 _ => Value::None,
318 }
319 }
320
321 #[allow(unused_must_use)]
322 fn process_read_value(
323 v: &mut DataField,
324 fields: MatchFieldTypeFn,
325 scales: MatchScaleFn,
326 offsets: MatchOffsetFn,
327 ) {
328 match fields(v.field_num as usize) {
329 FieldType::None => (),
330 FieldType::Coordinates => {
331 if let Value::I32(ref inner) = v.value {
332 let coord = *inner as f32 * COORD_SEMICIRCLES_CALC;
333 std::mem::replace(&mut v.value, Value::F32(coord));
334 }
335 }
336 FieldType::Timestamp | FieldType::DateTime => {
337 if let Value::U32(ref inner) = v.value {
338 let date = *inner + PSEUDO_EPOCH;
339 std::mem::replace(&mut v.value, Value::Time(date));
340 }
341 }
342 FieldType::LocalDateTime => {
343 if let Value::U32(ref inner) = v.value {
344 let time = *inner + PSEUDO_EPOCH - 3600;
345 std::mem::replace(&mut v.value, Value::Time(time));
346 }
347 }
348 FieldType::String | FieldType::LocaltimeIntoDay => {}
349 FieldType::Uint8
350 | FieldType::Uint8Z
351 | FieldType::Uint16
352 | FieldType::Uint16Z
353 | FieldType::Uint32
354 | FieldType::Uint32Z
355 | FieldType::Sint8 => {
356 if let Some(s) = scales(v.field_num as usize) {
357 v.value.scale(s);
358 }
359 if let Some(o) = offsets(v.field_num as usize) {
360 v.value.offset(o);
361 }
362 }
363 f => {
364 if let Value::U8(k) = v.value {
365 if let Some(t) = get_field_string_value(f, usize::from(k)) {
366 std::mem::replace(&mut v.value, Value::Enum(t));
367 }
368 } else if let Value::U16(k) = v.value {
369 if let Some(t) = get_field_string_value(f, usize::from(k)) {
370 std::mem::replace(&mut v.value, Value::Enum(t));
371 }
372 }
373 }
374 }
375 }
376
377 fn process_write_value(
378 v: &DataField,
379 fields: MatchFieldTypeFn,
380 scales: MatchScaleFn,
381 offsets: MatchOffsetFn,
382 def_field: Option<&FieldDefinition>,
383 ) -> Value {
384 match fields(v.field_num as usize) {
385 FieldType::None => Value::None,
386 FieldType::Coordinates => {
387 if let Value::F32(ref inner) = v.value {
388 let coord = *inner / COORD_SEMICIRCLES_CALC;
389 return Value::I32(coord as i32);
390 }
391 Value::None
392 }
393 FieldType::DateTime | FieldType::Timestamp => {
394 if let Value::Time(ref inner) = v.value {
395 let date = *inner - PSEUDO_EPOCH;
396 return Value::U32(date);
397 }
398 Value::None
399 }
400 FieldType::LocalDateTime => {
401 if let Value::Time(ref inner) = v.value {
402 let date = *inner - PSEUDO_EPOCH + 3600;
403 return Value::U32(date);
404 }
405 Value::None
406 }
407 FieldType::String | FieldType::LocaltimeIntoDay => v.clone().value,
408 FieldType::Uint8
409 | FieldType::Uint8Z
410 | FieldType::Uint16
411 | FieldType::Uint16Z
412 | FieldType::Uint32
413 | FieldType::Uint32Z
414 | FieldType::Sint8 => {
415 let mut v = v.clone();
416 if let Some(s) = scales(v.field_num as usize) {
417 v.value.rescale(s);
418 }
419 if let Some(o) = offsets(v.field_num as usize) {
420 v.value.reoffset(o);
421 }
422 v.value
423 }
424 f => {
425 let v = v.clone();
426 if let Value::Enum(k) = v.value {
427 if let Some(t) = get_field_key_from_string(f, k) {
428 match def_field {
429 None => {}
430 Some(def_field) => {
431 if def_field.size == 1 {
432 return Value::U8(t as u8);
433 } else if def_field.size == 2 {
434 return Value::U16(t as u16);
435 } else if def_field.size == 4 {
436 return Value::U32(t as u32);
437 } else if def_field.size == 8 {
438 return Value::U64(t as u64);
439 }
440 }
441 }
442 }
443 }
444 v.value
445 }
446 }
447 }
448
449 #[binrw::writer(writer, endian)]
450 pub fn write_data_field(
451 values: &Vec<DataField>,
452 message_type: MessageType,
453 def_msg: &DefinitionMessage,
454 ) -> BinResult<()> {
455 let scales = get_field_scale_fn(message_type);
456 let offsets = get_field_offset_fn(message_type);
457 let fields = get_field_type_fn(message_type);
458 for (i, field) in values.iter().enumerate() {
459 let def_field = def_msg.fields.get(i);
460 let value = DataField::process_write_value(field, fields, scales, offsets, def_field);
461 let _ = match &value {
462 Value::U8(v) => write_bin(writer, v, endian),
463 Value::I8(v) => write_bin(writer, v, endian),
464 Value::U16(v) => write_bin(writer, v, endian),
465 Value::I16(v) => write_bin(writer, v, endian),
466 Value::U32(v) => write_bin(writer, v, endian),
467 Value::I32(v) => write_bin(writer, v, endian),
468 Value::U64(v) => write_bin(writer, v, endian),
469 Value::I64(v) => write_bin(writer, v, endian),
470 Value::F32(v) => write_bin(writer, v, endian),
471 Value::F64(v) => write_bin(writer, v, endian),
472 Value::ArrU8(v) => write_bin(writer, v, endian),
473 Value::ArrU16(v) => write_bin(writer, v, endian),
474 Value::ArrU32(v) => write_bin(writer, v, endian),
475 Value::Time(v) => write_bin(writer, v, endian),
476 Value::String(v) => write_bin(writer, v.as_bytes(), endian),
477 Value::Enum(e) => {
478 println!(
479 "Write Enum({:?}) is unimplemented, def_field: {:?}",
480 e, def_field
481 );
482 Ok(DataField::write_none(writer, endian, def_field))
483 }
484 Value::None => Ok(DataField::write_none(writer, endian, def_field)),
485 };
486 }
487 Ok(())
488 }
489
490 fn write_none<W>(writer: &mut W, endian: Endian, def_field: Option<&FieldDefinition>)
491 where
492 W: Write + Seek,
493 {
494 match def_field {
495 None => {
496 println!("Can not write from None!");
497 }
498 Some(def_field) => {
499 let vec: Vec<u8> = vec![0x00; def_field.size as usize];
500 let _ = write_bin(writer, vec, endian);
501 }
502 }
503 }
504}