1#![cfg_attr(not(feature = "std"), no_std)]
83#![cfg_attr(docsrs, feature(doc_cfg))]
84#![deny(clippy::all)]
85#![warn(clippy::use_self)]
86
87use core::result::Result;
88
89#[cfg(feature = "std")]
90use std::io::{Read, Write};
91
92pub mod utils;
93#[allow(unused_imports)]
94use utils::{remove_trailing_zeroes, RustDefault};
95
96#[cfg(feature = "serde")]
97use serde::{Deserialize, Serialize};
98
99pub mod peek_reader;
100use peek_reader::PeekReader;
101
102use crate::{
103 bytes::Bytes,
104 error::{MessageReadError, MessageWriteError, ParserError},
105};
106
107use crc_any::CRCu16;
108
109#[doc(hidden)]
110pub mod bytes;
111#[doc(hidden)]
112pub mod bytes_mut;
113#[cfg(feature = "std")]
114mod connection;
115pub mod error;
116pub mod types;
117#[cfg(feature = "std")]
118pub use self::connection::{connect, Connectable, MavConnection};
119
120#[cfg(feature = "tokio-1")]
121mod async_connection;
122#[cfg(feature = "tokio-1")]
123pub use self::async_connection::{connect_async, AsyncConnectable, AsyncMavConnection};
124
125#[cfg(feature = "tokio-1")]
126pub mod async_peek_reader;
127#[cfg(feature = "tokio-1")]
128use async_peek_reader::AsyncPeekReader;
129#[cfg(feature = "tokio-1")]
130use tokio::io::{AsyncWrite, AsyncWriteExt};
131
132#[cfg(any(feature = "embedded", feature = "embedded-hal-02"))]
133pub mod embedded;
134#[cfg(any(feature = "embedded", feature = "embedded-hal-02"))]
135use embedded::{Read, Write};
136
137#[cfg(not(feature = "signing"))]
138type SigningData = ();
139#[cfg(feature = "signing")]
140mod signing;
141#[cfg(feature = "signing")]
142pub use self::signing::{SigningConfig, SigningData};
143#[cfg(feature = "signing")]
144use sha2::{Digest, Sha256};
145
146#[cfg(feature = "arbitrary")]
147use arbitrary::Arbitrary;
148
149#[cfg(any(feature = "std", feature = "tokio-1"))]
150mod connectable;
151
152#[cfg(any(feature = "std", feature = "tokio-1"))]
153pub use connectable::ConnectionAddress;
154
155#[cfg(feature = "direct-serial")]
156pub use connection::direct_serial::config::SerialConfig;
157
158#[cfg(feature = "tcp")]
159pub use connection::tcp::config::{TcpConfig, TcpMode};
160
161#[cfg(feature = "udp")]
162pub use connection::udp::config::{UdpConfig, UdpMode};
163
164#[cfg(feature = "std")]
165pub use connection::file::config::FileConfig;
166
167pub const MAX_FRAME_SIZE: usize = 280;
171
172pub trait Message
177where
178 Self: Sized,
179{
180 fn message_id(&self) -> u32;
182
183 fn message_name(&self) -> &'static str;
185
186 fn target_system_id(&self) -> Option<u8>;
188
189 fn target_component_id(&self) -> Option<u8>;
191
192 fn ser(&self, version: MavlinkVersion, bytes: &mut [u8]) -> usize;
198
199 fn parse(version: MavlinkVersion, msgid: u32, payload: &[u8]) -> Result<Self, ParserError>;
208
209 fn message_id_from_name(name: &str) -> Option<u32>;
211 fn default_message_from_id(id: u32) -> Option<Self>;
213 #[cfg(feature = "arbitrary")]
215 fn random_message_from_id<R: rand::RngCore>(id: u32, rng: &mut R) -> Option<Self>;
216 fn extra_crc(id: u32) -> u8;
218}
219
220pub trait MessageData: Sized {
221 type Message: Message;
222
223 const ID: u32;
224 const NAME: &'static str;
225 const EXTRA_CRC: u8;
226 const ENCODED_LEN: usize;
227
228 fn ser(&self, version: MavlinkVersion, payload: &mut [u8]) -> usize;
232 fn deser(version: MavlinkVersion, payload: &[u8]) -> Result<Self, ParserError>;
237}
238
239#[derive(Debug, Copy, Clone, PartialEq, Eq)]
241#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
242#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
243pub struct MavHeader {
244 pub system_id: u8,
246 pub component_id: u8,
248 pub sequence: u8,
250}
251
252#[derive(Debug, Copy, Clone, PartialEq, Eq)]
254#[cfg_attr(feature = "serde", derive(Serialize))]
255#[cfg_attr(feature = "serde", serde(tag = "type"))]
256#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
257pub enum MavlinkVersion {
258 V1,
260 V2,
262}
263
264pub const MAV_STX: u8 = 0xFE;
266
267pub const MAV_STX_V2: u8 = 0xFD;
269
270impl Default for MavHeader {
273 fn default() -> Self {
274 Self {
275 system_id: 255,
276 component_id: 0,
277 sequence: 0,
278 }
279 }
280}
281
282#[derive(Debug, Clone)]
286#[cfg_attr(feature = "serde", derive(Serialize))]
287#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
288pub struct MavFrame<M: Message> {
289 pub header: MavHeader,
291 pub msg: M,
293 pub protocol_version: MavlinkVersion,
295}
296
297impl<M: Message> MavFrame<M> {
298 pub fn ser(&self, buf: &mut [u8]) -> usize {
306 let mut buf = bytes_mut::BytesMut::new(buf);
307
308 let mut payload_buf = [0u8; 255];
310 let payload_len = self.msg.ser(self.protocol_version, &mut payload_buf);
311
312 buf.put_u8(self.header.sequence);
331 buf.put_u8(self.header.system_id);
332 buf.put_u8(self.header.component_id);
333
334 match self.protocol_version {
336 MavlinkVersion::V2 => {
337 let bytes: [u8; 4] = self.msg.message_id().to_le_bytes();
338 buf.put_slice(&bytes[..3]);
339 }
340 MavlinkVersion::V1 => {
341 buf.put_u8(self.msg.message_id() as u8); }
343 }
344
345 buf.put_slice(&payload_buf[..payload_len]);
346 buf.len()
347 }
348
349 pub fn deser(version: MavlinkVersion, input: &[u8]) -> Result<Self, ParserError> {
358 let mut buf = Bytes::new(input);
359
360 let sequence = buf.get_u8()?;
370 let system_id = buf.get_u8()?;
371 let component_id = buf.get_u8()?;
372 let header = MavHeader {
373 system_id,
374 component_id,
375 sequence,
376 };
377
378 let msg_id = match version {
379 MavlinkVersion::V2 => buf.get_u24_le()?,
380 MavlinkVersion::V1 => buf.get_u8()?.into(),
381 };
382
383 M::parse(version, msg_id, buf.remaining_bytes()).map(|msg| Self {
384 header,
385 msg,
386 protocol_version: version,
387 })
388 }
389
390 pub fn header(&self) -> MavHeader {
392 self.header
393 }
394}
395
396pub fn calculate_crc(data: &[u8], extra_crc: u8) -> u16 {
398 let mut crc_calculator = CRCu16::crc16mcrf4cc();
399 crc_calculator.digest(data);
400
401 crc_calculator.digest(&[extra_crc]);
402 crc_calculator.get_crc()
403}
404
405#[derive(Debug, Clone, Copy, PartialEq, Eq)]
406pub enum ReadVersion {
408 Single(MavlinkVersion),
410 Any,
412}
413
414impl ReadVersion {
415 #[cfg(feature = "std")]
416 fn from_conn_cfg<C: MavConnection<M>, M: Message>(conn: &C) -> Self {
417 if conn.allow_recv_any_version() {
418 Self::Any
419 } else {
420 conn.protocol_version().into()
421 }
422 }
423 #[cfg(feature = "tokio-1")]
424 fn from_async_conn_cfg<C: AsyncMavConnection<M>, M: Message + Sync + Send>(conn: &C) -> Self {
425 if conn.allow_recv_any_version() {
426 Self::Any
427 } else {
428 conn.protocol_version().into()
429 }
430 }
431}
432
433impl From<MavlinkVersion> for ReadVersion {
434 fn from(value: MavlinkVersion) -> Self {
435 Self::Single(value)
436 }
437}
438
439pub fn read_versioned_msg<M: Message, R: Read>(
445 r: &mut PeekReader<R>,
446 version: ReadVersion,
447) -> Result<(MavHeader, M), MessageReadError> {
448 match version {
449 ReadVersion::Single(MavlinkVersion::V2) => read_v2_msg(r),
450 ReadVersion::Single(MavlinkVersion::V1) => read_v1_msg(r),
451 ReadVersion::Any => read_any_msg(r),
452 }
453}
454
455pub fn read_versioned_raw_message<M: Message, R: Read>(
461 r: &mut PeekReader<R>,
462 version: ReadVersion,
463) -> Result<MAVLinkMessageRaw, MessageReadError> {
464 match version {
465 ReadVersion::Single(MavlinkVersion::V2) => {
466 Ok(MAVLinkMessageRaw::V2(read_v2_raw_message::<M, _>(r)?))
467 }
468 ReadVersion::Single(MavlinkVersion::V1) => {
469 Ok(MAVLinkMessageRaw::V1(read_v1_raw_message::<M, _>(r)?))
470 }
471 ReadVersion::Any => read_any_raw_message::<M, _>(r),
472 }
473}
474
475#[cfg(feature = "tokio-1")]
481pub async fn read_versioned_msg_async<M: Message, R: tokio::io::AsyncRead + Unpin>(
482 r: &mut AsyncPeekReader<R>,
483 version: ReadVersion,
484) -> Result<(MavHeader, M), MessageReadError> {
485 match version {
486 ReadVersion::Single(MavlinkVersion::V2) => read_v2_msg_async(r).await,
487 ReadVersion::Single(MavlinkVersion::V1) => read_v1_msg_async(r).await,
488 ReadVersion::Any => read_any_msg_async(r).await,
489 }
490}
491
492#[cfg(feature = "tokio-1")]
498pub async fn read_versioned_raw_message_async<M: Message, R: tokio::io::AsyncRead + Unpin>(
499 r: &mut AsyncPeekReader<R>,
500 version: ReadVersion,
501) -> Result<MAVLinkMessageRaw, MessageReadError> {
502 match version {
503 ReadVersion::Single(MavlinkVersion::V2) => Ok(MAVLinkMessageRaw::V2(
504 read_v2_raw_message_async::<M, _>(r).await?,
505 )),
506 ReadVersion::Single(MavlinkVersion::V1) => Ok(MAVLinkMessageRaw::V1(
507 read_v1_raw_message_async::<M, _>(r).await?,
508 )),
509 ReadVersion::Any => read_any_raw_message_async::<M, _>(r).await,
510 }
511}
512
513#[cfg(feature = "signing")]
522pub fn read_versioned_raw_message_signed<M: Message, R: Read>(
523 r: &mut PeekReader<R>,
524 version: ReadVersion,
525 signing_data: Option<&SigningData>,
526) -> Result<MAVLinkMessageRaw, MessageReadError> {
527 match version {
528 ReadVersion::Single(MavlinkVersion::V2) => Ok(MAVLinkMessageRaw::V2(
529 read_v2_raw_message_inner::<M, _>(r, signing_data)?,
530 )),
531 ReadVersion::Single(MavlinkVersion::V1) => {
532 Ok(MAVLinkMessageRaw::V1(read_v1_raw_message::<M, _>(r)?))
533 }
534 ReadVersion::Any => read_any_raw_message_inner::<M, _>(r, signing_data),
535 }
536}
537
538#[cfg(feature = "signing")]
547pub fn read_versioned_msg_signed<M: Message, R: Read>(
548 r: &mut PeekReader<R>,
549 version: ReadVersion,
550 signing_data: Option<&SigningData>,
551) -> Result<(MavHeader, M), MessageReadError> {
552 match version {
553 ReadVersion::Single(MavlinkVersion::V2) => read_v2_msg_inner(r, signing_data),
554 ReadVersion::Single(MavlinkVersion::V1) => read_v1_msg(r),
555 ReadVersion::Any => read_any_msg_inner(r, signing_data),
556 }
557}
558
559#[cfg(all(feature = "tokio-1", feature = "signing"))]
568pub async fn read_versioned_raw_message_async_signed<
569 M: Message,
570 R: tokio::io::AsyncRead + Unpin,
571>(
572 r: &mut AsyncPeekReader<R>,
573 version: ReadVersion,
574 signing_data: Option<&SigningData>,
575) -> Result<MAVLinkMessageRaw, MessageReadError> {
576 match version {
577 ReadVersion::Single(MavlinkVersion::V2) => Ok(MAVLinkMessageRaw::V2(
578 read_v2_raw_message_async_inner::<M, _>(r, signing_data).await?,
579 )),
580 ReadVersion::Single(MavlinkVersion::V1) => Ok(MAVLinkMessageRaw::V1(
581 read_v1_raw_message_async::<M, _>(r).await?,
582 )),
583 ReadVersion::Any => read_any_raw_message_async_inner::<M, _>(r, signing_data).await,
584 }
585}
586
587#[cfg(all(feature = "tokio-1", feature = "signing"))]
596pub async fn read_versioned_msg_async_signed<M: Message, R: tokio::io::AsyncRead + Unpin>(
597 r: &mut AsyncPeekReader<R>,
598 version: ReadVersion,
599 signing_data: Option<&SigningData>,
600) -> Result<(MavHeader, M), MessageReadError> {
601 match version {
602 ReadVersion::Single(MavlinkVersion::V2) => read_v2_msg_async_inner(r, signing_data).await,
603 ReadVersion::Single(MavlinkVersion::V1) => read_v1_msg_async(r).await,
604 ReadVersion::Any => read_any_msg_async_inner(r, signing_data).await,
605 }
606}
607
608#[derive(Debug, Copy, Clone, PartialEq, Eq)]
609pub struct MAVLinkV1MessageRaw([u8; 1 + Self::HEADER_SIZE + 255 + 2]);
614
615impl Default for MAVLinkV1MessageRaw {
616 fn default() -> Self {
617 Self::new()
618 }
619}
620
621impl MAVLinkV1MessageRaw {
622 const HEADER_SIZE: usize = 5;
623
624 pub const fn new() -> Self {
626 Self([0; 1 + Self::HEADER_SIZE + 255 + 2])
627 }
628
629 pub const fn from_bytes_unparsed(bytes: [u8; 1 + Self::HEADER_SIZE + 255 + 2]) -> Self {
633 Self(bytes)
634 }
635
636 #[inline]
638 pub fn as_slice(&self) -> &[u8] {
639 &self.0
640 }
641
642 #[inline]
644 pub fn as_mut_slice(&mut self) -> &mut [u8] {
645 &mut self.0
646 }
647
648 #[inline]
650 pub fn into_inner(self) -> [u8; 1 + Self::HEADER_SIZE + 255 + 2] {
651 self.0
652 }
653
654 #[inline]
656 pub fn header(&self) -> &[u8] {
657 &self.0[1..=Self::HEADER_SIZE]
658 }
659
660 #[inline]
662 fn mut_header(&mut self) -> &mut [u8] {
663 &mut self.0[1..=Self::HEADER_SIZE]
664 }
665
666 #[inline]
668 pub fn payload_length(&self) -> u8 {
669 self.0[1]
670 }
671
672 #[inline]
674 pub fn sequence(&self) -> u8 {
675 self.0[2]
676 }
677
678 #[inline]
680 pub fn system_id(&self) -> u8 {
681 self.0[3]
682 }
683
684 #[inline]
686 pub fn component_id(&self) -> u8 {
687 self.0[4]
688 }
689
690 #[inline]
692 pub fn message_id(&self) -> u8 {
693 self.0[5]
694 }
695
696 #[inline]
698 pub fn payload(&self) -> &[u8] {
699 let payload_length: usize = self.payload_length().into();
700 &self.0[(1 + Self::HEADER_SIZE)..(1 + Self::HEADER_SIZE + payload_length)]
701 }
702
703 #[inline]
705 pub fn checksum(&self) -> u16 {
706 let payload_length: usize = self.payload_length().into();
707 u16::from_le_bytes([
708 self.0[1 + Self::HEADER_SIZE + payload_length],
709 self.0[1 + Self::HEADER_SIZE + payload_length + 1],
710 ])
711 }
712
713 #[inline]
714 fn mut_payload_and_checksum(&mut self) -> &mut [u8] {
715 let payload_length: usize = self.payload_length().into();
716 &mut self.0[(1 + Self::HEADER_SIZE)..(1 + Self::HEADER_SIZE + payload_length + 2)]
717 }
718
719 #[inline]
721 pub fn has_valid_crc<M: Message>(&self) -> bool {
722 let payload_length: usize = self.payload_length().into();
723 self.checksum()
724 == calculate_crc(
725 &self.0[1..(1 + Self::HEADER_SIZE + payload_length)],
726 M::extra_crc(self.message_id().into()),
727 )
728 }
729
730 pub fn raw_bytes(&self) -> &[u8] {
732 let payload_length = self.payload_length() as usize;
733 &self.0[..(1 + Self::HEADER_SIZE + payload_length + 2)]
734 }
735
736 fn serialize_stx_and_header_and_crc(
740 &mut self,
741 header: MavHeader,
742 msgid: u32,
743 payload_length: usize,
744 extra_crc: u8,
745 ) {
746 self.0[0] = MAV_STX;
747
748 let header_buf = self.mut_header();
749 header_buf.copy_from_slice(&[
750 payload_length as u8,
751 header.sequence,
752 header.system_id,
753 header.component_id,
754 msgid.try_into().unwrap(),
755 ]);
756
757 let crc = calculate_crc(
758 &self.0[1..(1 + Self::HEADER_SIZE + payload_length)],
759 extra_crc,
760 );
761 self.0[(1 + Self::HEADER_SIZE + payload_length)
762 ..(1 + Self::HEADER_SIZE + payload_length + 2)]
763 .copy_from_slice(&crc.to_le_bytes());
764 }
765
766 pub fn serialize_message<M: Message>(&mut self, header: MavHeader, message: &M) {
772 let payload_buf = &mut self.0[(1 + Self::HEADER_SIZE)..(1 + Self::HEADER_SIZE + 255)];
773 let payload_length = message.ser(MavlinkVersion::V1, payload_buf);
774
775 let message_id = message.message_id();
776 self.serialize_stx_and_header_and_crc(
777 header,
778 message_id,
779 payload_length,
780 M::extra_crc(message_id),
781 );
782 }
783
784 pub fn serialize_message_data<D: MessageData>(&mut self, header: MavHeader, message_data: &D) {
788 let payload_buf = &mut self.0[(1 + Self::HEADER_SIZE)..(1 + Self::HEADER_SIZE + 255)];
789 let payload_length = message_data.ser(MavlinkVersion::V1, payload_buf);
790
791 self.serialize_stx_and_header_and_crc(header, D::ID, payload_length, D::EXTRA_CRC);
792 }
793}
794
795fn try_decode_v1<M: Message, R: Read>(
796 reader: &mut PeekReader<R>,
797) -> Result<Option<MAVLinkV1MessageRaw>, MessageReadError> {
798 let mut message = MAVLinkV1MessageRaw::new();
799 let whole_header_size = MAVLinkV1MessageRaw::HEADER_SIZE + 1;
800
801 message.0[0] = MAV_STX;
802 let header = &reader.peek_exact(whole_header_size)?[1..whole_header_size];
803 message.mut_header().copy_from_slice(header);
804 let packet_length = message.raw_bytes().len();
805 let payload_and_checksum = &reader.peek_exact(packet_length)?[whole_header_size..packet_length];
806 message
807 .mut_payload_and_checksum()
808 .copy_from_slice(payload_and_checksum);
809
810 if message.has_valid_crc::<M>() {
813 reader.consume(message.raw_bytes().len());
814 Ok(Some(message))
815 } else {
816 Ok(None)
817 }
818}
819
820#[cfg(feature = "tokio-1")]
821async fn try_decode_v1_async<M: Message, R: tokio::io::AsyncRead + Unpin>(
823 reader: &mut AsyncPeekReader<R>,
824) -> Result<Option<MAVLinkV1MessageRaw>, MessageReadError> {
825 let mut message = MAVLinkV1MessageRaw::new();
826
827 message.0[0] = MAV_STX;
828 let header = &reader.peek_exact(MAVLinkV1MessageRaw::HEADER_SIZE).await?
829 [..MAVLinkV1MessageRaw::HEADER_SIZE];
830 message.mut_header().copy_from_slice(header);
831 let packet_length = message.raw_bytes().len() - 1;
832 let payload_and_checksum =
833 &reader.peek_exact(packet_length).await?[MAVLinkV1MessageRaw::HEADER_SIZE..packet_length];
834 message
835 .mut_payload_and_checksum()
836 .copy_from_slice(payload_and_checksum);
837
838 if message.has_valid_crc::<M>() {
841 reader.consume(message.raw_bytes().len() - 1);
842 Ok(Some(message))
843 } else {
844 Ok(None)
845 }
846}
847
848pub fn read_v1_raw_message<M: Message, R: Read>(
854 reader: &mut PeekReader<R>,
855) -> Result<MAVLinkV1MessageRaw, MessageReadError> {
856 loop {
857 while reader.peek_exact(1)?[0] != MAV_STX {
859 reader.consume(1);
860 }
861
862 if let Some(msg) = try_decode_v1::<M, _>(reader)? {
863 return Ok(msg);
864 }
865
866 reader.consume(1);
867 }
868}
869
870#[cfg(feature = "tokio-1")]
876pub async fn read_v1_raw_message_async<M: Message, R: tokio::io::AsyncRead + Unpin>(
877 reader: &mut AsyncPeekReader<R>,
878) -> Result<MAVLinkV1MessageRaw, MessageReadError> {
879 loop {
880 loop {
881 if reader.read_u8().await? == MAV_STX {
883 break;
884 }
885 }
886
887 if let Some(message) = try_decode_v1_async::<M, _>(reader).await? {
888 return Ok(message);
889 }
890 }
891}
892
893#[cfg(feature = "embedded")]
900pub async fn read_v1_raw_message_async<M: Message>(
901 reader: &mut impl embedded_io_async::Read,
902) -> Result<MAVLinkV1MessageRaw, MessageReadError> {
903 loop {
904 let mut byte = [0u8];
906 loop {
907 reader
908 .read_exact(&mut byte)
909 .await
910 .map_err(|_| MessageReadError::Io)?;
911 if byte[0] == MAV_STX {
912 break;
913 }
914 }
915
916 let mut message = MAVLinkV1MessageRaw::new();
917
918 message.0[0] = MAV_STX;
919 reader
920 .read_exact(message.mut_header())
921 .await
922 .map_err(|_| MessageReadError::Io)?;
923 reader
924 .read_exact(message.mut_payload_and_checksum())
925 .await
926 .map_err(|_| MessageReadError::Io)?;
927
928 if message.has_valid_crc::<M>() {
931 return Ok(message);
932 }
933 }
934}
935
936pub fn read_v1_msg<M: Message, R: Read>(
942 r: &mut PeekReader<R>,
943) -> Result<(MavHeader, M), MessageReadError> {
944 let message = read_v1_raw_message::<M, _>(r)?;
945
946 Ok((
947 MavHeader {
948 sequence: message.sequence(),
949 system_id: message.system_id(),
950 component_id: message.component_id(),
951 },
952 M::parse(
953 MavlinkVersion::V1,
954 u32::from(message.message_id()),
955 message.payload(),
956 )?,
957 ))
958}
959
960#[cfg(feature = "tokio-1")]
966pub async fn read_v1_msg_async<M: Message, R: tokio::io::AsyncRead + Unpin>(
967 r: &mut AsyncPeekReader<R>,
968) -> Result<(MavHeader, M), MessageReadError> {
969 let message = read_v1_raw_message_async::<M, _>(r).await?;
970
971 Ok((
972 MavHeader {
973 sequence: message.sequence(),
974 system_id: message.system_id(),
975 component_id: message.component_id(),
976 },
977 M::parse(
978 MavlinkVersion::V1,
979 u32::from(message.message_id()),
980 message.payload(),
981 )?,
982 ))
983}
984
985#[cfg(feature = "embedded")]
990pub async fn read_v1_msg_async<M: Message>(
991 r: &mut impl embedded_io_async::Read,
992) -> Result<(MavHeader, M), MessageReadError> {
993 let message = read_v1_raw_message_async::<M>(r).await?;
994
995 Ok((
996 MavHeader {
997 sequence: message.sequence(),
998 system_id: message.system_id(),
999 component_id: message.component_id(),
1000 },
1001 M::parse(
1002 MavlinkVersion::V1,
1003 u32::from(message.message_id()),
1004 message.payload(),
1005 )?,
1006 ))
1007}
1008
1009const MAVLINK_IFLAG_SIGNED: u8 = 0x01;
1010const MAVLINK_SUPPORTED_IFLAGS: u8 = MAVLINK_IFLAG_SIGNED;
1011
1012#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1013pub struct MAVLinkV2MessageRaw([u8; 1 + Self::HEADER_SIZE + 255 + 2 + Self::SIGNATURE_SIZE]);
1018
1019impl Default for MAVLinkV2MessageRaw {
1020 fn default() -> Self {
1021 Self::new()
1022 }
1023}
1024
1025impl MAVLinkV2MessageRaw {
1026 const HEADER_SIZE: usize = 9;
1027 const SIGNATURE_SIZE: usize = 13;
1028
1029 pub const fn new() -> Self {
1031 Self([0; 1 + Self::HEADER_SIZE + 255 + 2 + Self::SIGNATURE_SIZE])
1032 }
1033
1034 pub const fn from_bytes_unparsed(
1038 bytes: [u8; 1 + Self::HEADER_SIZE + 255 + 2 + Self::SIGNATURE_SIZE],
1039 ) -> Self {
1040 Self(bytes)
1041 }
1042
1043 #[inline]
1045 pub fn as_slice(&self) -> &[u8] {
1046 &self.0
1047 }
1048
1049 #[inline]
1051 pub fn as_mut_slice(&mut self) -> &mut [u8] {
1052 &mut self.0
1053 }
1054
1055 #[inline]
1057 pub fn into_inner(self) -> [u8; 1 + Self::HEADER_SIZE + 255 + 2 + Self::SIGNATURE_SIZE] {
1058 self.0
1059 }
1060
1061 #[inline]
1063 pub fn header(&self) -> &[u8] {
1064 &self.0[1..=Self::HEADER_SIZE]
1065 }
1066
1067 #[inline]
1069 fn mut_header(&mut self) -> &mut [u8] {
1070 &mut self.0[1..=Self::HEADER_SIZE]
1071 }
1072
1073 #[inline]
1075 pub fn payload_length(&self) -> u8 {
1076 self.0[1]
1077 }
1078
1079 #[inline]
1083 pub fn incompatibility_flags(&self) -> u8 {
1084 self.0[2]
1085 }
1086
1087 #[inline]
1091 pub fn incompatibility_flags_mut(&mut self) -> &mut u8 {
1092 &mut self.0[2]
1093 }
1094
1095 #[inline]
1097 pub fn compatibility_flags(&self) -> u8 {
1098 self.0[3]
1099 }
1100
1101 #[inline]
1103 pub fn sequence(&self) -> u8 {
1104 self.0[4]
1105 }
1106
1107 #[inline]
1109 pub fn system_id(&self) -> u8 {
1110 self.0[5]
1111 }
1112
1113 #[inline]
1115 pub fn component_id(&self) -> u8 {
1116 self.0[6]
1117 }
1118
1119 #[inline]
1121 pub fn message_id(&self) -> u32 {
1122 u32::from_le_bytes([self.0[7], self.0[8], self.0[9], 0])
1123 }
1124
1125 #[inline]
1127 pub fn payload(&self) -> &[u8] {
1128 let payload_length: usize = self.payload_length().into();
1129 &self.0[(1 + Self::HEADER_SIZE)..(1 + Self::HEADER_SIZE + payload_length)]
1130 }
1131
1132 #[inline]
1134 pub fn checksum(&self) -> u16 {
1135 let payload_length: usize = self.payload_length().into();
1136 u16::from_le_bytes([
1137 self.0[1 + Self::HEADER_SIZE + payload_length],
1138 self.0[1 + Self::HEADER_SIZE + payload_length + 1],
1139 ])
1140 }
1141
1142 #[cfg(feature = "signing")]
1144 #[inline]
1145 pub fn checksum_bytes(&self) -> &[u8] {
1146 let checksum_offset = 1 + Self::HEADER_SIZE + self.payload_length() as usize;
1147 &self.0[checksum_offset..(checksum_offset + 2)]
1148 }
1149
1150 #[cfg(feature = "signing")]
1154 #[inline]
1155 pub fn signature_link_id(&self) -> u8 {
1156 let payload_length: usize = self.payload_length().into();
1157 self.0[1 + Self::HEADER_SIZE + payload_length + 2]
1158 }
1159
1160 #[cfg(feature = "signing")]
1162 #[inline]
1163 pub fn signature_link_id_mut(&mut self) -> &mut u8 {
1164 let payload_length: usize = self.payload_length().into();
1165 &mut self.0[1 + Self::HEADER_SIZE + payload_length + 2]
1166 }
1167
1168 #[cfg(feature = "signing")]
1174 #[inline]
1175 pub fn signature_timestamp(&self) -> u64 {
1176 let mut timestamp_bytes = [0u8; 8];
1177 timestamp_bytes[0..6].copy_from_slice(self.signature_timestamp_bytes());
1178 u64::from_le_bytes(timestamp_bytes)
1179 }
1180
1181 #[cfg(feature = "signing")]
1185 #[inline]
1186 pub fn signature_timestamp_bytes(&self) -> &[u8] {
1187 let payload_length: usize = self.payload_length().into();
1188 let timestamp_start = 1 + Self::HEADER_SIZE + payload_length + 3;
1189 &self.0[timestamp_start..(timestamp_start + 6)]
1190 }
1191
1192 #[cfg(feature = "signing")]
1194 #[inline]
1195 pub fn signature_timestamp_bytes_mut(&mut self) -> &mut [u8] {
1196 let payload_length: usize = self.payload_length().into();
1197 let timestamp_start = 1 + Self::HEADER_SIZE + payload_length + 3;
1198 &mut self.0[timestamp_start..(timestamp_start + 6)]
1199 }
1200
1201 #[cfg(feature = "signing")]
1205 #[inline]
1206 pub fn signature_value(&self) -> &[u8] {
1207 let payload_length: usize = self.payload_length().into();
1208 let signature_start = 1 + Self::HEADER_SIZE + payload_length + 3 + 6;
1209 &self.0[signature_start..(signature_start + 6)]
1210 }
1211
1212 #[cfg(feature = "signing")]
1214 #[inline]
1215 pub fn signature_value_mut(&mut self) -> &mut [u8] {
1216 let payload_length: usize = self.payload_length().into();
1217 let signature_start = 1 + Self::HEADER_SIZE + payload_length + 3 + 6;
1218 &mut self.0[signature_start..(signature_start + 6)]
1219 }
1220
1221 fn mut_payload_and_checksum_and_sign(&mut self) -> &mut [u8] {
1222 let payload_length: usize = self.payload_length().into();
1223
1224 let signature_size = if (self.incompatibility_flags() & MAVLINK_IFLAG_SIGNED) == 0 {
1226 0
1227 } else {
1228 Self::SIGNATURE_SIZE
1229 };
1230
1231 &mut self.0
1232 [(1 + Self::HEADER_SIZE)..(1 + Self::HEADER_SIZE + payload_length + signature_size + 2)]
1233 }
1234
1235 #[inline]
1237 pub fn has_valid_crc<M: Message>(&self) -> bool {
1238 let payload_length: usize = self.payload_length().into();
1239 self.checksum()
1240 == calculate_crc(
1241 &self.0[1..(1 + Self::HEADER_SIZE + payload_length)],
1242 M::extra_crc(self.message_id()),
1243 )
1244 }
1245
1246 #[cfg(feature = "signing")]
1250 pub fn calculate_signature(&self, secret_key: &[u8], target_buffer: &mut [u8; 6]) {
1251 let mut hasher = Sha256::new();
1252 hasher.update(secret_key);
1253 hasher.update([MAV_STX_V2]);
1254 hasher.update(self.header());
1255 hasher.update(self.payload());
1256 hasher.update(self.checksum_bytes());
1257 hasher.update([self.signature_link_id()]);
1258 hasher.update(self.signature_timestamp_bytes());
1259 target_buffer.copy_from_slice(&hasher.finalize()[0..6]);
1260 }
1261
1262 pub fn raw_bytes(&self) -> &[u8] {
1264 let payload_length = self.payload_length() as usize;
1265
1266 let signature_size = if (self.incompatibility_flags() & MAVLINK_IFLAG_SIGNED) == 0 {
1267 0
1268 } else {
1269 Self::SIGNATURE_SIZE
1270 };
1271
1272 &self.0[..(1 + Self::HEADER_SIZE + payload_length + signature_size + 2)]
1273 }
1274
1275 fn serialize_stx_and_header_and_crc(
1276 &mut self,
1277 header: MavHeader,
1278 msgid: u32,
1279 payload_length: usize,
1280 extra_crc: u8,
1281 incompat_flags: u8,
1282 ) {
1283 self.0[0] = MAV_STX_V2;
1284 let msgid_bytes = msgid.to_le_bytes();
1285
1286 let header_buf = self.mut_header();
1287 header_buf.copy_from_slice(&[
1288 payload_length as u8,
1289 incompat_flags,
1290 0, header.sequence,
1292 header.system_id,
1293 header.component_id,
1294 msgid_bytes[0],
1295 msgid_bytes[1],
1296 msgid_bytes[2],
1297 ]);
1298
1299 let crc = calculate_crc(
1300 &self.0[1..(1 + Self::HEADER_SIZE + payload_length)],
1301 extra_crc,
1302 );
1303 self.0[(1 + Self::HEADER_SIZE + payload_length)
1304 ..(1 + Self::HEADER_SIZE + payload_length + 2)]
1305 .copy_from_slice(&crc.to_le_bytes());
1306 }
1307
1308 pub fn serialize_message<M: Message>(&mut self, header: MavHeader, message: &M) {
1312 let payload_buf = &mut self.0[(1 + Self::HEADER_SIZE)..(1 + Self::HEADER_SIZE + 255)];
1313 let payload_length = message.ser(MavlinkVersion::V2, payload_buf);
1314
1315 let message_id = message.message_id();
1316 self.serialize_stx_and_header_and_crc(
1317 header,
1318 message_id,
1319 payload_length,
1320 M::extra_crc(message_id),
1321 0,
1322 );
1323 }
1324
1325 pub fn serialize_message_for_signing<M: Message>(&mut self, header: MavHeader, message: &M) {
1330 let payload_buf = &mut self.0[(1 + Self::HEADER_SIZE)..(1 + Self::HEADER_SIZE + 255)];
1331 let payload_length = message.ser(MavlinkVersion::V2, payload_buf);
1332
1333 let message_id = message.message_id();
1334 self.serialize_stx_and_header_and_crc(
1335 header,
1336 message_id,
1337 payload_length,
1338 M::extra_crc(message_id),
1339 MAVLINK_IFLAG_SIGNED,
1340 );
1341 }
1342
1343 pub fn serialize_message_data<D: MessageData>(&mut self, header: MavHeader, message_data: &D) {
1344 let payload_buf = &mut self.0[(1 + Self::HEADER_SIZE)..(1 + Self::HEADER_SIZE + 255)];
1345 let payload_length = message_data.ser(MavlinkVersion::V2, payload_buf);
1346
1347 self.serialize_stx_and_header_and_crc(header, D::ID, payload_length, D::EXTRA_CRC, 0);
1348 }
1349}
1350
1351#[allow(unused_variables)]
1352fn try_decode_v2<M: Message, R: Read>(
1353 reader: &mut PeekReader<R>,
1354 signing_data: Option<&SigningData>,
1355) -> Result<Option<MAVLinkV2MessageRaw>, MessageReadError> {
1356 let mut message = MAVLinkV2MessageRaw::new();
1357 let whole_header_size = MAVLinkV2MessageRaw::HEADER_SIZE + 1;
1358
1359 message.0[0] = MAV_STX_V2;
1360 let header = &reader.peek_exact(whole_header_size)?[1..whole_header_size];
1361 message.mut_header().copy_from_slice(header);
1362
1363 if message.incompatibility_flags() & !MAVLINK_SUPPORTED_IFLAGS > 0 {
1364 reader.consume(1);
1366 return Ok(None);
1367 }
1368
1369 let packet_length = message.raw_bytes().len();
1370 let payload_and_checksum_and_sign =
1371 &reader.peek_exact(packet_length)?[whole_header_size..packet_length];
1372 message
1373 .mut_payload_and_checksum_and_sign()
1374 .copy_from_slice(payload_and_checksum_and_sign);
1375
1376 if message.has_valid_crc::<M>() {
1377 reader.consume(message.raw_bytes().len());
1379 } else {
1380 reader.consume(1);
1381 return Ok(None);
1382 }
1383
1384 #[cfg(feature = "signing")]
1385 if let Some(signing_data) = signing_data {
1386 if !signing_data.verify_signature(&message) {
1387 return Ok(None);
1388 }
1389 }
1390
1391 Ok(Some(message))
1392}
1393
1394#[cfg(feature = "tokio-1")]
1395#[allow(unused_variables)]
1396async fn try_decode_v2_async<M: Message, R: tokio::io::AsyncRead + Unpin>(
1398 reader: &mut AsyncPeekReader<R>,
1399 signing_data: Option<&SigningData>,
1400) -> Result<Option<MAVLinkV2MessageRaw>, MessageReadError> {
1401 let mut message = MAVLinkV2MessageRaw::new();
1402
1403 message.0[0] = MAV_STX_V2;
1404 let header = &reader.peek_exact(MAVLinkV2MessageRaw::HEADER_SIZE).await?
1405 [..MAVLinkV2MessageRaw::HEADER_SIZE];
1406 message.mut_header().copy_from_slice(header);
1407
1408 if message.incompatibility_flags() & !MAVLINK_SUPPORTED_IFLAGS > 0 {
1409 return Ok(None);
1411 }
1412
1413 let packet_length = message.raw_bytes().len() - 1;
1414 let payload_and_checksum_and_sign =
1415 &reader.peek_exact(packet_length).await?[MAVLinkV2MessageRaw::HEADER_SIZE..packet_length];
1416 message
1417 .mut_payload_and_checksum_and_sign()
1418 .copy_from_slice(payload_and_checksum_and_sign);
1419
1420 if message.has_valid_crc::<M>() {
1421 reader.consume(message.raw_bytes().len() - 1);
1423 } else {
1424 return Ok(None);
1425 }
1426
1427 #[cfg(feature = "signing")]
1428 if let Some(signing_data) = signing_data {
1429 if !signing_data.verify_signature(&message) {
1430 return Ok(None);
1431 }
1432 }
1433
1434 Ok(Some(message))
1435}
1436
1437#[inline]
1443pub fn read_v2_raw_message<M: Message, R: Read>(
1444 reader: &mut PeekReader<R>,
1445) -> Result<MAVLinkV2MessageRaw, MessageReadError> {
1446 read_v2_raw_message_inner::<M, R>(reader, None)
1447}
1448
1449#[cfg(feature = "signing")]
1455#[inline]
1456pub fn read_v2_raw_message_signed<M: Message, R: Read>(
1457 reader: &mut PeekReader<R>,
1458 signing_data: Option<&SigningData>,
1459) -> Result<MAVLinkV2MessageRaw, MessageReadError> {
1460 read_v2_raw_message_inner::<M, R>(reader, signing_data)
1461}
1462
1463#[allow(unused_variables)]
1464fn read_v2_raw_message_inner<M: Message, R: Read>(
1465 reader: &mut PeekReader<R>,
1466 signing_data: Option<&SigningData>,
1467) -> Result<MAVLinkV2MessageRaw, MessageReadError> {
1468 loop {
1469 while reader.peek_exact(1)?[0] != MAV_STX_V2 {
1471 reader.consume(1);
1472 }
1473
1474 if let Some(message) = try_decode_v2::<M, _>(reader, signing_data)? {
1475 return Ok(message);
1476 }
1477 }
1478}
1479
1480#[cfg(feature = "tokio-1")]
1486pub async fn read_v2_raw_message_async<M: Message, R: tokio::io::AsyncRead + Unpin>(
1487 reader: &mut AsyncPeekReader<R>,
1488) -> Result<MAVLinkV2MessageRaw, MessageReadError> {
1489 read_v2_raw_message_async_inner::<M, R>(reader, None).await
1490}
1491
1492#[cfg(feature = "tokio-1")]
1493#[allow(unused_variables)]
1494async fn read_v2_raw_message_async_inner<M: Message, R: tokio::io::AsyncRead + Unpin>(
1495 reader: &mut AsyncPeekReader<R>,
1496 signing_data: Option<&SigningData>,
1497) -> Result<MAVLinkV2MessageRaw, MessageReadError> {
1498 loop {
1499 loop {
1500 if reader.read_u8().await? == MAV_STX_V2 {
1502 break;
1503 }
1504 }
1505
1506 if let Some(message) = try_decode_v2_async::<M, _>(reader, signing_data).await? {
1507 return Ok(message);
1508 }
1509 }
1510}
1511
1512#[cfg(all(feature = "tokio-1", feature = "signing"))]
1518pub async fn read_v2_raw_message_async_signed<M: Message, R: tokio::io::AsyncRead + Unpin>(
1519 reader: &mut AsyncPeekReader<R>,
1520 signing_data: Option<&SigningData>,
1521) -> Result<MAVLinkV2MessageRaw, MessageReadError> {
1522 read_v2_raw_message_async_inner::<M, R>(reader, signing_data).await
1523}
1524
1525#[cfg(feature = "embedded")]
1531pub async fn read_v2_raw_message_async<M: Message>(
1532 reader: &mut impl embedded_io_async::Read,
1533) -> Result<MAVLinkV2MessageRaw, MessageReadError> {
1534 loop {
1535 let mut byte = [0u8];
1537 loop {
1538 reader
1539 .read_exact(&mut byte)
1540 .await
1541 .map_err(|_| MessageReadError::Io)?;
1542 if byte[0] == MAV_STX_V2 {
1543 break;
1544 }
1545 }
1546
1547 let mut message = MAVLinkV2MessageRaw::new();
1548
1549 message.0[0] = MAV_STX_V2;
1550 reader
1551 .read_exact(message.mut_header())
1552 .await
1553 .map_err(|_| MessageReadError::Io)?;
1554
1555 if message.incompatibility_flags() & !MAVLINK_SUPPORTED_IFLAGS > 0 {
1556 continue;
1558 }
1559
1560 reader
1561 .read_exact(message.mut_payload_and_checksum_and_sign())
1562 .await
1563 .map_err(|_| MessageReadError::Io)?;
1564
1565 if message.has_valid_crc::<M>() {
1568 return Ok(message);
1569 }
1570 }
1571}
1572
1573#[inline]
1579pub fn read_v2_msg<M: Message, R: Read>(
1580 read: &mut PeekReader<R>,
1581) -> Result<(MavHeader, M), MessageReadError> {
1582 read_v2_msg_inner(read, None)
1583}
1584
1585#[cfg(feature = "signing")]
1591#[inline]
1592pub fn read_v2_msg_signed<M: Message, R: Read>(
1593 read: &mut PeekReader<R>,
1594 signing_data: Option<&SigningData>,
1595) -> Result<(MavHeader, M), MessageReadError> {
1596 read_v2_msg_inner(read, signing_data)
1597}
1598
1599fn read_v2_msg_inner<M: Message, R: Read>(
1600 read: &mut PeekReader<R>,
1601 signing_data: Option<&SigningData>,
1602) -> Result<(MavHeader, M), MessageReadError> {
1603 let message = read_v2_raw_message_inner::<M, _>(read, signing_data)?;
1604
1605 Ok((
1606 MavHeader {
1607 sequence: message.sequence(),
1608 system_id: message.system_id(),
1609 component_id: message.component_id(),
1610 },
1611 M::parse(MavlinkVersion::V2, message.message_id(), message.payload())?,
1612 ))
1613}
1614
1615#[cfg(feature = "tokio-1")]
1621pub async fn read_v2_msg_async<M: Message, R: tokio::io::AsyncRead + Unpin>(
1622 read: &mut AsyncPeekReader<R>,
1623) -> Result<(MavHeader, M), MessageReadError> {
1624 read_v2_msg_async_inner(read, None).await
1625}
1626
1627#[cfg(all(feature = "tokio-1", feature = "signing"))]
1633pub async fn read_v2_msg_async_signed<M: Message, R: tokio::io::AsyncRead + Unpin>(
1634 read: &mut AsyncPeekReader<R>,
1635 signing_data: Option<&SigningData>,
1636) -> Result<(MavHeader, M), MessageReadError> {
1637 read_v2_msg_async_inner(read, signing_data).await
1638}
1639
1640#[cfg(feature = "tokio-1")]
1641async fn read_v2_msg_async_inner<M: Message, R: tokio::io::AsyncRead + Unpin>(
1642 read: &mut AsyncPeekReader<R>,
1643 signing_data: Option<&SigningData>,
1644) -> Result<(MavHeader, M), MessageReadError> {
1645 let message = read_v2_raw_message_async_inner::<M, _>(read, signing_data).await?;
1646
1647 Ok((
1648 MavHeader {
1649 sequence: message.sequence(),
1650 system_id: message.system_id(),
1651 component_id: message.component_id(),
1652 },
1653 M::parse(MavlinkVersion::V2, message.message_id(), message.payload())?,
1654 ))
1655}
1656
1657#[cfg(feature = "embedded")]
1662pub async fn read_v2_msg_async<M: Message, R: embedded_io_async::Read>(
1663 r: &mut R,
1664) -> Result<(MavHeader, M), MessageReadError> {
1665 let message = read_v2_raw_message_async::<M>(r).await?;
1666
1667 Ok((
1668 MavHeader {
1669 sequence: message.sequence(),
1670 system_id: message.system_id(),
1671 component_id: message.component_id(),
1672 },
1673 M::parse(
1674 MavlinkVersion::V2,
1675 u32::from(message.message_id()),
1676 message.payload(),
1677 )?,
1678 ))
1679}
1680
1681pub enum MAVLinkMessageRaw {
1683 V1(MAVLinkV1MessageRaw),
1684 V2(MAVLinkV2MessageRaw),
1685}
1686
1687impl MAVLinkMessageRaw {
1688 pub fn payload(&self) -> &[u8] {
1689 match self {
1690 Self::V1(msg) => msg.payload(),
1691 Self::V2(msg) => msg.payload(),
1692 }
1693 }
1694 pub fn sequence(&self) -> u8 {
1695 match self {
1696 Self::V1(msg) => msg.sequence(),
1697 Self::V2(msg) => msg.sequence(),
1698 }
1699 }
1700 pub fn system_id(&self) -> u8 {
1701 match self {
1702 Self::V1(msg) => msg.system_id(),
1703 Self::V2(msg) => msg.system_id(),
1704 }
1705 }
1706 pub fn component_id(&self) -> u8 {
1707 match self {
1708 Self::V1(msg) => msg.component_id(),
1709 Self::V2(msg) => msg.component_id(),
1710 }
1711 }
1712 pub fn message_id(&self) -> u32 {
1713 match self {
1714 Self::V1(msg) => u32::from(msg.message_id()),
1715 Self::V2(msg) => msg.message_id(),
1716 }
1717 }
1718 pub fn version(&self) -> MavlinkVersion {
1719 match self {
1720 Self::V1(_) => MavlinkVersion::V1,
1721 Self::V2(_) => MavlinkVersion::V2,
1722 }
1723 }
1724}
1725
1726#[inline]
1732pub fn read_any_raw_message<M: Message, R: Read>(
1733 reader: &mut PeekReader<R>,
1734) -> Result<MAVLinkMessageRaw, MessageReadError> {
1735 read_any_raw_message_inner::<M, R>(reader, None)
1736}
1737
1738#[cfg(feature = "signing")]
1744#[inline]
1745pub fn read_any_raw_message_signed<M: Message, R: Read>(
1746 reader: &mut PeekReader<R>,
1747 signing_data: Option<&SigningData>,
1748) -> Result<MAVLinkMessageRaw, MessageReadError> {
1749 read_any_raw_message_inner::<M, R>(reader, signing_data)
1750}
1751
1752#[allow(unused_variables)]
1753fn read_any_raw_message_inner<M: Message, R: Read>(
1754 reader: &mut PeekReader<R>,
1755 signing_data: Option<&SigningData>,
1756) -> Result<MAVLinkMessageRaw, MessageReadError> {
1757 loop {
1758 let version = loop {
1760 let byte = reader.peek_exact(1)?[0];
1761 if byte == MAV_STX {
1762 break MavlinkVersion::V1;
1763 }
1764 if byte == MAV_STX_V2 {
1765 break MavlinkVersion::V2;
1766 }
1767 reader.consume(1);
1768 };
1769 match version {
1770 MavlinkVersion::V1 => {
1771 if let Some(message) = try_decode_v1::<M, _>(reader)? {
1772 #[cfg(feature = "signing")]
1774 if let Some(signing) = signing_data {
1775 if signing.config.allow_unsigned {
1776 return Ok(MAVLinkMessageRaw::V1(message));
1777 }
1778 } else {
1779 return Ok(MAVLinkMessageRaw::V1(message));
1780 }
1781 #[cfg(not(feature = "signing"))]
1782 return Ok(MAVLinkMessageRaw::V1(message));
1783 }
1784
1785 reader.consume(1);
1786 }
1787 MavlinkVersion::V2 => {
1788 if let Some(message) = try_decode_v2::<M, _>(reader, signing_data)? {
1789 return Ok(MAVLinkMessageRaw::V2(message));
1790 }
1791 }
1792 }
1793 }
1794}
1795
1796#[cfg(feature = "tokio-1")]
1802pub async fn read_any_raw_message_async<M: Message, R: tokio::io::AsyncRead + Unpin>(
1803 reader: &mut AsyncPeekReader<R>,
1804) -> Result<MAVLinkMessageRaw, MessageReadError> {
1805 read_any_raw_message_async_inner::<M, R>(reader, None).await
1806}
1807
1808#[cfg(all(feature = "tokio-1", feature = "signing"))]
1816pub async fn read_any_raw_message_async_signed<M: Message, R: tokio::io::AsyncRead + Unpin>(
1817 reader: &mut AsyncPeekReader<R>,
1818 signing_data: Option<&SigningData>,
1819) -> Result<MAVLinkMessageRaw, MessageReadError> {
1820 read_any_raw_message_async_inner::<M, R>(reader, signing_data).await
1821}
1822
1823#[cfg(feature = "tokio-1")]
1824#[allow(unused_variables)]
1825async fn read_any_raw_message_async_inner<M: Message, R: tokio::io::AsyncRead + Unpin>(
1826 reader: &mut AsyncPeekReader<R>,
1827 signing_data: Option<&SigningData>,
1828) -> Result<MAVLinkMessageRaw, MessageReadError> {
1829 loop {
1830 let version = loop {
1832 let read = reader.read_u8().await?;
1833 if read == MAV_STX {
1834 break MavlinkVersion::V1;
1835 }
1836 if read == MAV_STX_V2 {
1837 break MavlinkVersion::V2;
1838 }
1839 };
1840
1841 match version {
1842 MavlinkVersion::V1 => {
1843 if let Some(message) = try_decode_v1_async::<M, _>(reader).await? {
1844 #[cfg(feature = "signing")]
1846 if let Some(signing) = signing_data {
1847 if signing.config.allow_unsigned {
1848 return Ok(MAVLinkMessageRaw::V1(message));
1849 }
1850 } else {
1851 return Ok(MAVLinkMessageRaw::V1(message));
1852 }
1853 #[cfg(not(feature = "signing"))]
1854 return Ok(MAVLinkMessageRaw::V1(message));
1855 }
1856 }
1857 MavlinkVersion::V2 => {
1858 if let Some(message) = try_decode_v2_async::<M, _>(reader, signing_data).await? {
1859 return Ok(MAVLinkMessageRaw::V2(message));
1860 }
1861 }
1862 }
1863 }
1864}
1865
1866#[inline]
1872pub fn read_any_msg<M: Message, R: Read>(
1873 read: &mut PeekReader<R>,
1874) -> Result<(MavHeader, M), MessageReadError> {
1875 read_any_msg_inner(read, None)
1876}
1877
1878#[cfg(feature = "signing")]
1886#[inline]
1887pub fn read_any_msg_signed<M: Message, R: Read>(
1888 read: &mut PeekReader<R>,
1889 signing_data: Option<&SigningData>,
1890) -> Result<(MavHeader, M), MessageReadError> {
1891 read_any_msg_inner(read, signing_data)
1892}
1893
1894fn read_any_msg_inner<M: Message, R: Read>(
1895 read: &mut PeekReader<R>,
1896 signing_data: Option<&SigningData>,
1897) -> Result<(MavHeader, M), MessageReadError> {
1898 let message = read_any_raw_message_inner::<M, _>(read, signing_data)?;
1899 Ok((
1900 MavHeader {
1901 sequence: message.sequence(),
1902 system_id: message.system_id(),
1903 component_id: message.component_id(),
1904 },
1905 M::parse(message.version(), message.message_id(), message.payload())?,
1906 ))
1907}
1908
1909#[cfg(feature = "tokio-1")]
1915pub async fn read_any_msg_async<M: Message, R: tokio::io::AsyncRead + Unpin>(
1916 read: &mut AsyncPeekReader<R>,
1917) -> Result<(MavHeader, M), MessageReadError> {
1918 read_any_msg_async_inner(read, None).await
1919}
1920
1921#[cfg(all(feature = "tokio-1", feature = "signing"))]
1929#[inline]
1930pub async fn read_any_msg_async_signed<M: Message, R: tokio::io::AsyncRead + Unpin>(
1931 read: &mut AsyncPeekReader<R>,
1932 signing_data: Option<&SigningData>,
1933) -> Result<(MavHeader, M), MessageReadError> {
1934 read_any_msg_async_inner(read, signing_data).await
1935}
1936
1937#[cfg(feature = "tokio-1")]
1938async fn read_any_msg_async_inner<M: Message, R: tokio::io::AsyncRead + Unpin>(
1939 read: &mut AsyncPeekReader<R>,
1940 signing_data: Option<&SigningData>,
1941) -> Result<(MavHeader, M), MessageReadError> {
1942 let message = read_any_raw_message_async_inner::<M, _>(read, signing_data).await?;
1943
1944 Ok((
1945 MavHeader {
1946 sequence: message.sequence(),
1947 system_id: message.system_id(),
1948 component_id: message.component_id(),
1949 },
1950 M::parse(message.version(), message.message_id(), message.payload())?,
1951 ))
1952}
1953
1954pub fn write_versioned_msg<M: Message, W: Write>(
1960 w: &mut W,
1961 version: MavlinkVersion,
1962 header: MavHeader,
1963 data: &M,
1964) -> Result<usize, MessageWriteError> {
1965 match version {
1966 MavlinkVersion::V2 => write_v2_msg(w, header, data),
1967 MavlinkVersion::V1 => write_v1_msg(w, header, data),
1968 }
1969}
1970
1971#[cfg(feature = "signing")]
1979pub fn write_versioned_msg_signed<M: Message, W: Write>(
1980 w: &mut W,
1981 version: MavlinkVersion,
1982 header: MavHeader,
1983 data: &M,
1984 signing_data: Option<&SigningData>,
1985) -> Result<usize, MessageWriteError> {
1986 match version {
1987 MavlinkVersion::V2 => write_v2_msg_signed(w, header, data, signing_data),
1988 MavlinkVersion::V1 => write_v1_msg(w, header, data),
1989 }
1990}
1991
1992#[cfg(feature = "tokio-1")]
1998pub async fn write_versioned_msg_async<M: Message, W: AsyncWrite + Unpin>(
1999 w: &mut W,
2000 version: MavlinkVersion,
2001 header: MavHeader,
2002 data: &M,
2003) -> Result<usize, MessageWriteError> {
2004 match version {
2005 MavlinkVersion::V2 => write_v2_msg_async(w, header, data).await,
2006 MavlinkVersion::V1 => write_v1_msg_async(w, header, data).await,
2007 }
2008}
2009
2010#[cfg(all(feature = "tokio-1", feature = "signing"))]
2018pub async fn write_versioned_msg_async_signed<M: Message, W: AsyncWrite + Unpin>(
2019 w: &mut W,
2020 version: MavlinkVersion,
2021 header: MavHeader,
2022 data: &M,
2023 signing_data: Option<&SigningData>,
2024) -> Result<usize, MessageWriteError> {
2025 match version {
2026 MavlinkVersion::V2 => write_v2_msg_async_signed(w, header, data, signing_data).await,
2027 MavlinkVersion::V1 => write_v1_msg_async(w, header, data).await,
2028 }
2029}
2030
2031#[cfg(feature = "embedded")]
2036pub async fn write_versioned_msg_async<M: Message>(
2037 w: &mut impl embedded_io_async::Write,
2038 version: MavlinkVersion,
2039 header: MavHeader,
2040 data: &M,
2041) -> Result<usize, MessageWriteError> {
2042 match version {
2043 MavlinkVersion::V2 => write_v2_msg_async(w, header, data).await,
2044 MavlinkVersion::V1 => write_v1_msg_async(w, header, data).await,
2045 }
2046}
2047
2048pub fn write_v2_msg<M: Message, W: Write>(
2054 w: &mut W,
2055 header: MavHeader,
2056 data: &M,
2057) -> Result<usize, MessageWriteError> {
2058 let mut message_raw = MAVLinkV2MessageRaw::new();
2059 message_raw.serialize_message(header, data);
2060
2061 let payload_length: usize = message_raw.payload_length().into();
2062 let len = 1 + MAVLinkV2MessageRaw::HEADER_SIZE + payload_length + 2;
2063
2064 w.write_all(&message_raw.0[..len])?;
2065
2066 Ok(len)
2067}
2068
2069#[cfg(feature = "signing")]
2075pub fn write_v2_msg_signed<M: Message, W: Write>(
2076 w: &mut W,
2077 header: MavHeader,
2078 data: &M,
2079 signing_data: Option<&SigningData>,
2080) -> Result<usize, MessageWriteError> {
2081 let mut message_raw = MAVLinkV2MessageRaw::new();
2082
2083 let signature_len = if let Some(signing_data) = signing_data {
2084 if signing_data.config.sign_outgoing {
2085 message_raw.serialize_message_for_signing(header, data);
2086 signing_data.sign_message(&mut message_raw);
2087 MAVLinkV2MessageRaw::SIGNATURE_SIZE
2088 } else {
2089 message_raw.serialize_message(header, data);
2090 0
2091 }
2092 } else {
2093 message_raw.serialize_message(header, data);
2094 0
2095 };
2096
2097 let payload_length: usize = message_raw.payload_length().into();
2098 let len = 1 + MAVLinkV2MessageRaw::HEADER_SIZE + payload_length + 2 + signature_len;
2099
2100 w.write_all(&message_raw.0[..len])?;
2101
2102 Ok(len)
2103}
2104
2105#[cfg(feature = "tokio-1")]
2111pub async fn write_v2_msg_async<M: Message, W: AsyncWrite + Unpin>(
2112 w: &mut W,
2113 header: MavHeader,
2114 data: &M,
2115) -> Result<usize, MessageWriteError> {
2116 let mut message_raw = MAVLinkV2MessageRaw::new();
2117 message_raw.serialize_message(header, data);
2118
2119 let payload_length: usize = message_raw.payload_length().into();
2120 let len = 1 + MAVLinkV2MessageRaw::HEADER_SIZE + payload_length + 2;
2121
2122 w.write_all(&message_raw.0[..len]).await?;
2123
2124 Ok(len)
2125}
2126
2127#[cfg(feature = "signing")]
2133#[cfg(feature = "tokio-1")]
2134pub async fn write_v2_msg_async_signed<M: Message, W: AsyncWrite + Unpin>(
2135 w: &mut W,
2136 header: MavHeader,
2137 data: &M,
2138 signing_data: Option<&SigningData>,
2139) -> Result<usize, MessageWriteError> {
2140 let mut message_raw = MAVLinkV2MessageRaw::new();
2141
2142 let signature_len = if let Some(signing_data) = signing_data {
2143 if signing_data.config.sign_outgoing {
2144 message_raw.serialize_message_for_signing(header, data);
2145 signing_data.sign_message(&mut message_raw);
2146 MAVLinkV2MessageRaw::SIGNATURE_SIZE
2147 } else {
2148 message_raw.serialize_message(header, data);
2149 0
2150 }
2151 } else {
2152 message_raw.serialize_message(header, data);
2153 0
2154 };
2155
2156 let payload_length: usize = message_raw.payload_length().into();
2157 let len = 1 + MAVLinkV2MessageRaw::HEADER_SIZE + payload_length + 2 + signature_len;
2158
2159 w.write_all(&message_raw.0[..len]).await?;
2160
2161 Ok(len)
2162}
2163
2164#[cfg(feature = "embedded")]
2173pub async fn write_v2_msg_async<M: Message>(
2174 w: &mut impl embedded_io_async::Write,
2175 header: MavHeader,
2176 data: &M,
2177) -> Result<usize, MessageWriteError> {
2178 let mut message_raw = MAVLinkV2MessageRaw::new();
2179 message_raw.serialize_message(header, data);
2180
2181 let payload_length: usize = message_raw.payload_length().into();
2182 let len = 1 + MAVLinkV2MessageRaw::HEADER_SIZE + payload_length + 2;
2183
2184 w.write_all(&message_raw.0[..len])
2185 .await
2186 .map_err(|_| MessageWriteError::Io)?;
2187
2188 Ok(len)
2189}
2190
2191pub fn write_v1_msg<M: Message, W: Write>(
2197 w: &mut W,
2198 header: MavHeader,
2199 data: &M,
2200) -> Result<usize, MessageWriteError> {
2201 if data.message_id() > u8::MAX.into() {
2202 return Err(MessageWriteError::MAVLink2Only);
2203 }
2204 let mut message_raw = MAVLinkV1MessageRaw::new();
2205 message_raw.serialize_message(header, data);
2206
2207 let payload_length: usize = message_raw.payload_length().into();
2208 let len = 1 + MAVLinkV1MessageRaw::HEADER_SIZE + payload_length + 2;
2209
2210 w.write_all(&message_raw.0[..len])?;
2211
2212 Ok(len)
2213}
2214
2215#[cfg(feature = "tokio-1")]
2221pub async fn write_v1_msg_async<M: Message, W: AsyncWrite + Unpin>(
2222 w: &mut W,
2223 header: MavHeader,
2224 data: &M,
2225) -> Result<usize, MessageWriteError> {
2226 if data.message_id() > u8::MAX.into() {
2227 return Err(MessageWriteError::MAVLink2Only);
2228 }
2229 let mut message_raw = MAVLinkV1MessageRaw::new();
2230 message_raw.serialize_message(header, data);
2231
2232 let payload_length: usize = message_raw.payload_length().into();
2233 let len = 1 + MAVLinkV1MessageRaw::HEADER_SIZE + payload_length + 2;
2234
2235 w.write_all(&message_raw.0[..len]).await?;
2236
2237 Ok(len)
2238}
2239
2240#[cfg(feature = "embedded")]
2245pub async fn write_v1_msg_async<M: Message>(
2246 w: &mut impl embedded_io_async::Write,
2247 header: MavHeader,
2248 data: &M,
2249) -> Result<usize, MessageWriteError> {
2250 if data.message_id() > u8::MAX.into() {
2251 return Err(MessageWriteError::MAVLink2Only);
2252 }
2253 let mut message_raw = MAVLinkV1MessageRaw::new();
2254 message_raw.serialize_message(header, data);
2255
2256 let payload_length: usize = message_raw.payload_length().into();
2257 let len = 1 + MAVLinkV1MessageRaw::HEADER_SIZE + payload_length + 2;
2258
2259 w.write_all(&message_raw.0[..len])
2260 .await
2261 .map_err(|_| MessageWriteError::Io)?;
2262
2263 Ok(len)
2264}
2265
2266#[deprecated = "use read_versioned_raw_message instead"]
2267pub fn read_raw_versioned_msg<M: Message, R: Read>(
2268 r: &mut PeekReader<R>,
2269 version: ReadVersion,
2270) -> Result<MAVLinkMessageRaw, MessageReadError> {
2271 read_versioned_raw_message::<M, _>(r, version)
2272}
2273
2274#[cfg(feature = "tokio-1")]
2275#[deprecated = "use read_versioned_raw_message_async instead"]
2276pub async fn read_raw_versioned_msg_async<M: Message, R: tokio::io::AsyncRead + Unpin>(
2277 r: &mut AsyncPeekReader<R>,
2278 version: ReadVersion,
2279) -> Result<MAVLinkMessageRaw, MessageReadError> {
2280 read_versioned_raw_message_async::<M, _>(r, version).await
2281}
2282
2283#[cfg(feature = "signing")]
2284#[deprecated = "use read_versioned_raw_message_signed instead"]
2285pub fn read_raw_versioned_msg_signed<M: Message, R: Read>(
2286 r: &mut PeekReader<R>,
2287 version: ReadVersion,
2288 signing_data: Option<&SigningData>,
2289) -> Result<MAVLinkMessageRaw, MessageReadError> {
2290 read_versioned_raw_message_signed::<M, _>(r, version, signing_data)
2291}
2292
2293#[cfg(all(feature = "tokio-1", feature = "signing"))]
2294#[deprecated = "use read_versioned_raw_message_async_signed instead"]
2295pub async fn read_raw_versioned_msg_async_signed<M: Message, R: tokio::io::AsyncRead + Unpin>(
2296 r: &mut AsyncPeekReader<R>,
2297 version: ReadVersion,
2298 signing_data: Option<&SigningData>,
2299) -> Result<MAVLinkMessageRaw, MessageReadError> {
2300 read_versioned_raw_message_async_signed::<M, _>(r, version, signing_data).await
2301}