1use crate::{
4 MAVLinkMessageRaw, MavHeader, MavlinkVersion, Message,
5 error::MessageReadError,
6 frame_decoder::{FrameDecoder, VersionFilter},
7 reader::{try_decode_message, try_decode_raw_message},
8 static_dialect::StaticDialect,
9};
10
11#[cfg(feature = "tokio")]
12use crate::{Dialect, SigningData};
13
14#[cfg(all(feature = "embedded", not(feature = "std")))]
15use embedded_io_async::Read;
16#[cfg(feature = "tokio")]
17use tokio::io::{AsyncRead, AsyncReadExt};
18
19pub struct AsyncMavlinkReader<R> {
25 source: R,
26 decoder: FrameDecoder,
27}
28
29impl<R> AsyncMavlinkReader<R> {
30 #[cfg(feature = "std")]
34 pub fn new(source: R) -> Self
35 where
36 R: AsyncRead + Unpin,
37 {
38 Self {
39 source,
40 decoder: FrameDecoder::new(),
41 }
42 }
43
44 #[cfg(not(feature = "std"))]
46 pub const fn new(source: R) -> Self
47 where
48 R: Read,
49 {
50 Self {
51 source,
52 decoder: FrameDecoder::new(),
53 }
54 }
55
56 #[cfg(feature = "std")]
62 pub fn with_capacity(capacity: usize, source: R) -> Self
63 where
64 R: AsyncRead + Unpin,
65 {
66 Self {
67 source,
68 decoder: FrameDecoder::with_capacity(capacity),
69 }
70 }
71
72 pub const fn get_ref(&self) -> &R {
74 &self.source
75 }
76
77 pub const fn get_mut(&mut self) -> &mut R {
82 &mut self.source
83 }
84
85 pub fn into_inner(self) -> R {
89 self.source
90 }
91}
92
93#[cfg(feature = "tokio")]
94impl<R: AsyncRead + Unpin> AsyncMavlinkReader<R> {
95 pub async fn read_message<M: Message>(
97 &mut self,
98 version: MavlinkVersion,
99 ) -> Result<(MavHeader, M), MessageReadError> {
100 self.read_message_inner(VersionFilter::Exact(version), None)
101 .await
102 }
103
104 pub async fn read_message_with_dialect<D: Dialect>(
106 &mut self,
107 dialect: &D,
108 version: MavlinkVersion,
109 ) -> Result<(MavHeader, D::Message), MessageReadError> {
110 self.read_message_with_dialect_inner(VersionFilter::Exact(version), dialect, None)
111 .await
112 }
113
114 pub async fn read_any_message<M: Message>(
116 &mut self,
117 ) -> Result<(MavHeader, M), MessageReadError> {
118 self.read_message_inner(VersionFilter::Any, None).await
119 }
120
121 pub async fn read_any_message_with_dialect<D: Dialect>(
123 &mut self,
124 dialect: &D,
125 ) -> Result<(MavHeader, D::Message), MessageReadError> {
126 self.read_message_with_dialect_inner(VersionFilter::Any, dialect, None)
127 .await
128 }
129
130 pub async fn read_raw_message<M: Message>(
132 &mut self,
133 version: MavlinkVersion,
134 ) -> Result<MAVLinkMessageRaw, MessageReadError> {
135 self.read_raw_message_inner::<M>(VersionFilter::Exact(version), None)
136 .await
137 }
138
139 pub async fn read_raw_message_with_dialect<D: Dialect>(
141 &mut self,
142 dialect: &D,
143 version: MavlinkVersion,
144 ) -> Result<MAVLinkMessageRaw, MessageReadError> {
145 self.read_raw_message_with_dialect_inner(VersionFilter::Exact(version), dialect, None)
146 .await
147 }
148
149 pub async fn read_any_raw_message<M: Message>(
151 &mut self,
152 ) -> Result<MAVLinkMessageRaw, MessageReadError> {
153 self.read_raw_message_inner::<M>(VersionFilter::Any, None)
154 .await
155 }
156
157 pub async fn read_any_raw_message_with_dialect<D: Dialect>(
159 &mut self,
160 dialect: &D,
161 ) -> Result<MAVLinkMessageRaw, MessageReadError> {
162 self.read_raw_message_with_dialect_inner(VersionFilter::Any, dialect, None)
163 .await
164 }
165
166 #[cfg(feature = "mav2-message-signing")]
171 pub async fn read_message_signed<M: Message>(
172 &mut self,
173 version: MavlinkVersion,
174 signing_data: Option<&SigningData>,
175 ) -> Result<(MavHeader, M), MessageReadError> {
176 self.read_message_inner(VersionFilter::Exact(version), signing_data)
177 .await
178 }
179
180 #[cfg(feature = "mav2-message-signing")]
182 pub async fn read_message_signed_with_dialect<D: Dialect>(
183 &mut self,
184 dialect: &D,
185 version: MavlinkVersion,
186 signing_data: Option<&SigningData>,
187 ) -> Result<(MavHeader, D::Message), MessageReadError> {
188 self.read_message_with_dialect_inner(VersionFilter::Exact(version), dialect, signing_data)
189 .await
190 }
191
192 #[cfg(feature = "mav2-message-signing")]
196 pub async fn read_any_message_signed<M: Message>(
197 &mut self,
198 signing_data: Option<&SigningData>,
199 ) -> Result<(MavHeader, M), MessageReadError> {
200 self.read_message_inner(VersionFilter::Any, signing_data)
201 .await
202 }
203
204 #[cfg(feature = "mav2-message-signing")]
206 pub async fn read_any_message_signed_with_dialect<D: Dialect>(
207 &mut self,
208 dialect: &D,
209 signing_data: Option<&SigningData>,
210 ) -> Result<(MavHeader, D::Message), MessageReadError> {
211 self.read_message_with_dialect_inner(VersionFilter::Any, dialect, signing_data)
212 .await
213 }
214
215 #[cfg(feature = "mav2-message-signing")]
220 pub async fn read_raw_message_signed<M: Message>(
221 &mut self,
222 version: MavlinkVersion,
223 signing_data: Option<&SigningData>,
224 ) -> Result<MAVLinkMessageRaw, MessageReadError> {
225 self.read_raw_message_inner::<M>(VersionFilter::Exact(version), signing_data)
226 .await
227 }
228
229 #[cfg(feature = "mav2-message-signing")]
231 pub async fn read_raw_message_signed_with_dialect<D: Dialect>(
232 &mut self,
233 dialect: &D,
234 version: MavlinkVersion,
235 signing_data: Option<&SigningData>,
236 ) -> Result<MAVLinkMessageRaw, MessageReadError> {
237 self.read_raw_message_with_dialect_inner(
238 VersionFilter::Exact(version),
239 dialect,
240 signing_data,
241 )
242 .await
243 }
244
245 #[cfg(feature = "mav2-message-signing")]
249 pub async fn read_any_raw_message_signed<M: Message>(
250 &mut self,
251 signing_data: Option<&SigningData>,
252 ) -> Result<MAVLinkMessageRaw, MessageReadError> {
253 self.read_raw_message_inner::<M>(VersionFilter::Any, signing_data)
254 .await
255 }
256
257 #[cfg(feature = "mav2-message-signing")]
259 pub async fn read_any_raw_message_signed_with_dialect<D: Dialect>(
260 &mut self,
261 dialect: &D,
262 signing_data: Option<&SigningData>,
263 ) -> Result<MAVLinkMessageRaw, MessageReadError> {
264 self.read_raw_message_with_dialect_inner(VersionFilter::Any, dialect, signing_data)
265 .await
266 }
267
268 #[inline]
269 pub(crate) async fn read_message_inner<M: Message>(
270 &mut self,
271 filter: VersionFilter,
272 signing_data: Option<&SigningData>,
273 ) -> Result<(MavHeader, M), MessageReadError> {
274 self.read_message_with_dialect_inner(filter, &StaticDialect::<M>::new(), signing_data)
275 .await
276 }
277
278 #[inline]
279 pub(crate) async fn read_message_with_dialect_inner<D: Dialect>(
280 &mut self,
281 filter: VersionFilter,
282 dialect: &D,
283 signing_data: Option<&SigningData>,
284 ) -> Result<(MavHeader, D::Message), MessageReadError> {
285 loop {
286 if let Some(result) =
287 try_decode_message(&mut self.decoder, filter, dialect, signing_data)
288 {
289 return result;
290 }
291 self.read_more().await?;
292 }
293 }
294
295 #[inline]
296 pub(crate) async fn read_raw_message_inner<M: Message>(
297 &mut self,
298 filter: VersionFilter,
299 signing_data: Option<&SigningData>,
300 ) -> Result<MAVLinkMessageRaw, MessageReadError> {
301 self.read_raw_message_with_dialect_inner(filter, &StaticDialect::<M>::new(), signing_data)
302 .await
303 }
304
305 #[inline]
306 pub(crate) async fn read_raw_message_with_dialect_inner<D: Dialect>(
307 &mut self,
308 filter: VersionFilter,
309 dialect: &D,
310 signing_data: Option<&SigningData>,
311 ) -> Result<MAVLinkMessageRaw, MessageReadError> {
312 loop {
313 if let Some(message) =
314 try_decode_raw_message(&mut self.decoder, filter, dialect, signing_data)
315 {
316 return Ok(message);
317 }
318 self.read_more().await?;
319 }
320 }
321
322 async fn read_more(&mut self) -> Result<(), MessageReadError> {
323 let destination = self.decoder.spare_capacity_mut();
324 assert!(
325 !destination.is_empty(),
326 "a pending MAVLink frame must fit in the decoder buffer"
327 );
328 let count = loop {
329 match self.source.read(destination).await {
330 Err(error) if error.kind() == std::io::ErrorKind::Interrupted => continue,
331 result => break result?,
332 }
333 };
334 if count == 0 {
335 return Err(MessageReadError::eof());
336 }
337 self.decoder.commit(count);
338 Ok(())
339 }
340}
341
342#[cfg(all(feature = "embedded", not(feature = "std")))]
343impl<R: Read> AsyncMavlinkReader<R> {
344 pub async fn read_message<M: Message>(
346 &mut self,
347 version: MavlinkVersion,
348 ) -> Result<(MavHeader, M), MessageReadError> {
349 let filter = VersionFilter::Exact(version);
350 loop {
351 if let Some(result) =
352 try_decode_message(&mut self.decoder, filter, &StaticDialect::<M>::new(), None)
353 {
354 return result;
355 }
356 self.read_more().await?;
357 }
358 }
359
360 pub async fn read_any_message<M: Message>(
362 &mut self,
363 ) -> Result<(MavHeader, M), MessageReadError> {
364 loop {
365 if let Some(result) = try_decode_message(
366 &mut self.decoder,
367 VersionFilter::Any,
368 &StaticDialect::<M>::new(),
369 None,
370 ) {
371 return result;
372 }
373 self.read_more().await?;
374 }
375 }
376
377 pub async fn read_raw_message<M: Message>(
379 &mut self,
380 version: MavlinkVersion,
381 ) -> Result<MAVLinkMessageRaw, MessageReadError> {
382 let filter = VersionFilter::Exact(version);
383 loop {
384 if let Some(message) =
385 try_decode_raw_message(&mut self.decoder, filter, &StaticDialect::<M>::new(), None)
386 {
387 return Ok(message);
388 }
389 self.read_more().await?;
390 }
391 }
392
393 pub async fn read_any_raw_message<M: Message>(
395 &mut self,
396 ) -> Result<MAVLinkMessageRaw, MessageReadError> {
397 loop {
398 if let Some(message) = try_decode_raw_message(
399 &mut self.decoder,
400 VersionFilter::Any,
401 &StaticDialect::<M>::new(),
402 None,
403 ) {
404 return Ok(message);
405 }
406 self.read_more().await?;
407 }
408 }
409
410 async fn read_more(&mut self) -> Result<(), MessageReadError> {
411 let destination = self.decoder.spare_capacity_mut();
412 assert!(
413 !destination.is_empty(),
414 "a pending MAVLink frame must fit in the decoder buffer"
415 );
416 let count = self
417 .source
418 .read(destination)
419 .await
420 .map_err(|_| MessageReadError::Io)?;
421 if count == 0 {
422 return Err(MessageReadError::eof());
423 }
424 self.decoder.commit(count);
425 Ok(())
426 }
427}