Skip to content

Commit e9ec14c

Browse files
pv42joaoantoniocardosoJörn Roth
authored
Use deprecation tags in message definition for code generation (#389)
* forward deprecated tag during codegen * allow deprecated in example/test * add deprecated snapshot test * fix MSRV issue Co-authored-by: João Antônio Cardoso <joao.maker@gmail.com> * expect instead of allow * use emit_deprecation on enum entries * add inline(always) on most emit functions --------- Co-authored-by: João Antônio Cardoso <joao.maker@gmail.com> Co-authored-by: Jörn Roth <joern.roth@s2016.tu-chemnitz.de>
1 parent 85f6788 commit e9ec14c

9 files changed

Lines changed: 450 additions & 5 deletions

mavlink-bindgen/src/parser.rs

Lines changed: 181 additions & 5 deletions
Large diffs are not rendered by default.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<mavlink>
2+
<enums>
3+
<enum name="MAV_FRAME">
4+
<!-- ... -->
5+
<entry value="5" name="MAV_FRAME_GLOBAL_INT">
6+
<deprecated since="2024-03" replaced_by="MAV_FRAME_GLOBAL">Use MAV_FRAME_GLOBAL in COMMAND_INT (and elsewhere) as a synonymous replacement.</deprecated>
7+
<description>Global (WGS84) coordinate frame (scaled) + altitude relative to mean sea level (MSL).</description>
8+
</entry>
9+
<!-- ... -->
10+
</enum>
11+
<enum name="MAV_MOUNT_MODE">
12+
<deprecated since="2020-01" replaced_by="GIMBAL_MANAGER_FLAGS"/>
13+
<description>Enumeration of possible mount operation modes. This message is used by obsolete/deprecated gimbal messages.</description>
14+
<entry value="0" name="MAV_MOUNT_MODE_RETRACT">
15+
<description>Load and keep safe position (Roll,Pitch,Yaw) from permanent memory and stop stabilization</description>
16+
</entry>
17+
<!-- ... -->
18+
</enum>
19+
</enums>
20+
<messages>
21+
<message id="4" name="PING">
22+
<deprecated since="2011-08" replaced_by="TIMESYNC">To be removed / merged with TIMESYNC</deprecated>
23+
<description>A ping message either requesting or responding to a ping. This allows to measure the system latencies, including serial port, radio modem and UDP connections. The ping microservice is documented at https://mavlink.io/en/services/ping.html</description>
24+
<field type="uint64_t" name="time_usec" units="us">Timestamp (UNIX Epoch time or time since system boot). The receiving end can infer timestamp format (since 1.1.1970 or since system boot) by checking for the magnitude of the number.</field>
25+
<field type="uint32_t" name="seq">PING sequence</field>
26+
<field type="uint8_t" name="target_system">0: request ping from all receiving systems. If greater than 0: message is a ping response and number is the system id of the requesting system</field>
27+
<field type="uint8_t" name="target_component">0: request ping from all receiving components. If greater than 0: message is a ping response and number is the component id of the requesting component.</field>
28+
</message>
29+
</messages>
30+
</mavlink>

mavlink-bindgen/tests/e2e_snapshots.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,8 @@ fn snapshot_heartbeat() {
3636
fn snapshot_parameters() {
3737
run_snapshot("parameters.xml");
3838
}
39+
40+
#[test]
41+
fn snapshot_deprecated() {
42+
run_snapshot("deprecated.xml");
43+
}
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
---
2+
source: mavlink-bindgen/tests/e2e_snapshots.rs
3+
assertion_line: 26
4+
expression: contents
5+
---
6+
#![doc = "MAVLink deprecated dialect."]
7+
#![doc = ""]
8+
#![doc = "This file was automatically generated, do not edit."]
9+
#![allow(deprecated)]
10+
#[cfg(feature = "arbitrary")]
11+
use arbitrary::Arbitrary;
12+
#[allow(unused_imports)]
13+
use bitflags::bitflags;
14+
use mavlink_core::{bytes::Bytes, bytes_mut::BytesMut, MavlinkVersion, Message, MessageData};
15+
#[allow(unused_imports)]
16+
use num_derive::FromPrimitive;
17+
#[allow(unused_imports)]
18+
use num_derive::ToPrimitive;
19+
#[allow(unused_imports)]
20+
use num_traits::FromPrimitive;
21+
#[allow(unused_imports)]
22+
use num_traits::ToPrimitive;
23+
#[cfg(feature = "serde")]
24+
use serde::{Deserialize, Serialize};
25+
#[derive(Debug, Copy, Clone, PartialEq, FromPrimitive, ToPrimitive)]
26+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
27+
#[cfg_attr(feature = "serde", serde(tag = "type"))]
28+
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
29+
#[repr(u32)]
30+
pub enum MavFrame {
31+
#[deprecated = "Use MAV_FRAME_GLOBAL in COMMAND_INT (and elsewhere) as a synonymous replacement. See `MAV_FRAME_GLOBAL` (Deprecated since 2024-03)"]
32+
MAV_FRAME_GLOBAL_INT = 5,
33+
}
34+
impl MavFrame {
35+
pub const DEFAULT: Self = Self::MAV_FRAME_GLOBAL_INT;
36+
}
37+
impl Default for MavFrame {
38+
fn default() -> Self {
39+
Self::DEFAULT
40+
}
41+
}
42+
#[derive(Debug, Copy, Clone, PartialEq, FromPrimitive, ToPrimitive)]
43+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
44+
#[cfg_attr(feature = "serde", serde(tag = "type"))]
45+
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
46+
#[repr(u32)]
47+
#[deprecated = " See `GIMBAL_MANAGER_FLAGS` (Deprecated since 2020-01)"]
48+
pub enum MavMountMode {
49+
MAV_MOUNT_MODE_RETRACT = 0,
50+
}
51+
impl MavMountMode {
52+
pub const DEFAULT: Self = Self::MAV_MOUNT_MODE_RETRACT;
53+
}
54+
impl Default for MavMountMode {
55+
fn default() -> Self {
56+
Self::DEFAULT
57+
}
58+
}
59+
#[deprecated = "To be removed / merged with TIMESYNC. See `TIMESYNC` (Deprecated since 2011-08)"]
60+
#[derive(Debug, Clone, PartialEq)]
61+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
62+
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
63+
pub struct PING_DATA {
64+
pub time_usec: u64,
65+
pub seq: u32,
66+
pub target_system: u8,
67+
pub target_component: u8,
68+
}
69+
impl PING_DATA {
70+
pub const ENCODED_LEN: usize = 14usize;
71+
pub const DEFAULT: Self = Self {
72+
time_usec: 0_u64,
73+
seq: 0_u32,
74+
target_system: 0_u8,
75+
target_component: 0_u8,
76+
};
77+
#[cfg(feature = "arbitrary")]
78+
pub fn random<R: rand::RngCore>(rng: &mut R) -> Self {
79+
use arbitrary::{Arbitrary, Unstructured};
80+
let mut buf = [0u8; 1024];
81+
rng.fill_bytes(&mut buf);
82+
let mut unstructured = Unstructured::new(&buf);
83+
Self::arbitrary(&mut unstructured).unwrap_or_default()
84+
}
85+
}
86+
impl Default for PING_DATA {
87+
fn default() -> Self {
88+
Self::DEFAULT.clone()
89+
}
90+
}
91+
impl MessageData for PING_DATA {
92+
type Message = MavMessage;
93+
const ID: u32 = 4u32;
94+
const NAME: &'static str = "PING";
95+
const EXTRA_CRC: u8 = 237u8;
96+
const ENCODED_LEN: usize = 14usize;
97+
fn deser(
98+
_version: MavlinkVersion,
99+
__input: &[u8],
100+
) -> Result<Self, ::mavlink_core::error::ParserError> {
101+
let avail_len = __input.len();
102+
let mut payload_buf = [0; Self::ENCODED_LEN];
103+
let mut buf = if avail_len < Self::ENCODED_LEN {
104+
payload_buf[0..avail_len].copy_from_slice(__input);
105+
Bytes::new(&payload_buf)
106+
} else {
107+
Bytes::new(__input)
108+
};
109+
let mut __struct = Self::default();
110+
__struct.time_usec = buf.get_u64_le();
111+
__struct.seq = buf.get_u32_le();
112+
__struct.target_system = buf.get_u8();
113+
__struct.target_component = buf.get_u8();
114+
Ok(__struct)
115+
}
116+
fn ser(&self, version: MavlinkVersion, bytes: &mut [u8]) -> usize {
117+
let mut __tmp = BytesMut::new(bytes);
118+
#[allow(clippy::absurd_extreme_comparisons)]
119+
#[allow(unused_comparisons)]
120+
if __tmp.remaining() < Self::ENCODED_LEN {
121+
panic!(
122+
"buffer is too small (need {} bytes, but got {})",
123+
Self::ENCODED_LEN,
124+
__tmp.remaining(),
125+
)
126+
}
127+
__tmp.put_u64_le(self.time_usec);
128+
__tmp.put_u32_le(self.seq);
129+
__tmp.put_u8(self.target_system);
130+
__tmp.put_u8(self.target_component);
131+
if matches!(version, MavlinkVersion::V2) {
132+
let len = __tmp.len();
133+
::mavlink_core::utils::remove_trailing_zeroes(&bytes[..len])
134+
} else {
135+
__tmp.len()
136+
}
137+
}
138+
}
139+
#[derive(Clone, PartialEq, Debug)]
140+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
141+
#[cfg_attr(feature = "serde", serde(tag = "type"))]
142+
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
143+
#[repr(u32)]
144+
pub enum MavMessage {
145+
#[deprecated = "To be removed / merged with TIMESYNC. See `TIMESYNC` (Deprecated since 2011-08)"]
146+
PING(PING_DATA),
147+
}
148+
impl MavMessage {
149+
pub const fn all_ids() -> &'static [u32] {
150+
&[4u32]
151+
}
152+
}
153+
impl Message for MavMessage {
154+
fn parse(
155+
version: MavlinkVersion,
156+
id: u32,
157+
payload: &[u8],
158+
) -> Result<Self, ::mavlink_core::error::ParserError> {
159+
match id {
160+
PING_DATA::ID => PING_DATA::deser(version, payload).map(Self::PING),
161+
_ => Err(::mavlink_core::error::ParserError::UnknownMessage { id }),
162+
}
163+
}
164+
fn message_name(&self) -> &'static str {
165+
match self {
166+
Self::PING(..) => PING_DATA::NAME,
167+
}
168+
}
169+
fn message_id(&self) -> u32 {
170+
match self {
171+
Self::PING(..) => PING_DATA::ID,
172+
}
173+
}
174+
fn message_id_from_name(name: &str) -> Option<u32> {
175+
match name {
176+
PING_DATA::NAME => Some(PING_DATA::ID),
177+
_ => None,
178+
}
179+
}
180+
fn default_message_from_id(id: u32) -> Option<Self> {
181+
match id {
182+
PING_DATA::ID => Some(Self::PING(PING_DATA::default())),
183+
_ => None,
184+
}
185+
}
186+
#[cfg(feature = "arbitrary")]
187+
fn random_message_from_id<R: rand::RngCore>(id: u32, rng: &mut R) -> Option<Self> {
188+
match id {
189+
PING_DATA::ID => Some(Self::PING(PING_DATA::random(rng))),
190+
_ => None,
191+
}
192+
}
193+
fn ser(&self, version: MavlinkVersion, bytes: &mut [u8]) -> usize {
194+
match self {
195+
Self::PING(body) => body.ser(version, bytes),
196+
}
197+
}
198+
fn extra_crc(id: u32) -> u8 {
199+
match id {
200+
PING_DATA::ID => PING_DATA::EXTRA_CRC,
201+
_ => 0,
202+
}
203+
}
204+
fn target_system_id(&self) -> Option<u8> {
205+
match self {
206+
Self::PING(inner) => Some(inner.target_system),
207+
_ => None,
208+
}
209+
}
210+
fn target_component_id(&self) -> Option<u8> {
211+
match self {
212+
Self::PING(inner) => Some(inner.target_component),
213+
_ => None,
214+
}
215+
}
216+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
source: mavlink-bindgen/tests/e2e_snapshots.rs
3+
assertion_line: 26
4+
expression: contents
5+
---
6+
#[allow(non_camel_case_types)]
7+
#[allow(clippy::derive_partial_eq_without_eq)]
8+
#[allow(clippy::field_reassign_with_default)]
9+
#[allow(non_snake_case)]
10+
#[allow(clippy::unnecessary_cast)]
11+
#[allow(clippy::bad_bit_mask)]
12+
#[allow(clippy::suspicious_else_formatting)]
13+
#[cfg(feature = "deprecated")]
14+
pub mod deprecated;

mavlink-bindgen/tests/snapshots/e2e_snapshots__heartbeat.xml@heartbeat.rs.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ expression: contents
55
#![doc = "MAVLink heartbeat dialect."]
66
#![doc = ""]
77
#![doc = "This file was automatically generated, do not edit."]
8+
#![allow(deprecated)]
89
#[cfg(feature = "arbitrary")]
910
use arbitrary::Arbitrary;
1011
#[allow(unused_imports)]

mavlink-bindgen/tests/snapshots/e2e_snapshots__parameters.xml@parameters.rs.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ expression: contents
55
#![doc = "MAVLink parameters dialect."]
66
#![doc = ""]
77
#![doc = "This file was automatically generated, do not edit."]
8+
#![allow(deprecated)]
89
#[cfg(feature = "arbitrary")]
910
use arbitrary::Arbitrary;
1011
#[allow(unused_imports)]

mavlink/examples/mavlink-dump/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ pub fn request_parameters() -> mavlink::ardupilotmega::MavMessage {
8383

8484
/// Create a message enabling data streaming
8585
pub fn request_stream() -> mavlink::ardupilotmega::MavMessage {
86+
#[expect(deprecated)]
8687
mavlink::ardupilotmega::MavMessage::REQUEST_DATA_STREAM(
8788
mavlink::ardupilotmega::REQUEST_DATA_STREAM_DATA {
8889
target_system: 0,

mavlink/tests/helper_tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ mod helper_tests {
99
let id = id.unwrap();
1010
assert!(id == 4, "Invalid id for message name: PING");
1111
let message = MavMessage::default_message_from_id(id);
12+
#[expect(deprecated)]
1213
if !matches!(message, Some(MavMessage::PING(_))) {
1314
unreachable!("Invalid message type.")
1415
}

0 commit comments

Comments
 (0)