use crate::{
buf::{send_data, RecvBuf},
fun::{Fun, Result},
val::{ByteQue, Store},
};
use std::{
io::{Read, Write},
net::{Shutdown, TcpListener, TcpStream},
sync::Arc,
thread,
};
pub fn service(srv_fun: Fun, addr: &str) {
let srv_fun = Arc::new(srv_fun);
let listener = TcpListener::bind(addr).unwrap();
for stream in listener.incoming() {
if let Ok(mut stream) = stream {
let srv_fun = srv_fun.clone();
thread::spawn(move || {
let mut buf = [0u8; 1024];
loop {
let mut recv = RecvBuf::new();
loop {
match recv.size() {
Some(s) if s == recv.len() => break,
_ => match stream.read(&mut buf) {
Ok(l) if l > 0 => recv.append(&buf[..l]),
_ => match stream.shutdown(Shutdown::Both) {
_ => return,
},
},
}
}
if let Err(_) = stream.write_all(&send_data(srv_fun.invoke(&mut recv.into()))) {
match stream.shutdown(Shutdown::Both) {
_ => return,
}
}
}
});
}
}
}
pub struct Connection(TcpStream);
impl Connection {
pub fn new(addr: &str) -> Self {
Connection(TcpStream::connect(addr).unwrap())
}
pub fn invoke<T: Store>(&mut self, fun: ByteQue) -> Result<T> {
if let Err(e) = self.0.write_all(&send_data(fun)) {
return Err(format!("{}", e));
}
let mut recv = RecvBuf::new();
let mut buf = [0u8; 1024];
loop {
match recv.size() {
Some(s) if s == recv.len() => break,
_ => match self.0.read(&mut buf) {
Ok(l) => {
if l > 0 {
recv.append(&buf[..l]);
} else {
return Err(String::from("the server is disconnected"));
}
}
Err(e) => return Err(format!("{}", e)),
},
}
}
Store::restore(&mut recv.into())
}
}