use crate::error::{ChecksumError, VersionError};
use crate::protocol::{
Checksum, CrcExtra, MessageId, Payload, PayloadLength, Sequence, Signature, SystemId,
};
use crate::prelude::*;
#[derive(Clone, Debug)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum MavFrame {
V1(Frame<V1>),
V2(Frame<V2>),
}
impl MavFrame {
pub fn new<V: MaybeVersioned>(frame: Frame<V>) -> Self {
match frame.version() {
MavLinkVersion::V1 => MavFrame::V1(frame.try_into_versioned::<V1>().unwrap()),
MavLinkVersion::V2 => MavFrame::V2(frame.try_into_versioned::<V2>().unwrap()),
}
}
#[inline]
pub fn version(&self) -> MavLinkVersion {
match self {
MavFrame::V1(_) => MavLinkVersion::V1,
MavFrame::V2(_) => MavLinkVersion::V2,
}
}
#[inline]
pub fn payload_length(&self) -> PayloadLength {
match self {
MavFrame::V1(frame) => frame.payload_length(),
MavFrame::V2(frame) => frame.payload_length(),
}
}
#[inline]
pub fn sequence(&self) -> Sequence {
match self {
MavFrame::V1(frame) => frame.sequence(),
MavFrame::V2(frame) => frame.sequence(),
}
}
#[inline]
pub fn system_id(&self) -> SystemId {
match self {
MavFrame::V1(frame) => frame.system_id(),
MavFrame::V2(frame) => frame.system_id(),
}
}
#[inline]
pub fn component_id(&self) -> SystemId {
match self {
MavFrame::V1(frame) => frame.component_id(),
MavFrame::V2(frame) => frame.component_id(),
}
}
#[inline]
pub fn message_id(&self) -> MessageId {
match self {
MavFrame::V1(frame) => frame.message_id(),
MavFrame::V2(frame) => frame.message_id(),
}
}
#[inline]
pub fn payload(&self) -> &Payload {
match self {
MavFrame::V1(frame) => frame.payload(),
MavFrame::V2(frame) => frame.payload(),
}
}
#[inline]
pub fn checksum(&self) -> Checksum {
match self {
MavFrame::V1(frame) => frame.checksum(),
MavFrame::V2(frame) => frame.checksum(),
}
}
#[inline]
pub fn is_signed(&self) -> bool {
match self {
MavFrame::V1(_) => false,
MavFrame::V2(frame) => frame.is_signed(),
}
}
#[inline]
pub fn signature(&self) -> Option<&Signature> {
match self {
MavFrame::V1(_) => None,
MavFrame::V2(frame) => frame.signature(),
}
}
#[inline]
pub fn remove_signature(&mut self) {
match self {
MavFrame::V1(_) => (),
MavFrame::V2(frame) => frame.remove_signature(),
}
}
#[inline]
pub fn body_length(&self) -> usize {
match self {
MavFrame::V1(frame) => frame.body_length(),
MavFrame::V2(frame) => frame.body_length(),
}
}
#[inline]
pub fn calculate_crc(&self, crc_extra: CrcExtra) -> Checksum {
match self {
MavFrame::V1(frame) => frame.calculate_crc(crc_extra),
MavFrame::V2(frame) => frame.calculate_crc(crc_extra),
}
}
#[inline]
pub fn validate_checksum<D: Dialect>(&self) -> Result<()> {
match self {
MavFrame::V1(frame) => frame.validate_checksum::<D>(),
MavFrame::V2(frame) => frame.validate_checksum::<D>(),
}
}
#[inline]
pub fn validate_checksum_with_crc_extra(
&self,
crc_extra: CrcExtra,
) -> core::result::Result<(), ChecksumError> {
match self {
MavFrame::V1(frame) => frame.validate_checksum_with_crc_extra(crc_extra),
MavFrame::V2(frame) => frame.validate_checksum_with_crc_extra(crc_extra),
}
}
#[inline]
pub fn matches_version<Version: Versioned>(
&self,
#[allow(unused_variables)] version: Version,
) -> bool {
Version::matches(self.version())
}
#[inline]
pub fn decode<D: Dialect>(&self) -> Result<D> {
match self {
MavFrame::V1(frame) => frame.decode(),
MavFrame::V2(frame) => frame.decode(),
}
}
pub fn into_versionless(self) -> Frame<Versionless> {
match self {
MavFrame::V1(frame) => frame.into_versionless(),
MavFrame::V2(frame) => frame.into_versionless(),
}
}
pub fn try_into_versioned<V: MaybeVersioned>(
self,
) -> core::result::Result<Frame<V>, VersionError> {
match self {
MavFrame::V1(frame) => frame.try_into_versioned::<V>(),
MavFrame::V2(frame) => frame.try_into_versioned::<V>(),
}
}
}
#[cfg(feature = "unsafe")]
impl<V: MaybeVersioned> TryUpdateFrom<&MavFrame> for Frame<V> {
type Error = VersionError;
fn check_try_update_from(&self, value: &&MavFrame) -> std::result::Result<(), Self::Error> {
V::expect(value.version())
}
unsafe fn update_from_unchecked(&mut self, value: &MavFrame) {
match value {
MavFrame::V1(inner) => {
self.header.payload_length = inner.header.payload_length;
self.header.sequence = inner.header.sequence;
self.header.system_id = inner.header.system_id;
self.header.component_id = inner.header.component_id;
self.header.message_id = inner.header.message_id;
self.payload = inner.payload.clone();
self.checksum = inner.checksum;
}
MavFrame::V2(inner) => {
self.header.payload_length = inner.header.payload_length;
self.header.sequence = inner.header.sequence;
self.header.system_id = inner.header.system_id;
self.header.component_id = inner.header.component_id;
self.header.message_id = inner.header.message_id;
self.payload = inner.payload.clone();
self.checksum = inner.checksum;
self.payload = inner.payload.clone();
self.checksum = inner.checksum;
self.signature = inner.signature.clone();
}
}
}
}
impl<V: MaybeVersioned> TryFrom<MavFrame> for Frame<V> {
type Error = VersionError;
fn try_from(value: MavFrame) -> core::result::Result<Self, VersionError> {
value.try_into_versioned()
}
}
impl<V: MaybeVersioned> From<Frame<V>> for MavFrame {
fn from(value: Frame<V>) -> Self {
Self::new(value)
}
}