1use crate::protocol::io::write_bin;
2use binrw::BinResult;
3
4macro_rules! enum_from_primitive {
5 ($typ:ident, $t:ty, $($name:ident = $value:expr),+,) => {
6 #[derive(Debug, Copy, Clone, PartialEq)]
7 #[repr($t)]
8 pub enum $typ {
9 $($name = $value),+,
10 }
11
12 impl $typ {
13 pub fn from_primitive(value: $t) -> Option<Self> {
14 match value {
15 $(x if x == $typ::$name as $t => Some($typ::$name),)+
16 _ => None,
17 }
18 }
19
20 pub fn to_primitive(self) -> $t {
21 self as $t
22 }
23 }
24 };
25}
26
27enum_from_primitive! {
29 MessageType, u16,
30 FileId = 0,
31 Capabilities = 1,
32 DeviceSettings = 2,
33 UserProfile = 3,
34 HrmProfile = 4,
35 SdmProfile = 5,
36 BikeProfile = 6,
37 ZonesTarget = 7,
38 HrZone = 8,
39 PowerZone = 9,
40 MetZone = 10,
41 Sport = 12,
42 Goal = 15,
43 Session = 18,
44 Lap = 19,
45 Record = 20,
46 Event = 21,
47 DeviceInfo = 23,
48 Workout = 26,
49 WorkoutStep = 27,
50 Schedule = 28,
51 WeightScale = 30,
52 Course = 31,
53 CoursePoint = 32,
54 Totals = 33,
55 Activity = 34,
56 Software = 35,
57 FileCapabilities = 37,
58 MesgCapabilities = 38,
59 FieldCapabilities = 39,
60 FileCreator = 49,
61 BloodPressure = 51,
62 SpeedZone = 53,
63 Monitoring = 55,
64 TrainingFile = 72,
65 Hrv = 78,
66 AntRx = 80,
67 AntTx = 81,
68 AntChannelId = 82,
69 Length = 101,
70 MonitoringInfo = 103,
71 Pad = 105,
72 SlaveDevice = 106,
73 Connectivity = 127,
74 WeatherConditions = 128,
75 WeatherAlert = 129,
76 CadenceZone = 131,
77 Hr = 132,
78 SegmentLap = 142,
79 MemoGlob = 145,
80 SegmentId = 148,
81 SegmentLeaderboardEntry = 149,
82 SegmentPoint = 150,
83 SegmentFile = 151,
84 WorkoutSession = 158,
85 WatchfaceSettings = 159,
86 GpsMetadata = 160,
87 CameraEvent = 161,
88 TimestampCorrelation = 162,
89 GyroscopeData = 164,
90 AccelerometerData = 165,
91 ThreeDSensorCalibration = 167,
92 VideoFrame = 169,
93 ObdiiData = 174,
94 NmeaSentence = 177,
95 AviationAttitude = 178,
96 Video = 184,
97 VideoTitle = 185,
98 VideoDescription = 186,
99 VideoClip = 187,
100 OhrSettings = 188,
101 ExdScreenConfiguration = 200,
102 ExdDataFieldConfiguration = 201,
103 ExdDataConceptConfiguration = 202,
104 FieldDescription = 206,
105 DeveloperDataId = 207,
106 MagnetometerData = 208,
107 BarometerData = 209,
108 OneDSensorCalibration = 210,
109 MonitoringHrData = 211,
110 TimeInZone = 216,
111 Set = 225,
112 StressLevel = 227,
113 MaxMetData = 229,
114 DiveSettings = 258,
115 DiveGas = 259,
116 DiveAlarm = 262,
117 ExerciseTitle = 264,
118 DiveSummary = 268,
119 Spo2Data = 269,
120 SleepLevel = 275,
121 Jump = 285,
122 BeatIntervals = 290,
123 RespirationRate = 297,
124 Split = 312,
125 ClimbPro = 317,
126 TankUpdate = 319,
127 TankSummary = 323,
128 SleepAssessment = 346,
129 HrvStatusSummary = 370,
130 HrvValue = 371,
131 DeviceAuxBatteryInfo = 375,
132 DiveApneaAlarm = 393,
133 MfgRangeMin = 0xFF00,
134 MfgRangeMax = 0xFFFE,
135 None = 0xFFFF,
136}
137
138#[allow(unused)]
139#[binrw::writer(writer, endian)]
140pub fn write_message_type(value: &MessageType) -> BinResult<()> {
141 write_bin(writer, value.to_primitive(), endian)?;
142 Ok(())
143}
144
145#[binrw::parser()]
146pub fn parse_message_type(value: u16) -> BinResult<MessageType> {
147 if let Some(message_type) = MessageType::from_primitive(value) {
148 return Ok(message_type);
149 } else {
150 match value {
151 0xFF00..=0xFFFE => Ok(MessageType::MfgRangeMin),
152 _ => Ok(MessageType::None),
153 }
154 }
155}