use core::fmt::Debug;
use crate::consts::{STX_V1, STX_V2};
use crate::protocol::MavLinkVersion;
use crate::utils::sealed::Sealed;
#[cfg(doc)]
use crate::protocol::Frame;
pub trait MaybeVersioned: IsMagicByte + Clone + Debug + Sync + Send + Sealed + 'static {
#[inline]
fn expect(#[allow(unused_variables)] version: MavLinkVersion) -> Result<(), VersionError> {
Ok(())
}
#[inline]
fn matches(#[allow(unused_variables)] version: MavLinkVersion) -> bool {
true
}
}
#[derive(Clone, Copy, Debug, Default)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Versionless;
impl Sealed for Versionless {}
impl IsMagicByte for Versionless {}
#[cfg(feature = "specta")]
impl Sealed for () {}
#[cfg(feature = "specta")]
impl IsMagicByte for () {}
#[cfg(feature = "specta")]
impl MaybeVersioned for () {}
impl MaybeVersioned for Versionless {}
pub trait Versioned: MaybeVersioned {
fn version() -> MavLinkVersion;
fn ver(&self) -> MavLinkVersion;
fn v() -> Self;
}
#[derive(Clone, Copy, Debug, Default)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct V1;
impl Sealed for V1 {}
impl IsMagicByte for V1 {
#[inline(always)]
fn is_magic_byte(byte: u8) -> bool {
byte == STX_V1
}
}
impl MaybeVersioned for V1 {
#[inline]
fn expect(version: MavLinkVersion) -> Result<(), VersionError> {
match_error(MavLinkVersion::V1, version)
}
#[inline(always)]
fn matches(version: MavLinkVersion) -> bool {
version == MavLinkVersion::V1
}
}
impl Versioned for V1 {
#[inline(always)]
fn version() -> MavLinkVersion {
MavLinkVersion::V1
}
fn ver(&self) -> MavLinkVersion {
MavLinkVersion::V1
}
#[inline(always)]
fn v() -> Self {
V1
}
}
#[derive(Clone, Copy, Debug, Default)]
#[cfg_attr(feature = "specta", derive(specta::Type))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct V2;
impl Sealed for V2 {}
impl IsMagicByte for V2 {
#[inline(always)]
fn is_magic_byte(byte: u8) -> bool {
byte == STX_V2
}
}
impl MaybeVersioned for V2 {
#[inline]
fn expect(version: MavLinkVersion) -> Result<(), VersionError> {
match_error(MavLinkVersion::V2, version)
}
#[inline(always)]
fn matches(version: MavLinkVersion) -> bool {
version == MavLinkVersion::V2
}
}
impl Versioned for V2 {
#[inline(always)]
fn version() -> MavLinkVersion {
MavLinkVersion::V2
}
#[inline(always)]
fn ver(&self) -> MavLinkVersion {
MavLinkVersion::V2
}
#[inline(always)]
fn v() -> Self {
V2
}
}
#[inline]
fn match_error(expected: MavLinkVersion, actual: MavLinkVersion) -> Result<(), VersionError> {
if expected != actual {
return Err(VersionError { expected, actual });
}
Ok(())
}
mod is_magic_byte {
use crate::protocol::MavSTX;
pub trait IsMagicByte {
#[inline]
fn is_magic_byte(byte: u8) -> bool {
MavSTX::is_magic_byte(byte)
}
}
}
use crate::error::VersionError;
pub(crate) use is_magic_byte::IsMagicByte;
#[cfg(test)]
mod version_marker_tests {
use super::*;
#[test]
fn version_matching() {
V1::expect(MavLinkVersion::V1).unwrap();
V2::expect(MavLinkVersion::V2).unwrap();
Versionless::expect(MavLinkVersion::V1).unwrap();
Versionless::expect(MavLinkVersion::V2).unwrap();
assert!(Versionless::matches(MavLinkVersion::V1));
assert!(Versionless::matches(MavLinkVersion::V2));
assert!(V1::matches(MavLinkVersion::V1));
assert!(V2::matches(MavLinkVersion::V2));
assert!(!V1::matches(MavLinkVersion::V2));
assert!(!V2::matches(MavLinkVersion::V1));
fn expect_versioned<V: Versioned>(
_: V,
version: MavLinkVersion,
) -> Result<(), VersionError> {
V::expect(version)
}
expect_versioned(V1, MavLinkVersion::V1).unwrap();
expect_versioned(V2, MavLinkVersion::V2).unwrap();
assert!(expect_versioned(V1, MavLinkVersion::V2).is_err());
assert!(expect_versioned(V2, MavLinkVersion::V1).is_err());
}
}