mavlink_core/connection/
file.rs

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