mavlink_core/async_connection/
file.rs1use 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}