Skip to main content

mavlink_core/async_connection/
file.rs

1//! Async File MAVLINK connection
2use core::ops::DerefMut;
3use std::io;
4use std::path::PathBuf;
5
6use super::{AsyncConnectable, AsyncMavConnection};
7use crate::connection::file::config::FileConfig;
8use crate::error::{MessageReadError, MessageWriteError};
9use crate::{
10    async_peek_reader::AsyncPeekReader, MAVLinkMessageRaw, MavHeader, MavlinkVersion, Message,
11    ReadVersion,
12};
13
14use async_trait::async_trait;
15use futures::lock::Mutex;
16use tokio::fs::File;
17
18#[cfg(not(feature = "mav2-message-signing"))]
19use crate::{read_versioned_msg_async, read_versioned_raw_message_async};
20
21#[cfg(feature = "mav2-message-signing")]
22use crate::{
23    read_versioned_msg_async_signed, read_versioned_raw_message_async_signed, SigningConfig,
24    SigningData,
25};
26
27pub async fn open(file_path: &PathBuf) -> io::Result<AsyncFileConnection> {
28    let file = File::open(file_path).await?;
29    Ok(AsyncFileConnection {
30        file: Mutex::new(AsyncPeekReader::new(file)),
31        protocol_version: MavlinkVersion::V2,
32        recv_any_version: false,
33        #[cfg(feature = "mav2-message-signing")]
34        signing_data: None,
35    })
36}
37
38pub struct AsyncFileConnection {
39    file: Mutex<AsyncPeekReader<File>>,
40    protocol_version: MavlinkVersion,
41    recv_any_version: bool,
42    #[cfg(feature = "mav2-message-signing")]
43    signing_data: Option<SigningData>,
44}
45
46#[async_trait::async_trait]
47impl<M: Message + Sync + Send> AsyncMavConnection<M> for AsyncFileConnection {
48    async fn recv_raw(&self) -> Result<MAVLinkMessageRaw, crate::error::MessageReadError> {
49        let mut file = self.file.lock().await;
50        let version = ReadVersion::from_async_conn_cfg::<_, M>(self);
51        loop {
52            #[cfg(not(feature = "mav2-message-signing"))]
53            let result = read_versioned_raw_message_async::<M, _>(file.deref_mut(), version).await;
54            #[cfg(feature = "mav2-message-signing")]
55            let result = read_versioned_raw_message_async_signed::<M, _>(
56                file.deref_mut(),
57                version,
58                self.signing_data.as_ref(),
59            )
60            .await;
61            match result {
62                ok @ Ok(..) => {
63                    return ok;
64                }
65                Err(MessageReadError::Io(e)) if e.kind() == io::ErrorKind::UnexpectedEof => {
66                    return Err(MessageReadError::Io(e));
67                }
68                _ => {}
69            }
70        }
71    }
72
73    async fn recv(&self) -> Result<(MavHeader, M), crate::error::MessageReadError> {
74        let mut file = self.file.lock().await;
75        let version = ReadVersion::from_async_conn_cfg::<_, M>(self);
76        loop {
77            #[cfg(not(feature = "mav2-message-signing"))]
78            let result = read_versioned_msg_async(file.deref_mut(), version).await;
79            #[cfg(feature = "mav2-message-signing")]
80            let result = read_versioned_msg_async_signed(
81                file.deref_mut(),
82                version,
83                self.signing_data.as_ref(),
84            )
85            .await;
86            match result {
87                ok @ Ok(..) => {
88                    return ok;
89                }
90                Err(MessageReadError::Io(e)) if e.kind() == io::ErrorKind::UnexpectedEof => {
91                    return Err(MessageReadError::Io(e));
92                }
93                _ => {}
94            }
95        }
96    }
97
98    async fn try_recv(&self) -> Result<(MavHeader, M), crate::error::MessageReadError> {
99        let mut file = self.file.lock().await;
100        let version = ReadVersion::from_async_conn_cfg::<_, M>(self);
101
102        #[cfg(not(feature = "mav2-message-signing"))]
103        let result = read_versioned_msg_async(file.deref_mut(), version).await;
104
105        #[cfg(feature = "mav2-message-signing")]
106        let result =
107            read_versioned_msg_async_signed(file.deref_mut(), version, self.signing_data.as_ref())
108                .await;
109
110        result
111    }
112
113    async fn send(&self, _header: &MavHeader, _data: &M) -> Result<usize, MessageWriteError> {
114        Ok(0)
115    }
116
117    fn set_protocol_version(&mut self, version: MavlinkVersion) {
118        self.protocol_version = version;
119    }
120
121    fn protocol_version(&self) -> MavlinkVersion {
122        self.protocol_version
123    }
124
125    fn set_allow_recv_any_version(&mut self, allow: bool) {
126        self.recv_any_version = allow;
127    }
128
129    fn allow_recv_any_version(&self) -> bool {
130        self.recv_any_version
131    }
132
133    #[cfg(feature = "mav2-message-signing")]
134    fn setup_signing(&mut self, signing_data: Option<SigningConfig>) {
135        self.signing_data = signing_data.map(SigningData::from_config);
136    }
137}
138
139#[async_trait]
140impl AsyncConnectable for FileConfig {
141    async fn connect_async<M>(&self) -> io::Result<Box<dyn AsyncMavConnection<M> + Sync + Send>>
142    where
143        M: Message + Sync + Send,
144    {
145        Ok(Box::new(open(&self.address).await?))
146    }
147}