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_versioned_msg, read_versioned_raw_message};
16#[cfg(feature = "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 = "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 = "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
49        loop {
50            let version = ReadVersion::from_conn_cfg::<_, M>(self);
51            #[cfg(not(feature = "signing"))]
52            let result = read_versioned_msg(file.deref_mut(), version);
53            #[cfg(feature = "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)) => {
61                    if e.kind() == io::ErrorKind::UnexpectedEof {
62                        return Err(MessageReadError::Io(e));
63                    }
64                }
65                _ => {}
66            }
67        }
68    }
69
70    fn recv_raw(&self) -> Result<MAVLinkMessageRaw, crate::error::MessageReadError> {
71        let mut file = self.file.lock().unwrap();
72
73        loop {
74            let version = ReadVersion::from_conn_cfg::<_, M>(self);
75            #[cfg(not(feature = "signing"))]
76            let result = read_versioned_raw_message::<M, _>(file.deref_mut(), version);
77            #[cfg(feature = "signing")]
78            let result = read_versioned_raw_message_signed::<M, _>(
79                file.deref_mut(),
80                version,
81                self.signing_data.as_ref(),
82            );
83            match result {
84                ok @ Ok(..) => {
85                    return ok;
86                }
87                Err(MessageReadError::Io(e)) => {
88                    if e.kind() == io::ErrorKind::UnexpectedEof {
89                        return Err(MessageReadError::Io(e));
90                    }
91                }
92                _ => {}
93            }
94        }
95    }
96
97    fn try_recv(&self) -> Result<(MavHeader, M), crate::error::MessageReadError> {
98        let mut file = self.file.lock().unwrap();
99        let version = ReadVersion::from_conn_cfg::<_, M>(self);
100
101        #[cfg(not(feature = "signing"))]
102        let result = read_versioned_msg(file.deref_mut(), version);
103        #[cfg(feature = "signing")]
104        let result =
105            read_versioned_msg_signed(file.deref_mut(), version, self.signing_data.as_ref());
106
107        result
108    }
109
110    fn send(&self, _header: &MavHeader, _data: &M) -> Result<usize, MessageWriteError> {
111        Ok(0)
112    }
113
114    fn set_protocol_version(&mut self, version: MavlinkVersion) {
115        self.protocol_version = version;
116    }
117
118    fn protocol_version(&self) -> MavlinkVersion {
119        self.protocol_version
120    }
121
122    fn set_allow_recv_any_version(&mut self, allow: bool) {
123        self.recv_any_version = allow;
124    }
125
126    fn allow_recv_any_version(&self) -> bool {
127        self.recv_any_version
128    }
129
130    #[cfg(feature = "signing")]
131    fn setup_signing(&mut self, signing_data: Option<SigningConfig>) {
132        self.signing_data = signing_data.map(SigningData::from_config);
133    }
134}
135
136impl Connectable for FileConfig {
137    fn connect<M: Message>(&self) -> io::Result<Box<dyn MavConnection<M> + Sync + Send>> {
138        Ok(Box::new(open(&self.address)?))
139    }
140}