Make the TcpServer work with bytes instead of strings

This makes it possible to implement byte-based protocols using TcpServer, instead of only being able to implement string-based protocols.
This commit is contained in:
Ben Bridle 2021-08-07 14:20:59 +12:00
parent 3f46685100
commit ccd4da433b
3 changed files with 8 additions and 15 deletions

View File

@ -15,13 +15,13 @@ impl<Req: Request, Res: Response> Connection<Req, Res> {
stream, stream,
address, address,
token, token,
state: RequestState::Incoming(String::new()), state: RequestState::Incoming(Vec::new()),
} }
} }
} }
pub enum RequestState<Req: Request, Res: Response> { pub enum RequestState<Req: Request, Res: Response> {
Incoming(String), Incoming(Vec<u8>),
Processing(Req), Processing(Req),
Outgoing(Res), Outgoing(Res),
} }

View File

@ -1,13 +1,13 @@
pub trait Request { pub trait Request {
type Response; type Response;
fn from_string(request_string: &str) -> RequestParseResult<Self, Self::Response> fn from_bytes(request_bytes: &[u8]) -> RequestParseResult<Self, Self::Response>
where where
Self: Sized, Self: Sized,
Self::Response: Response; Self::Response: Response;
} }
pub trait Response { pub trait Response {
fn to_string(self) -> String; fn to_bytes(self) -> Vec<u8>;
} }
pub type ProcessRequest<Req, Res> = fn(request: &Req) -> Res; pub type ProcessRequest<Req, Res> = fn(request: &Req) -> Res;

View File

@ -144,19 +144,13 @@ impl<
self.remove_connection(event.token()).unwrap(); self.remove_connection(event.token()).unwrap();
return; return;
} }
Ok(_) => match std::str::from_utf8(&buffer) { Ok(len) => request_data.extend_from_slice(&buffer[..len]),
Ok(s) => request_data.push_str(s.trim_matches(char::from(0))),
Err(e) => panic!(
"Incoming data from {:?} is not valid UTF-8: {}",
connection.address, e
),
},
Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => break, Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => break,
Err(e) => panic!("Unexpected error: {}", e), Err(e) => panic!("Unexpected error: {}", e),
}; };
} }
match Req::from_string(&request_data) { match Req::from_bytes(&request_data) {
RequestParseResult::Complete(request) => { RequestParseResult::Complete(request) => {
let mut connection = let mut connection =
std::mem::replace(&mut self.connections[token.0], None).unwrap(); std::mem::replace(&mut self.connections[token.0], None).unwrap();
@ -180,9 +174,8 @@ impl<
let token = event.token(); let token = event.token();
let mut connection = std::mem::replace(&mut self.connections[token.0], None).unwrap(); let mut connection = std::mem::replace(&mut self.connections[token.0], None).unwrap();
if let RequestState::Outgoing(response) = connection.state { if let RequestState::Outgoing(response) = connection.state {
let response_string = response.to_string(); let bytes = response.to_bytes();
let bytes = response_string.as_bytes(); connection.stream.write_all(&bytes).unwrap();
connection.stream.write_all(bytes).unwrap();
} else { } else {
info!("Received write event for non-outgoing connection") info!("Received write event for non-outgoing connection")
} }