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    async fn send_raw(&self, _data: &MAVLinkMessageRaw) -> Result<usize, MessageWriteError> {
78        Ok(0)
79    }
80
81    fn set_protocol_version(&mut self, version: MavlinkVersion) {
82        self.state.set_protocol_version(version);
83    }
84
85    fn protocol_version(&self) -> MavlinkVersion {
86        self.state.protocol_version()
87    }
88
89    fn set_allow_recv_any_version(&mut self, allow: bool) {
90        self.state.set_allow_recv_any_version(allow);
91    }
92
93    fn allow_recv_any_version(&self) -> bool {
94        self.state.allow_recv_any_version()
95    }
96
97    #[cfg(feature = "mav2-message-signing")]
98    fn setup_signing(&mut self, signing_data: Option<SigningConfig>) {
99        self.state.setup_signing(signing_data);
100    }
101}
102
103#[async_trait]
104impl AsyncConnectable for FileConfig {
105    async fn connect_async<M>(&self) -> io::Result<Box<dyn AsyncMavConnection<M> + Sync + Send>>
106    where
107        M: Message + Sync + Send,
108    {
109        Ok(Box::new(open(&self.address).await?))
110    }
111}