remote-block-device-backup/remote-block-device-backup-.../src/simple_communicator.rs

139 lines
4.9 KiB
Rust

use std::cmp::min;
use std::io;
use std::io::prelude::*;
pub trait SimpleCommunicator {
fn send_bool(&mut self, b: bool) -> io::Result<usize>;
fn send_2bytes(&mut self, v: &[u8; 2]) -> io::Result<usize>;
fn send_32bytes(&mut self, v: &[u8; 32]) -> io::Result<usize>;
fn send_u16(&mut self, number: u16) -> io::Result<usize>;
fn send_u32(&mut self, number: u32) -> io::Result<usize>;
fn send_u64(&mut self, number: u64) -> io::Result<usize>;
fn send_string_small(&mut self, text: &str) -> io::Result<usize>;
fn send_bytes_short(&mut self, bytes: &[u8]) -> io::Result<usize>;
fn send_bytes_large(&mut self, bytes: &[u8]) -> io::Result<usize>;
fn recv_bool(&mut self) -> io::Result<bool>;
fn recv_2bytes(&mut self) -> io::Result<[u8; 2]>;
fn recv_32bytes(&mut self) -> io::Result<[u8; 32]>;
fn recv_u16(&mut self) -> io::Result<u16>;
fn recv_u32(&mut self) -> io::Result<u32>;
fn recv_u64(&mut self) -> io::Result<u64>;
fn recv_string_small(&mut self) -> io::Result<String>;
fn recv_bytes_short(&mut self) -> io::Result<Vec<u8>>;
fn recv_bytes_large(&mut self) -> io::Result<Vec<u8>>;
}
impl<T> SimpleCommunicator for T
where
T: io::Read + io::Write,
{
fn send_bool(&mut self, b: bool) -> io::Result<usize> {
Ok(if b {
self.write(&[255])?
} else {
self.write(&[0])?
})
}
fn send_2bytes(&mut self, v: &[u8; 2]) -> io::Result<usize> {
Ok(self.write(v)?)
}
fn send_32bytes(&mut self, v: &[u8; 32]) -> io::Result<usize> {
Ok(self.write(v)?)
}
fn send_u16(&mut self, number: u16) -> io::Result<usize> {
Ok(self.write(&number.to_be_bytes())?)
}
fn send_u32(&mut self, number: u32) -> io::Result<usize> {
Ok(self.write(&number.to_be_bytes())?)
}
fn send_u64(&mut self, number: u64) -> io::Result<usize> {
Ok(self.write(&number.to_be_bytes())?)
}
fn send_string_small(&mut self, text: &str) -> io::Result<usize> {
Ok(self.send_bytes_short(text.as_bytes())?)
}
fn send_bytes_short(&mut self, bytes: &[u8]) -> io::Result<usize> {
let s1 = self.send_u16(bytes.len() as u16)?;
let s2 = self.write(bytes)?;
Ok(s1 + s2)
}
fn send_bytes_large(&mut self, bytes: &[u8]) -> io::Result<usize> {
let bl = bytes.len();
let s1 = self.send_u64(bytes.len() as u64)?;
let mut s2: usize = 0;
let bucketsz: usize = 1 << 14;
while s2 < bl {
s2 += self.write(
&bytes
.iter()
.skip(s2)
.take(bucketsz)
.copied()
.collect::<Vec<u8>>(),
)?;
self.flush()?;
}
Ok(s1 + s2)
}
fn recv_bool(&mut self) -> io::Result<bool> {
let mut bytes = [0u8; 1];
self.read_exact(&mut bytes)?;
match bytes[0] {
255 => Ok(true),
0 => Ok(false),
_ => Err(io::Error::from(io::ErrorKind::InvalidData)),
}
}
fn recv_2bytes(&mut self) -> io::Result<[u8; 2]> {
let mut bytes = [0u8; 2];
self.read_exact(&mut bytes)?;
Ok(bytes)
}
fn recv_32bytes(&mut self) -> io::Result<[u8; 32]> {
let mut bytes = [0u8; 32];
self.read_exact(&mut bytes)?;
Ok(bytes)
}
fn recv_u16(&mut self) -> io::Result<u16> {
let mut u16_bytes = [0u8; 2];
self.read_exact(&mut u16_bytes)?;
Ok(u16::from_be_bytes(u16_bytes))
}
fn recv_u32(&mut self) -> io::Result<u32> {
let mut u32_bytes = [0u8; 4];
self.read_exact(&mut u32_bytes)?;
Ok(u32::from_be_bytes(u32_bytes))
}
fn recv_u64(&mut self) -> io::Result<u64> {
let mut u64_bytes = [0u8; 8];
self.read_exact(&mut u64_bytes)?;
Ok(u64::from_be_bytes(u64_bytes))
}
fn recv_string_small(&mut self) -> io::Result<String> {
let size: u16 = self.recv_u16()?;
let mut small_string: String = String::new();
self.take(size as u64).read_to_string(&mut small_string)?;
Ok(small_string)
}
fn recv_bytes_short(&mut self) -> io::Result<Vec<u8>> {
let size: u16 = self.recv_u16()?;
let mut small_vec: Vec<u8> = vec![0u8; size as usize];
self.read(&mut small_vec)?;
Ok(small_vec)
}
fn recv_bytes_large(&mut self) -> io::Result<Vec<u8>> {
let size: usize = self.recv_u64()? as usize;
let mut large_vec: Vec<u8> = vec![0u8; size as usize];
let mut already_read = 0usize;
let bucketsz: usize = 1 << 14;
while already_read < size {
let to_take = min(size - already_read, bucketsz);
already_read += self
.take(to_take as u64)
.read(&mut large_vec[already_read..(already_read + to_take)])?;
self.flush()?;
}
Ok(large_vec)
}
}