massa_bootstrap/
bindings.rs

1mod client;
2mod server;
3use std::{
4    io::{self, ErrorKind},
5    time::{Duration, Instant},
6};
7
8pub(crate) use client::*;
9pub(crate) use server::*;
10
11trait BindingReadExact: io::Read {
12    /// similar to std::io::Read::read_exact, but with a timeout that is function-global instead of per-individual-read
13    fn read_exact_timeout(
14        &mut self,
15        buf: &mut [u8],
16        deadline: Option<Instant>,
17    ) -> Result<(), (std::io::Error, usize)> {
18        let mut count = 0;
19        self.set_read_timeout(None).map_err(|err| (err, count))?;
20        while count < buf.len() {
21            // update the timeout
22            if let Some(deadline) = deadline {
23                let dur = deadline.saturating_duration_since(Instant::now());
24                if dur.is_zero() {
25                    return Err((
26                        std::io::Error::new(ErrorKind::TimedOut, "deadline has elapsed"),
27                        count,
28                    ));
29                }
30                self.set_read_timeout(Some(dur))
31                    .map_err(|err| (err, count))?;
32            }
33
34            // do the read
35            match self.read(&mut buf[count..]) {
36                Ok(0) => break,
37                Ok(n) => {
38                    count += n;
39                }
40                Err(ref e) if e.kind() == std::io::ErrorKind::Interrupted => {}
41                Err(e) => {
42                    if e.kind() == ErrorKind::TimedOut || e.kind() == ErrorKind::WouldBlock {
43                        return Err((
44                            std::io::Error::new(ErrorKind::TimedOut, "deadline has elapsed"),
45                            count,
46                        ));
47                    } else {
48                        return Err((e, count));
49                    }
50                }
51            }
52        }
53        if count != buf.len() {
54            Err((
55                std::io::Error::new(
56                    ErrorKind::UnexpectedEof,
57                    format!("failed to fill whole buffer: {}/{}", count, buf.len()),
58                ),
59                count,
60            ))
61        } else {
62            Ok(())
63        }
64    }
65
66    /// Internal helper
67    fn set_read_timeout(&mut self, duration: Option<Duration>) -> Result<(), std::io::Error>;
68}
69
70trait BindingWriteExact: io::Write {
71    fn write_all_timeout(
72        &mut self,
73        write_buf: &[u8],
74        deadline: Option<Instant>,
75    ) -> Result<(), (std::io::Error, usize)> {
76        self.set_write_timeout(None).map_err(|e| (e, 0))?;
77        let mut total_bytes_written = 0;
78
79        while total_bytes_written < write_buf.len() {
80            if let Some(deadline) = deadline {
81                let dur = deadline.saturating_duration_since(Instant::now());
82                if dur.is_zero() {
83                    return Err((
84                        std::io::Error::new(ErrorKind::TimedOut, "deadline has elapsed"),
85                        total_bytes_written,
86                    ));
87                }
88                self.set_write_timeout(Some(dur))
89                    .map_err(|e| (e, total_bytes_written))?;
90            }
91
92            match self.write(&write_buf[total_bytes_written..]) {
93                Ok(bytes_written) => {
94                    total_bytes_written += bytes_written;
95                }
96                Err(err) => {
97                    return Err((err, total_bytes_written));
98                }
99            }
100        }
101
102        Ok(())
103    }
104    /// Internal helper
105    fn set_write_timeout(&mut self, duration: Option<Duration>) -> Result<(), std::io::Error>;
106}