mavlink_core/async_connection/
file.rs

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