Skip to main content

mavlink_core/connection/
file.rs

1//! File MAVLINK connection
2
3use crate::connection::{Connection, MavConnection};
4use crate::error::{MessageReadError, MessageWriteError};
5use crate::peek_reader::PeekReader;
6use crate::{Connectable, MAVLinkMessageRaw};
7use crate::{MavHeader, MavlinkVersion, Message, ReadVersion};
8use core::ops::DerefMut;
9use std::fs::File;
10use std::io;
11use std::path::PathBuf;
12use std::sync::Mutex;
13
14#[cfg(not(feature = "mav2-message-signing"))]
15use crate::{read_versioned_msg, read_versioned_raw_message};
16#[cfg(feature = "mav2-message-signing")]
17use crate::{
18    read_versioned_msg_signed, read_versioned_raw_message_signed, SigningConfig, SigningData,
19};
20
21pub mod config;
22
23use config::FileConfig;
24
25pub fn open(file_path: &PathBuf) -> io::Result<FileConnection> {
26    let file = File::open(file_path)?;
27
28    Ok(FileConnection {
29        file: Mutex::new(PeekReader::new(file)),
30        protocol_version: MavlinkVersion::V2,
31        #[cfg(feature = "mav2-message-signing")]
32        signing_data: None,
33        recv_any_version: false,
34    })
35}
36
37pub struct FileConnection {
38    file: Mutex<PeekReader<File>>,
39    protocol_version: MavlinkVersion,
40    recv_any_version: bool,
41    #[cfg(feature = "mav2-message-signing")]
42    signing_data: Option<SigningData>,
43}
44
45impl<M: Message> MavConnection<M> for FileConnection {
46    fn recv(&self) -> Result<(MavHeader, M), crate::error::MessageReadError> {
47        let mut file = self.file.lock().unwrap();
48        let version = ReadVersion::from_conn_cfg::<_, M>(self);
49
50        loop {
51            #[cfg(not(feature = "mav2-message-signing"))]
52            let result = read_versioned_msg(file.deref_mut(), version);
53            #[cfg(feature = "mav2-message-signing")]
54            let result =
55                read_versioned_msg_signed(file.deref_mut(), version, self.signing_data.as_ref());
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    fn recv_raw(&self) -> Result<MAVLinkMessageRaw, crate::error::MessageReadError> {
69        let mut file = self.file.lock().unwrap();
70        let version = ReadVersion::from_conn_cfg::<_, M>(self);
71
72        loop {
73            #[cfg(not(feature = "mav2-message-signing"))]
74            let result = read_versioned_raw_message::<M, _>(file.deref_mut(), version);
75            #[cfg(feature = "mav2-message-signing")]
76            let result = read_versioned_raw_message_signed::<M, _>(
77                file.deref_mut(),
78                version,
79                self.signing_data.as_ref(),
80            );
81            match result {
82                ok @ Ok(..) => {
83                    return ok;
84                }
85                Err(MessageReadError::Io(e)) if e.kind() == io::ErrorKind::UnexpectedEof => {
86                    return Err(MessageReadError::Io(e));
87                }
88                _ => {}
89            }
90        }
91    }
92
93    fn try_recv(&self) -> Result<(MavHeader, M), crate::error::MessageReadError> {
94        let mut file = self.file.lock().unwrap();
95        let version = ReadVersion::from_conn_cfg::<_, M>(self);
96
97        #[cfg(not(feature = "mav2-message-signing"))]
98        let result = read_versioned_msg(file.deref_mut(), version);
99        #[cfg(feature = "mav2-message-signing")]
100        let result =
101            read_versioned_msg_signed(file.deref_mut(), version, self.signing_data.as_ref());
102
103        result
104    }
105
106    fn send(&self, _header: &MavHeader, _data: &M) -> Result<usize, MessageWriteError> {
107        Ok(0)
108    }
109
110    fn set_protocol_version(&mut self, version: MavlinkVersion) {
111        self.protocol_version = version;
112    }
113
114    fn protocol_version(&self) -> MavlinkVersion {
115        self.protocol_version
116    }
117
118    fn set_allow_recv_any_version(&mut self, allow: bool) {
119        self.recv_any_version = allow;
120    }
121
122    fn allow_recv_any_version(&self) -> bool {
123        self.recv_any_version
124    }
125
126    #[cfg(feature = "mav2-message-signing")]
127    fn setup_signing(&mut self, signing_data: Option<SigningConfig>) {
128        self.signing_data = signing_data.map(SigningData::from_config);
129    }
130}
131
132impl Connectable for FileConfig {
133    fn connect<M: Message>(&self) -> io::Result<Connection<M>> {
134        Ok(open(&self.address)?.into())
135    }
136}