1#![warn(missing_docs)]
2
3use std::{error, fmt};
4
5use crate::profile::{
6 ProfileType,
7 typedef::{FitBaseType, MesgNum},
8};
9
10pub(crate) const MESG_DEFINITION_MASK: u8 = 0b01000000;
12
13pub(crate) const MESG_NORMAL_HEADER_MASK: u8 = 0b00000000;
15
16pub(crate) const MESG_COMPRESSED_HEADER_MASK: u8 = 0b10000000;
18
19pub(crate) const MESG_HEADER_MASK: u8 = MESG_COMPRESSED_HEADER_MASK | MESG_DEFINITION_MASK;
25
26pub(crate) const LOCAL_MESG_NUM_MASK: u8 = 0b00001111;
28
29pub(crate) const COMPRESSED_LOCAL_MESG_NUM_MASK: u8 = 0b01100000;
31
32pub(crate) const COMPRESSED_TIME_MASK: u8 = 0b00011111;
34
35pub(crate) const DEV_DATA_MASK: u8 = 0b00100000;
37
38pub(crate) const COMPRESSED_BIT_SHIFT: u8 = 5;
40
41pub(crate) const FIELD_NUM_TIMESTAMP: u8 = 253;
44
45pub(crate) static DATA_TYPE: &str = ".FIT";
47
48#[derive(Debug, Clone, Copy)]
50pub enum Error {
51 ProtocolViolationDeveloperData,
53 ProtocolViolationUnsupportedBaseType(FitBaseType),
55 InvalidValue,
57}
58
59impl fmt::Display for Error {
60 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61 match *self {
62 Error::ProtocolViolationDeveloperData => {
63 write!(f, "protocol version 1.0 do not support developer data")
64 }
65 Error::ProtocolViolationUnsupportedBaseType(base_type) => {
66 write!(f, "protocol version 1.0 do not support type {}", base_type)
67 }
68 Error::InvalidValue => write!(f, "invalid proto::Value"),
69 }
70 }
71}
72
73impl error::Error for Error {}
74
75#[derive(Default, Debug)]
77pub struct FIT {
78 pub file_header: FileHeader,
80 pub messages: Vec<Message>,
82 pub crc: u16,
84}
85
86#[derive(Debug, Default, Clone, Copy)]
89pub struct FileHeader {
90 pub size: u8,
92 pub protocol_version: ProtocolVersion,
94 pub profile_version: u16,
96 pub data_size: u32,
98 pub data_type: &'static str,
100 pub crc: u16,
103}
104
105impl FileHeader {
106 pub(crate) fn marshal_append(&self, vec: &mut Vec<u8>) {
107 vec.push(self.size);
108 vec.push(self.protocol_version.0);
109 vec.extend_from_slice(&self.profile_version.to_le_bytes());
110 vec.extend_from_slice(&self.data_size.to_le_bytes());
111 vec.extend_from_slice(DATA_TYPE.as_bytes());
112 if self.size >= 14 {
113 vec.extend_from_slice(&self.crc.to_le_bytes());
114 }
115 }
116}
117
118#[derive(Debug, Default, Clone)]
120pub struct MessageDefinition {
121 pub header: u8,
123 pub reserved: u8,
125 pub arch: u8,
127 pub mesg_num: MesgNum,
129 pub field_definitions: Vec<FieldDefinition>,
131 pub developer_field_definitions: Vec<DeveloperFieldDefinition>,
133}
134
135#[derive(Debug, Default, Clone, Copy)]
137pub struct FieldDefinition {
138 pub num: u8,
140 pub size: u8,
142 pub base_type: FitBaseType,
144}
145
146#[derive(Debug, Default, Clone, Copy)]
148pub struct DeveloperFieldDefinition {
149 pub num: u8,
151 pub size: u8,
153 pub developer_data_index: u8,
155}
156
157#[derive(Default, Debug, Clone)]
159pub struct Message {
160 pub header: u8,
163 pub num: MesgNum,
165 pub fields: Vec<Field>,
167 pub developer_fields: Vec<DeveloperField>,
169}
170
171impl Message {
172 pub fn sub_field_substitution<'a>(
175 &self,
176 field_ref: &FieldReference<'a>,
177 ) -> Option<&'a SubField<'a>> {
178 for sub_field in field_ref.sub_fields {
179 for sub_field_map in sub_field.maps {
180 for field in &self.fields {
181 if field.num != sub_field_map.ref_field_num {
182 continue;
183 }
184 if field.value.cast_i64() == sub_field_map.ref_field_value {
185 return Some(sub_field);
186 }
187 }
188 }
189 }
190 None
191 }
192
193 pub(crate) fn marshal_append(&self, vec: &mut Vec<u8>, arch: u8) -> Result<(), Error> {
194 vec.push(self.header);
195 for field in &self.fields {
196 field.value.marshal_append(vec, arch)?;
197 }
198 for dev_field in &self.developer_fields {
199 dev_field.value.marshal_append(vec, arch)?;
200 }
201 Ok(())
202 }
203}
204
205#[derive(Default, Debug, Clone)]
207pub struct Field {
208 pub num: u8,
211 pub profile_type: ProfileType,
213 pub value: Value,
215 pub is_expanded: bool,
217}
218
219#[derive(Debug, Clone, Copy)]
221pub struct FieldReference<'a> {
222 pub num: u8,
225 pub name: &'a str,
228 pub base_type: FitBaseType,
231 pub profile_type: ProfileType,
234 pub array: bool,
236 pub accumulate: bool,
238 pub scale: f64,
241 pub offset: f64,
244 pub units: &'a str,
246 pub components: &'a [Component],
248 pub sub_fields: &'a [SubField<'a>],
250}
251
252#[derive(Debug, Clone)]
261pub struct DeveloperField {
262 pub num: u8,
264 pub developer_data_index: u8,
266 pub value: Value,
268}
269
270#[derive(Debug)]
273pub struct Component {
274 pub field_num: u8,
276 pub accumulate: bool,
278 pub bits: u8,
280 pub scale: f64,
282 pub offset: f64,
284}
285
286#[derive(Debug)]
288pub struct SubField<'a> {
289 pub name: &'a str,
291 pub profile_type: ProfileType,
293 pub scale: f64,
295 pub offset: f64,
297 pub units: &'a str,
299 pub maps: &'a [SubFieldMap],
301 pub components: &'a [Component],
303}
304
305#[derive(Debug)]
309pub struct SubFieldMap {
310 pub ref_field_num: u8,
312 pub ref_field_value: i64,
314}
315
316#[allow(missing_docs)]
318#[derive(Debug, Clone, Default)]
319pub enum Value {
320 #[default]
321 Invalid,
322 Int8(i8),
323 Uint8(u8),
324 Int16(i16),
325 Uint16(u16),
326 Int32(i32),
327 Uint32(u32),
328 String(String),
329 Float32(f32),
330 Float64(f64),
331 Int64(i64),
332 Uint64(u64),
333 VecInt8(Vec<i8>),
334 VecUint8(Vec<u8>),
335 VecInt16(Vec<i16>),
336 VecUint16(Vec<u16>),
337 VecInt32(Vec<i32>),
338 VecUint32(Vec<u32>),
339 VecString(Vec<String>),
340 VecFloat32(Vec<f32>),
341 VecFloat64(Vec<f64>),
342 VecInt64(Vec<i64>),
343 VecUint64(Vec<u64>),
344}
345
346impl Value {
348 pub(crate) fn unmarshal(buf: &[u8], array: bool, base_type: FitBaseType, arch: u8) -> Value {
353 match base_type {
354 FitBaseType::SINT8 => match array {
355 true => Value::VecInt8({
356 let mut vals: Vec<i8> = Vec::with_capacity(buf.len());
357 for &v in buf {
358 vals.push(v as i8);
359 }
360 vals
361 }),
362 false => Value::Int8(buf[0] as i8),
363 },
364 FitBaseType::ENUM | FitBaseType::BYTE | FitBaseType::UINT8 | FitBaseType::UINT8Z => {
365 match array {
366 true => Value::VecUint8(buf.to_vec()),
367 false => Value::Uint8(buf[0]),
368 }
369 }
370 FitBaseType::SINT16 => match array {
371 true => Value::VecInt16({
372 let mut vals: Vec<i16> = Vec::with_capacity(buf.len() / 2);
373 let mut buf = buf;
374 while buf.len() >= 2 {
375 vals.push(match arch {
376 0 => i16::from_le_bytes(buf[..2].try_into().unwrap()),
377 _ => i16::from_be_bytes(buf[..2].try_into().unwrap()),
378 });
379 buf = &buf[2..];
380 }
381 vals
382 }),
383 false => match arch {
384 0 => Value::Int16(i16::from_le_bytes(buf[..2].try_into().unwrap())),
385 _ => Value::Int16(i16::from_be_bytes(buf[..2].try_into().unwrap())),
386 },
387 },
388 FitBaseType::UINT16 | FitBaseType::UINT16Z => match array {
389 true => Value::VecUint16({
390 let mut vals: Vec<u16> = Vec::with_capacity(buf.len() / 2);
391 let mut buf = buf;
392 while buf.len() >= 2 {
393 vals.push(match arch {
394 0 => u16::from_le_bytes(buf[..2].try_into().unwrap()),
395 _ => u16::from_be_bytes(buf[..2].try_into().unwrap()),
396 });
397 buf = &buf[2..];
398 }
399 vals
400 }),
401 false => match arch {
402 0 => Value::Uint16(u16::from_le_bytes(buf[..2].try_into().unwrap())),
403 _ => Value::Uint16(u16::from_be_bytes(buf[..2].try_into().unwrap())),
404 },
405 },
406 FitBaseType::SINT32 => match array {
407 true => Value::VecInt32({
408 let mut vals: Vec<i32> = Vec::with_capacity(buf.len() / 4);
409 let mut buf = buf;
410 while buf.len() >= 4 {
411 vals.push(match arch {
412 0 => i32::from_le_bytes(buf[..4].try_into().unwrap()),
413 _ => i32::from_be_bytes(buf[..4].try_into().unwrap()),
414 });
415 buf = &buf[4..];
416 }
417 vals
418 }),
419 false => match arch {
420 0 => Value::Int32(i32::from_le_bytes(buf[..4].try_into().unwrap())),
421 _ => Value::Int32(i32::from_be_bytes(buf[..4].try_into().unwrap())),
422 },
423 },
424 FitBaseType::UINT32 | FitBaseType::UINT32Z => match array {
425 true => Value::VecUint32({
426 let mut vals: Vec<u32> = Vec::with_capacity(buf.len() / 4);
427 let mut buf = buf;
428 while buf.len() >= 4 {
429 vals.push(match arch {
430 0 => u32::from_le_bytes(buf[..4].try_into().unwrap()),
431 _ => u32::from_be_bytes(buf[..4].try_into().unwrap()),
432 });
433 buf = &buf[4..];
434 }
435 vals
436 }),
437 false => match arch {
438 0 => Value::Uint32(u32::from_le_bytes(buf[..4].try_into().unwrap())),
439 _ => Value::Uint32(u32::from_be_bytes(buf[..4].try_into().unwrap())),
440 },
441 },
442 FitBaseType::STRING => match array {
443 true => Value::String(String::from_utf8_lossy(buf).to_string()),
444 false => Value::VecString({
445 let mut vals = Vec::with_capacity(strcount(buf) as usize);
446 let mut last = 0usize;
447 for (i, &v) in buf.iter().enumerate() {
448 if v != 0 {
449 continue;
450 }
451 if last != i {
452 vals.push(String::from_utf8_lossy(&buf[last..i]).into_owned());
453 }
454 last = i + 1
455 }
456 vals
457 }),
458 },
459 FitBaseType::FLOAT32 => match array {
460 true => Value::VecFloat32({
461 let mut vals: Vec<f32> = Vec::with_capacity(buf.len() / 4);
462 let mut buf = buf;
463 while buf.len() >= 4 {
464 vals.push(match arch {
465 0 => f32::from_le_bytes(buf[..4].try_into().unwrap()),
466 _ => f32::from_be_bytes(buf[..4].try_into().unwrap()),
467 });
468 buf = &buf[4..];
469 }
470 vals
471 }),
472 false => match arch {
473 0 => Value::Float32(f32::from_le_bytes(buf[..4].try_into().unwrap())),
474 _ => Value::Float32(f32::from_be_bytes(buf[..4].try_into().unwrap())),
475 },
476 },
477 FitBaseType::FLOAT64 => match array {
478 true => Value::VecFloat64({
479 let mut vals: Vec<f64> = Vec::with_capacity(buf.len() / 8);
480 let mut buf = buf;
481 while buf.len() >= 2 {
482 vals.push(match arch {
483 0 => f64::from_le_bytes(buf[..8].try_into().unwrap()),
484 _ => f64::from_be_bytes(buf[..8].try_into().unwrap()),
485 });
486 buf = &buf[8..];
487 }
488 vals
489 }),
490 false => match arch {
491 0 => Value::Float64(f64::from_le_bytes(buf[..8].try_into().unwrap())),
492 _ => Value::Float64(f64::from_be_bytes(buf[..8].try_into().unwrap())),
493 },
494 },
495 FitBaseType::SINT64 => match array {
496 true => Value::VecInt64({
497 let mut vals: Vec<i64> = Vec::with_capacity(buf.len() / 8);
498 let mut buf = buf;
499 while buf.len() >= 8 {
500 vals.push(match arch {
501 0 => i64::from_le_bytes(buf[..8].try_into().unwrap()),
502 _ => i64::from_be_bytes(buf[..8].try_into().unwrap()),
503 });
504 buf = &buf[8..];
505 }
506 vals
507 }),
508 false => match arch {
509 0 => Value::Int64(i64::from_le_bytes(buf[..8].try_into().unwrap())),
510 _ => Value::Int64(i64::from_be_bytes(buf[..8].try_into().unwrap())),
511 },
512 },
513 FitBaseType::UINT64 | FitBaseType::UINT64Z => match array {
514 true => Value::VecUint64({
515 let mut vals: Vec<u64> = Vec::with_capacity(buf.len() / 8);
516 let mut buf = buf;
517 while buf.len() >= 8 {
518 vals.push(match arch {
519 0 => u64::from_le_bytes(buf[..8].try_into().unwrap()),
520 _ => u64::from_be_bytes(buf[..8].try_into().unwrap()),
521 });
522 buf = &buf[8..];
523 }
524 vals
525 }),
526 false => match arch {
527 0 => Value::Uint64(u64::from_le_bytes(buf[..8].try_into().unwrap())),
528 _ => Value::Uint64(u64::from_be_bytes(buf[..8].try_into().unwrap())),
529 },
530 },
531 _ => Value::Invalid,
532 }
533 }
534
535 pub(crate) fn marshal_append(&self, vec: &mut Vec<u8>, arch: u8) -> Result<(), Error> {
536 match self {
537 Value::Int8(v) => vec.push(*v as u8),
538 Value::Uint8(v) => vec.push(*v),
539 Value::Int16(v) => vec.extend_from_slice(&match arch {
540 0 => v.to_le_bytes(),
541 _ => v.to_be_bytes(),
542 }),
543 Value::Uint16(v) => vec.extend_from_slice(&match arch {
544 0 => v.to_le_bytes(),
545 _ => v.to_be_bytes(),
546 }),
547 Value::Int32(v) => vec.extend_from_slice(&match arch {
548 0 => v.to_le_bytes(),
549 _ => v.to_be_bytes(),
550 }),
551 Value::Uint32(v) => vec.extend_from_slice(&match arch {
552 0 => v.to_le_bytes(),
553 _ => v.to_be_bytes(),
554 }),
555 Value::String(v) => {
556 let b = v.as_bytes();
557 vec.extend_from_slice(b);
558 if v.is_empty() || b[b.len() - 1] != 0 {
559 vec.push(0);
560 }
561 }
562 Value::Float32(v) => vec.extend_from_slice(&match arch {
563 0 => v.to_le_bytes(),
564 _ => v.to_be_bytes(),
565 }),
566 Value::Float64(v) => vec.extend_from_slice(&match arch {
567 0 => v.to_le_bytes(),
568 _ => v.to_be_bytes(),
569 }),
570 Value::Int64(v) => vec.extend_from_slice(&match arch {
571 0 => v.to_le_bytes(),
572 _ => v.to_be_bytes(),
573 }),
574 Value::Uint64(v) => vec.extend_from_slice(&match arch {
575 0 => v.to_le_bytes(),
576 _ => v.to_be_bytes(),
577 }),
578 Value::VecInt8(v) => {
579 for &x in v {
580 vec.push(x as u8);
581 }
582 }
583 Value::VecUint8(v) => {
584 for &x in v {
585 vec.push(x);
586 }
587 }
588 Value::VecInt16(v) => match arch {
589 0 => {
590 for x in v {
591 vec.extend_from_slice(&x.to_le_bytes());
592 }
593 }
594 _ => {
595 for x in v {
596 vec.extend_from_slice(&x.to_be_bytes());
597 }
598 }
599 },
600 Value::VecUint16(v) => match arch {
601 0 => {
602 for x in v {
603 vec.extend_from_slice(&x.to_le_bytes());
604 }
605 }
606 _ => {
607 for x in v {
608 vec.extend_from_slice(&x.to_be_bytes());
609 }
610 }
611 },
612 Value::VecInt32(v) => match arch {
613 0 => {
614 for x in v {
615 vec.extend_from_slice(&x.to_le_bytes());
616 }
617 }
618 _ => {
619 for x in v {
620 vec.extend_from_slice(&x.to_be_bytes());
621 }
622 }
623 },
624 Value::VecUint32(v) => match arch {
625 0 => {
626 for x in v {
627 vec.extend_from_slice(&x.to_le_bytes());
628 }
629 }
630 _ => {
631 for x in v {
632 vec.extend_from_slice(&x.to_be_bytes());
633 }
634 }
635 },
636 Value::VecString(v) => {
637 for x in v {
638 let b = x.as_bytes();
639 vec.extend_from_slice(b);
640 if v.is_empty() || b[b.len() - 1] != 0 {
641 vec.push(0);
642 }
643 }
644 }
645 Value::VecFloat32(v) => match arch {
646 0 => {
647 for x in v {
648 vec.extend_from_slice(&x.to_le_bytes());
649 }
650 }
651 _ => {
652 for x in v {
653 vec.extend_from_slice(&x.to_be_bytes());
654 }
655 }
656 },
657 Value::VecFloat64(v) => match arch {
658 0 => {
659 for x in v {
660 vec.extend_from_slice(&x.to_le_bytes());
661 }
662 }
663 _ => {
664 for x in v {
665 vec.extend_from_slice(&x.to_be_bytes());
666 }
667 }
668 },
669 Value::VecInt64(v) => match arch {
670 0 => {
671 for x in v {
672 vec.extend_from_slice(&x.to_le_bytes());
673 }
674 }
675 _ => {
676 for x in v {
677 vec.extend_from_slice(&x.to_be_bytes());
678 }
679 }
680 },
681 Value::VecUint64(v) => match arch {
682 0 => {
683 for x in v {
684 vec.extend_from_slice(&x.to_le_bytes());
685 }
686 }
687 _ => {
688 for x in v {
689 vec.extend_from_slice(&x.to_be_bytes());
690 }
691 }
692 },
693 Value::Invalid => return Err(Error::InvalidValue),
694 };
695 Ok(())
696 }
697
698 pub(crate) fn cast_i64(&self) -> i64 {
700 match self {
701 Value::Uint8(v) => *v as i64,
702 Value::Int8(v) => *v as i64,
703 Value::Int16(v) => *v as i64,
704 Value::Uint16(v) => *v as i64,
705 Value::Int32(v) => *v as i64,
706 Value::Uint32(v) => *v as i64,
707 Value::Int64(v) => *v,
708 Value::Uint64(v) => *v as i64,
709 _ => i64::MAX,
710 }
711 }
712
713 pub fn as_i8(&self) -> i8 {
715 if let Value::Int8(v) = self {
716 return *v;
717 }
718 i8::MAX
719 }
720
721 pub fn as_u8(&self) -> u8 {
723 if let Value::Uint8(v) = self {
724 return *v;
725 }
726 u8::MAX
727 }
728
729 pub fn as_u8z(&self) -> u8 {
731 if let Value::Uint8(v) = self {
732 return *v;
733 }
734 0
735 }
736
737 pub fn as_i16(&self) -> i16 {
739 if let Value::Int16(v) = self {
740 return *v;
741 }
742 i16::MAX
743 }
744
745 pub fn as_u16(&self) -> u16 {
747 if let Value::Uint16(v) = self {
748 return *v;
749 }
750 u16::MAX
751 }
752
753 pub fn as_u16z(&self) -> u16 {
755 if let Value::Uint16(v) = self {
756 return *v;
757 }
758 0
759 }
760
761 pub fn as_i32(&self) -> i32 {
763 if let Value::Int32(v) = self {
764 return *v;
765 }
766 i32::MAX
767 }
768
769 pub fn as_u32(&self) -> u32 {
771 if let Value::Uint32(v) = self {
772 return *v;
773 }
774 u32::MAX
775 }
776
777 pub fn as_u32z(&self) -> u32 {
779 if let Value::Uint32(v) = self {
780 return *v;
781 }
782 0
783 }
784
785 pub fn as_string(&self) -> String {
787 if let Value::String(v) = self {
788 return v.clone();
789 }
790 String::new()
791 }
792
793 pub fn as_f32(&self) -> f32 {
795 if let Value::Float32(v) = self {
796 return *v;
797 }
798 f32::MAX
799 }
800
801 pub fn as_f64(&self) -> f64 {
803 if let Value::Float64(v) = self {
804 return *v;
805 }
806 f64::MAX
807 }
808
809 pub fn as_i64(&self) -> i64 {
811 if let Value::Int64(v) = self {
812 return *v;
813 }
814 i64::MAX
815 }
816
817 pub fn as_u64(&self) -> u64 {
819 if let Value::Uint64(v) = self {
820 return *v;
821 }
822 u64::MAX
823 }
824
825 pub fn as_u64z(&self) -> u64 {
827 if let Value::Uint64(v) = self {
828 return *v;
829 }
830 0
831 }
832
833 pub fn as_vec_i8(&self) -> Vec<i8> {
835 if let Value::VecInt8(v) = self {
836 return v.clone();
837 }
838 Vec::new()
839 }
840
841 pub fn as_vec_u8(&self) -> Vec<u8> {
843 if let Value::VecUint8(v) = self {
844 return v.clone();
845 }
846 Vec::new()
847 }
848
849 pub fn as_vec_i16(&self) -> Vec<i16> {
851 if let Value::VecInt16(v) = self {
852 return v.clone();
853 }
854 Vec::new()
855 }
856
857 pub fn as_vec_u16(&self) -> Vec<u16> {
859 if let Value::VecUint16(v) = self {
860 return v.clone();
861 }
862 Vec::new()
863 }
864
865 pub fn as_vec_i32(&self) -> Vec<i32> {
867 if let Value::VecInt32(v) = self {
868 return v.clone();
869 }
870 Vec::new()
871 }
872
873 pub fn as_vec_u32(&self) -> Vec<u32> {
875 if let Value::VecUint32(v) = self {
876 return v.clone();
877 }
878 Vec::new()
879 }
880
881 pub fn as_vec_string(&self) -> Vec<String> {
883 if let Value::VecString(v) = self {
884 return v.clone();
885 }
886 Vec::new()
887 }
888
889 pub fn as_vec_f32(&self) -> Vec<f32> {
891 if let Value::VecFloat32(v) = self {
892 return v.clone();
893 }
894 Vec::new()
895 }
896
897 pub fn as_vec_f64(&self) -> Vec<f64> {
899 if let Value::VecFloat64(v) = self {
900 return v.clone();
901 }
902 Vec::new()
903 }
904
905 pub fn as_vec_i64(&self) -> Vec<i64> {
907 if let Value::VecInt64(v) = self {
908 return v.clone();
909 }
910 Vec::new()
911 }
912
913 pub fn as_vec_u64(&self) -> Vec<u64> {
915 if let Value::VecUint64(v) = self {
916 return v.clone();
917 }
918 Vec::new()
919 }
920
921 pub(crate) fn is_valid(&self, base_type: FitBaseType) -> bool {
924 match self {
925 Value::Int8(v) => *v != i8::MAX,
926 Value::Uint8(v) => match base_type {
927 FitBaseType::UINT8 | FitBaseType::ENUM | FitBaseType::BYTE => *v != u8::MAX,
928 FitBaseType::UINT8Z => *v != 0,
929 _ => false,
930 },
931 Value::Int16(v) => *v != i16::MAX,
932 Value::Uint16(v) => match base_type {
933 FitBaseType::UINT16 => *v != u16::MAX,
934 FitBaseType::UINT16Z => *v != 0,
935 _ => false,
936 },
937 Value::Int32(v) => *v != i32::MAX,
938 Value::Uint32(v) => match base_type {
939 FitBaseType::UINT32 => *v != u32::MAX,
940 FitBaseType::UINT32Z => *v != 0,
941 _ => false,
942 },
943 Value::String(v) => !v.is_empty() && v.as_str() != "\x00",
944 Value::Float32(v) => f32::to_bits(*v) != u32::MAX,
945 Value::Float64(v) => f64::to_bits(*v) != u64::MAX,
946 Value::Int64(v) => *v != i64::MAX,
947 Value::Uint64(v) => match base_type {
948 FitBaseType::UINT64 => *v != u64::MAX,
949 FitBaseType::UINT64Z => *v != 0,
950 _ => false,
951 },
952 Value::VecInt8(v) => {
953 for &x in v {
954 if x != i8::MAX {
955 return true;
956 }
957 }
958 false
959 }
960 Value::VecUint8(v) => match base_type {
961 FitBaseType::UINT8 => {
962 for &x in v {
963 if x != u8::MAX {
964 return true;
965 }
966 }
967 false
968 }
969 FitBaseType::UINT8Z => {
970 for &x in v {
971 if x != u8::MIN {
972 return true;
973 }
974 }
975 false
976 }
977 _ => false,
978 },
979 Value::VecInt16(v) => {
980 for &x in v {
981 if x != i16::MAX {
982 return true;
983 }
984 }
985 false
986 }
987 Value::VecUint16(v) => match base_type {
988 FitBaseType::UINT16 => {
989 for &x in v {
990 if x != u16::MAX {
991 return true;
992 }
993 }
994 false
995 }
996 FitBaseType::UINT16Z => {
997 for &x in v {
998 if x != u16::MIN {
999 return true;
1000 }
1001 }
1002 false
1003 }
1004 _ => false,
1005 },
1006 Value::VecInt32(v) => {
1007 for &x in v {
1008 if x != i32::MAX {
1009 return true;
1010 }
1011 }
1012 false
1013 }
1014 Value::VecUint32(v) => match base_type {
1015 FitBaseType::UINT32 => {
1016 for &x in v {
1017 if x != u32::MAX {
1018 return true;
1019 }
1020 }
1021 false
1022 }
1023 FitBaseType::UINT32Z => {
1024 for &x in v {
1025 if x != u32::MIN {
1026 return true;
1027 }
1028 }
1029 false
1030 }
1031 _ => false,
1032 },
1033 Value::VecString(v) => {
1034 for x in v {
1035 if !x.is_empty() && x.as_str() != "\x00" {
1036 return true;
1037 }
1038 }
1039 false
1040 }
1041 Value::VecFloat32(v) => {
1042 for &x in v {
1043 if x.to_bits() != u32::MAX {
1044 return true;
1045 }
1046 }
1047 false
1048 }
1049 Value::VecFloat64(v) => {
1050 for &x in v {
1051 if x.to_bits() != u64::MAX {
1052 return true;
1053 }
1054 }
1055 false
1056 }
1057 Value::VecInt64(v) => {
1058 for &x in v {
1059 if x != i64::MAX {
1060 return true;
1061 }
1062 }
1063 false
1064 }
1065 Value::VecUint64(v) => match base_type {
1066 FitBaseType::UINT64 => {
1067 for &x in v {
1068 if x != u64::MAX {
1069 return true;
1070 }
1071 }
1072 false
1073 }
1074 FitBaseType::UINT64Z => {
1075 for &x in v {
1076 if x != u64::MIN {
1077 return true;
1078 }
1079 }
1080 false
1081 }
1082 _ => false,
1083 },
1084 Value::Invalid => false,
1085 }
1086 }
1087
1088 pub(crate) fn is_align(&self, base_type: FitBaseType) -> bool {
1090 match self {
1091 Value::Int8(_) => base_type == FitBaseType::SINT8,
1092 Value::Uint8(_) => {
1093 base_type == FitBaseType::ENUM
1094 || base_type == FitBaseType::UINT8
1095 || base_type == FitBaseType::UINT8Z
1096 || base_type == FitBaseType::BYTE
1097 }
1098 Value::Int16(_) => base_type == FitBaseType::SINT16,
1099 Value::Uint16(_) => {
1100 base_type == FitBaseType::UINT16 || base_type == FitBaseType::UINT16Z
1101 }
1102 Value::Int32(_) => base_type == FitBaseType::SINT32,
1103 Value::Uint32(_) => {
1104 base_type == FitBaseType::UINT32 || base_type == FitBaseType::UINT32Z
1105 }
1106 Value::String(_) => base_type == FitBaseType::STRING,
1107 Value::Float32(_) => base_type == FitBaseType::FLOAT32,
1108 Value::Float64(_) => base_type == FitBaseType::FLOAT64,
1109 Value::Int64(_) => base_type == FitBaseType::SINT64,
1110 Value::Uint64(_) => {
1111 base_type == FitBaseType::UINT64 || base_type == FitBaseType::UINT64Z
1112 }
1113 Value::VecInt8(_) => base_type == FitBaseType::SINT8,
1114 Value::VecUint8(_) => {
1115 base_type == FitBaseType::ENUM
1116 || base_type == FitBaseType::UINT8
1117 || base_type == FitBaseType::UINT8Z
1118 || base_type == FitBaseType::BYTE
1119 }
1120 Value::VecInt16(_) => base_type == FitBaseType::SINT16,
1121 Value::VecUint16(_) => {
1122 base_type == FitBaseType::UINT16 || base_type == FitBaseType::UINT16Z
1123 }
1124 Value::VecInt32(_) => base_type == FitBaseType::SINT32,
1125 Value::VecUint32(_) => {
1126 base_type == FitBaseType::UINT32 || base_type == FitBaseType::UINT32Z
1127 }
1128 Value::VecString(_) => base_type == FitBaseType::STRING,
1129 Value::VecFloat32(_) => base_type == FitBaseType::FLOAT32,
1130 Value::VecFloat64(_) => base_type == FitBaseType::FLOAT64,
1131 Value::VecInt64(_) => base_type == FitBaseType::SINT64,
1132 Value::VecUint64(_) => {
1133 base_type == FitBaseType::UINT64 || base_type == FitBaseType::UINT64Z
1134 }
1135 _ => false,
1136 }
1137 }
1138
1139 pub(crate) fn size(&self) -> usize {
1142 match self {
1143 Value::Int8(_) | Value::Uint8(_) => 1,
1144 Value::Int16(_) | Value::Uint16(_) => 2,
1145 Value::Int32(_) | Value::Uint32(_) | Value::Float32(_) => 4,
1146 Value::Int64(_) | Value::Uint64(_) | Value::Float64(_) => 8,
1147 Value::String(v) => {
1148 let n = v.len();
1149 if n == 0 || v.as_bytes()[n - 1] != 0 {
1150 return n + 1;
1151 }
1152 n
1153 }
1154 Value::VecInt8(v) => v.len(),
1155 Value::VecUint8(v) => v.len(),
1156 Value::VecInt16(v) => v.len() * 2,
1157 Value::VecUint16(v) => v.len() * 2,
1158 Value::VecInt32(v) => v.len() * 4,
1159 Value::VecUint32(v) => v.len() * 4,
1160 Value::VecFloat32(v) => v.len() * 4,
1161 Value::VecFloat64(v) => v.len() * 8,
1162 Value::VecInt64(v) => v.len() * 8,
1163 Value::VecUint64(v) => v.len() * 8,
1164 Value::VecString(v) => {
1165 let mut size = 0usize;
1166 for x in v {
1167 let mut n = x.len();
1168 if n == 0 || x.as_bytes()[n - 1] != 0 {
1169 n += 1;
1170 }
1171 size += n;
1172 }
1173 size
1174 }
1175 Value::Invalid => 0,
1176 }
1177 }
1178}
1179
1180#[derive(Default, Debug, Clone, Copy, PartialEq)]
1182pub struct ProtocolVersion(pub u8);
1183
1184#[allow(missing_docs)]
1185impl ProtocolVersion {
1186 pub const V1: ProtocolVersion = ProtocolVersion(1 << 4);
1187 pub const V2: ProtocolVersion = ProtocolVersion(2 << 4);
1188
1189 pub fn major(self) -> u8 {
1191 self.0 >> 4
1192 }
1193
1194 pub fn minor(self) -> u8 {
1196 self.0 | ((1 << 4) - 1)
1197 }
1198}
1199
1200pub(crate) fn validate_message(
1202 mesg: &Message,
1203 protocol_version: ProtocolVersion,
1204) -> Result<(), Error> {
1205 if protocol_version == ProtocolVersion::V1 {
1206 if !mesg.developer_fields.is_empty() {
1207 return Err(Error::ProtocolViolationDeveloperData);
1208 }
1209 for field in &mesg.fields {
1210 if field.profile_type.base_type().0 & FitBaseType::NUM_MASK
1211 > FitBaseType::BYTE.0 & FitBaseType::NUM_MASK
1212 {
1213 return Err(Error::ProtocolViolationUnsupportedBaseType(
1214 field.profile_type.base_type(),
1215 ));
1216 }
1217 }
1218 }
1219 Ok(())
1220}
1221
1222pub(crate) fn strcount(s: &[u8]) -> u8 {
1224 let mut last = 0usize;
1225 let mut size = 0u8;
1226 for (i, &v) in s.iter().enumerate() {
1227 if v != 0 {
1228 continue;
1229 }
1230 if last != i {
1231 size += 1
1232 }
1233 last = i + 1
1234 }
1235 if size == 0 && !s.is_empty() {
1236 return 1; }
1238 size
1239}
1240
1241#[cfg(test)]
1242mod tests {
1243 use crate::{
1244 profile::typedef::FitBaseType,
1245 proto::{Value, strcount},
1246 };
1247
1248 #[test]
1249 fn test_strcount() {
1250 #[derive(Default, Clone, Copy)]
1251 struct Case {
1252 input: &'static str,
1253 expected: u8,
1254 }
1255
1256 let tt = [
1257 Case {
1258 input: "Open Water",
1259 expected: 1,
1260 },
1261 Case {
1262 input: "Open Water\x00",
1263 expected: 1,
1264 },
1265 Case {
1266 input: "Open Water\x00\x00",
1267 expected: 1,
1268 },
1269 Case {
1270 input: "Open\x00Water\x00",
1271 expected: 2,
1272 },
1273 ];
1274
1275 for (i, tc) in tt.iter().enumerate() {
1276 let v = strcount(tc.input.as_bytes());
1277 assert_eq!(v, tc.expected, "index {} input \"{}\"", i, tc.input);
1278 }
1279 }
1280
1281 #[test]
1282 fn test_value_is_valid() {
1283 struct Case {
1284 value: Value,
1285 base_type: FitBaseType,
1286 is_valid: bool,
1287 }
1288
1289 let tt = [
1290 Case {
1291 value: Value::Int8(i8::MIN),
1292 base_type: FitBaseType::SINT8,
1293 is_valid: true,
1294 },
1295 Case {
1296 value: Value::Int8(i8::MAX),
1297 base_type: FitBaseType::SINT8,
1298 is_valid: false,
1299 },
1300 Case {
1301 value: Value::Uint8(u8::MIN),
1302 base_type: FitBaseType::UINT8,
1303 is_valid: true,
1304 },
1305 Case {
1306 value: Value::Uint8(u8::MAX),
1307 base_type: FitBaseType::UINT8,
1308 is_valid: false,
1309 },
1310 Case {
1311 value: Value::Uint8(u8::MIN),
1312 base_type: FitBaseType::UINT8Z,
1313 is_valid: false,
1314 },
1315 Case {
1316 value: Value::Uint8(u8::MAX),
1317 base_type: FitBaseType::UINT8Z,
1318 is_valid: true,
1319 },
1320 Case {
1321 value: Value::Int16(i16::MIN),
1322 base_type: FitBaseType::SINT16,
1323 is_valid: true,
1324 },
1325 Case {
1326 value: Value::Int16(i16::MAX),
1327 base_type: FitBaseType::SINT16,
1328 is_valid: false,
1329 },
1330 Case {
1331 value: Value::Uint16(u16::MIN),
1332 base_type: FitBaseType::UINT16,
1333 is_valid: true,
1334 },
1335 Case {
1336 value: Value::Uint16(u16::MAX),
1337 base_type: FitBaseType::UINT16,
1338 is_valid: false,
1339 },
1340 Case {
1341 value: Value::Uint16(u16::MIN),
1342 base_type: FitBaseType::UINT16Z,
1343 is_valid: false,
1344 },
1345 Case {
1346 value: Value::Uint16(u16::MAX),
1347 base_type: FitBaseType::UINT16Z,
1348 is_valid: true,
1349 },
1350 Case {
1351 value: Value::Int32(i32::MIN),
1352 base_type: FitBaseType::SINT32,
1353 is_valid: true,
1354 },
1355 Case {
1356 value: Value::Int32(i32::MAX),
1357 base_type: FitBaseType::SINT32,
1358 is_valid: false,
1359 },
1360 Case {
1361 value: Value::Uint32(u32::MIN),
1362 base_type: FitBaseType::UINT32,
1363 is_valid: true,
1364 },
1365 Case {
1366 value: Value::Uint32(u32::MAX),
1367 base_type: FitBaseType::UINT32,
1368 is_valid: false,
1369 },
1370 Case {
1371 value: Value::Uint32(u32::MIN),
1372 base_type: FitBaseType::UINT32Z,
1373 is_valid: false,
1374 },
1375 Case {
1376 value: Value::Uint32(u32::MAX),
1377 base_type: FitBaseType::UINT32Z,
1378 is_valid: true,
1379 },
1380 Case {
1381 value: Value::Float32(f32::MIN),
1382 base_type: FitBaseType::FLOAT32,
1383 is_valid: true,
1384 },
1385 Case {
1386 value: Value::Float32(f32::from_bits(u32::MAX)),
1387 base_type: FitBaseType::FLOAT32,
1388 is_valid: false,
1389 },
1390 Case {
1391 value: Value::Float64(f64::MIN),
1392 base_type: FitBaseType::FLOAT64,
1393 is_valid: true,
1394 },
1395 Case {
1396 value: Value::Float64(f64::from_bits(u64::MAX)),
1397 base_type: FitBaseType::FLOAT64,
1398 is_valid: false,
1399 },
1400 Case {
1401 value: Value::Int64(i64::MIN),
1402 base_type: FitBaseType::SINT64,
1403 is_valid: true,
1404 },
1405 Case {
1406 value: Value::Int64(i64::MAX),
1407 base_type: FitBaseType::SINT64,
1408 is_valid: false,
1409 },
1410 Case {
1411 value: Value::Uint64(u64::MIN),
1412 base_type: FitBaseType::UINT64,
1413 is_valid: true,
1414 },
1415 Case {
1416 value: Value::Uint64(u64::MAX),
1417 base_type: FitBaseType::UINT64,
1418 is_valid: false,
1419 },
1420 Case {
1421 value: Value::Uint64(u64::MIN),
1422 base_type: FitBaseType::UINT64Z,
1423 is_valid: false,
1424 },
1425 Case {
1426 value: Value::Uint64(u64::MAX),
1427 base_type: FitBaseType::UINT64Z,
1428 is_valid: true,
1429 },
1430 Case {
1431 value: Value::String("rustyfit".to_string()),
1432 base_type: FitBaseType::STRING,
1433 is_valid: true,
1434 },
1435 Case {
1436 value: Value::String("".to_string()),
1437 base_type: FitBaseType::STRING,
1438 is_valid: false,
1439 },
1440 Case {
1441 value: Value::String("\x00".to_string()),
1442 base_type: FitBaseType::STRING,
1443 is_valid: false,
1444 },
1445 Case {
1446 value: Value::VecInt8(vec![0i8, 1i8]),
1447 base_type: FitBaseType::SINT8,
1448 is_valid: true,
1449 },
1450 Case {
1451 value: Value::VecInt8(vec![i8::MAX, i8::MAX]),
1452 base_type: FitBaseType::SINT8,
1453 is_valid: false,
1454 },
1455 Case {
1456 value: Value::VecUint8(vec![0u8, 1u8]),
1457 base_type: FitBaseType::UINT8,
1458 is_valid: true,
1459 },
1460 Case {
1461 value: Value::VecUint8(vec![0u8, 1u8]),
1462 base_type: FitBaseType::UINT8Z,
1463 is_valid: true,
1464 },
1465 Case {
1466 value: Value::VecUint8(vec![u8::MAX, u8::MAX]),
1467 base_type: FitBaseType::UINT8,
1468 is_valid: false,
1469 },
1470 Case {
1471 value: Value::VecUint8(vec![u8::MIN, u8::MIN]),
1472 base_type: FitBaseType::UINT8Z,
1473 is_valid: false,
1474 },
1475 Case {
1476 value: Value::VecInt16(vec![0i16, 1i16]),
1477 base_type: FitBaseType::SINT16,
1478 is_valid: true,
1479 },
1480 Case {
1481 value: Value::VecInt16(vec![i16::MAX, i16::MAX]),
1482 base_type: FitBaseType::SINT16,
1483 is_valid: false,
1484 },
1485 Case {
1486 value: Value::VecUint16(vec![0u16, 1u16]),
1487 base_type: FitBaseType::UINT16,
1488 is_valid: true,
1489 },
1490 Case {
1491 value: Value::VecUint16(vec![0u16, 1u16]),
1492 base_type: FitBaseType::UINT16Z,
1493 is_valid: true,
1494 },
1495 Case {
1496 value: Value::VecUint16(vec![u16::MAX, u16::MAX]),
1497 base_type: FitBaseType::UINT16,
1498 is_valid: false,
1499 },
1500 Case {
1501 value: Value::VecUint16(vec![u16::MIN, u16::MIN]),
1502 base_type: FitBaseType::UINT16Z,
1503 is_valid: false,
1504 },
1505 Case {
1506 value: Value::VecInt32(vec![0i32, 1i32]),
1507 base_type: FitBaseType::SINT32,
1508 is_valid: true,
1509 },
1510 Case {
1511 value: Value::VecInt32(vec![i32::MAX, i32::MAX]),
1512 base_type: FitBaseType::SINT32,
1513 is_valid: false,
1514 },
1515 Case {
1516 value: Value::VecUint32(vec![0u32, 1u32]),
1517 base_type: FitBaseType::UINT32,
1518 is_valid: true,
1519 },
1520 Case {
1521 value: Value::VecUint32(vec![0u32, 1u32]),
1522 base_type: FitBaseType::UINT32Z,
1523 is_valid: true,
1524 },
1525 Case {
1526 value: Value::VecUint32(vec![u32::MAX, u32::MAX]),
1527 base_type: FitBaseType::UINT32,
1528 is_valid: false,
1529 },
1530 Case {
1531 value: Value::VecUint32(vec![u32::MIN, u32::MIN]),
1532 base_type: FitBaseType::UINT32Z,
1533 is_valid: false,
1534 },
1535 Case {
1536 value: Value::VecFloat32(vec![0f32, 1f32]),
1537 base_type: FitBaseType::FLOAT32,
1538 is_valid: true,
1539 },
1540 Case {
1541 value: Value::VecFloat32(vec![f32::from_bits(u32::MAX), f32::from_bits(u32::MAX)]),
1542 base_type: FitBaseType::FLOAT32,
1543 is_valid: false,
1544 },
1545 Case {
1546 value: Value::VecFloat64(vec![0f64, 1f64]),
1547 base_type: FitBaseType::FLOAT64,
1548 is_valid: true,
1549 },
1550 Case {
1551 value: Value::VecFloat64(vec![f64::from_bits(u64::MAX), f64::from_bits(u64::MAX)]),
1552 base_type: FitBaseType::FLOAT64,
1553 is_valid: false,
1554 },
1555 Case {
1556 value: Value::VecInt64(vec![0i64, 1i64]),
1557 base_type: FitBaseType::SINT64,
1558 is_valid: true,
1559 },
1560 Case {
1561 value: Value::VecInt64(vec![i64::MAX, i64::MAX]),
1562 base_type: FitBaseType::SINT64,
1563 is_valid: false,
1564 },
1565 Case {
1566 value: Value::VecUint64(vec![0u64, 1u64]),
1567 base_type: FitBaseType::UINT64,
1568 is_valid: true,
1569 },
1570 Case {
1571 value: Value::VecUint64(vec![0u64, 1u64]),
1572 base_type: FitBaseType::UINT64Z,
1573 is_valid: true,
1574 },
1575 Case {
1576 value: Value::VecUint64(vec![u64::MAX, u64::MAX]),
1577 base_type: FitBaseType::UINT64,
1578 is_valid: false,
1579 },
1580 Case {
1581 value: Value::VecUint64(vec![u64::MIN, u64::MIN]),
1582 base_type: FitBaseType::UINT64Z,
1583 is_valid: false,
1584 },
1585 Case {
1586 value: Value::VecString(vec!["rustyfit".to_string(), "rustyfit".to_string()]),
1587 base_type: FitBaseType::STRING,
1588 is_valid: true,
1589 },
1590 Case {
1591 value: Value::VecString(vec!["\x00".to_string(), "\x00".to_string()]),
1592 base_type: FitBaseType::STRING,
1593 is_valid: false,
1594 },
1595 ];
1596
1597 for (i, tc) in tt.iter().enumerate() {
1598 let is_valid = tc.value.is_valid(tc.base_type);
1599 assert_eq!(
1600 tc.is_valid, is_valid,
1601 "{}: {:?} | {}",
1602 i, tc.value, tc.base_type,
1603 );
1604 }
1605 }
1606}