Skip to main content

mavlink_core/connection/file/
async.rs

1//! Async File MAVLINK connection
2use core::ops::DerefMut;
3use std::io;
4use std::path::PathBuf;
5
6use crate::connection::file::config::FileConfig;
7use crate::connection::{AsyncConnectable, AsyncMavConnection};
8use crate::connection_shared::{ConnectionState, read_message_async, read_raw_message_async};
9use crate::error::{MessageReadError, MessageWriteError};
10use crate::{
11    MAVLinkMessageRaw, MavHeader, MavlinkVersion, Message, async_peek_reader::AsyncPeekReader,
12};
13
14use async_trait::async_trait;
15use futures::lock::Mutex;
16use tokio::fs::File;
17
18#[cfg(feature = "mav2-message-signing")]
19use crate::SigningConfig;
20
21pub async fn open(file_path: &PathBuf) -> io::Result<AsyncFileConnection> {
22    let file = File::open(file_path).await?;
23    Ok(AsyncFileConnection {
24        file: Mutex::new(AsyncPeekReader::new(file)),
25        state: ConnectionState::new(),
26    })
27}
28
29pub struct AsyncFileConnection {
30    file: Mutex<AsyncPeekReader<File>>,
31    state: ConnectionState,
32}
33
34#[async_trait::async_trait]
35impl<M: Message + Sync + Send> AsyncMavConnection<M> for AsyncFileConnection {
36    async fn recv_raw(&self) -> Result<MAVLinkMessageRaw, crate::error::MessageReadError> {
37        let mut file = self.file.lock().await;
38        loop {
39            let result = read_raw_message_async::<M, _>(file.deref_mut(), &self.state).await;
40            match result {
41                ok @ Ok(..) => {
42                    return ok;
43                }
44                Err(MessageReadError::Io(e)) if e.kind() == io::ErrorKind::UnexpectedEof => {
45                    return Err(MessageReadError::Io(e));
46                }
47                _ => {}
48            }
49        }
50    }
51
52    async fn recv(&self) -> Result<(MavHeader, M), crate::error::MessageReadError> {
53        let mut file = self.file.lock().await;
54        loop {
55            let result = read_message_async::<M, _>(file.deref_mut(), &self.state).await;
56            match result {
57                ok @ Ok(..) => {
58                    return ok;
59                }
60                Err(MessageReadError::Io(e)) if e.kind() == io::ErrorKind::UnexpectedEof => {
61                    return Err(MessageReadError::Io(e));
62                }
63                _ => {}
64            }
65        }
66    }
67
68    async fn try_recv(&self) -> Result<(MavHeader, M), crate::error::MessageReadError> {
69        let mut file = self.file.lock().await;
70        read_message_async::<M, _>(file.deref_mut(), &self.state).await
71    }
72
73    async fn send(&self, _header: &MavHeader, _data: &M) -> Result<usize, MessageWriteError> {
74        Ok(0)
75    }
76
77    fn set_protocol_version(&mut self, version: MavlinkVersion) {
78        self.state.set_protocol_version(version);
79    }
80
81    fn protocol_version(&self) -> MavlinkVersion {
82        self.state.protocol_version()
83    }
84
85    fn set_allow_recv_any_version(&mut self, allow: bool) {
86        self.state.set_allow_recv_any_version(allow);
87    }
88
89    fn allow_recv_any_version(&self) -> bool {
90        self.state.allow_recv_any_version()
91    }
92
93    #[cfg(feature = "mav2-message-signing")]
94    fn setup_signing(&mut self, signing_data: Option<SigningConfig>) {
95        self.state.setup_signing(signing_data);
96    }
97}
98
99#[async_trait]
100impl AsyncConnectable for FileConfig {
101    async fn connect_async<M>(&self) -> io::Result<Box<dyn AsyncMavConnection<M> + Sync + Send>>
102    where
103        M: Message + Sync + Send,
104    {
105        Ok(Box::new(open(&self.address).await?))
106    }
107}