use bincode::{deserialize, serialize};
use serde::de::DeserializeOwned;
use serde::Serialize;
use std::net::SocketAddr;
use thiserror::Error;
use tokio::net::ToSocketAddrs;
#[derive(Error, Debug)]
pub enum UdpSocketError {
#[error("`{0}`")]
IoError(std::io::Error),
#[error("`{0}`")]
BincodeError(bincode::Error),
}
pub struct UdpSocket {
buffer: [u8; 512],
socket: tokio::net::UdpSocket,
}
impl UdpSocket {
pub async fn bind<A: ToSocketAddrs>(addr: A) -> Result<Self, UdpSocketError> {
let socket = tokio::net::UdpSocket::bind(addr).await?;
Ok(Self::new(socket))
}
pub fn new(socket: tokio::net::UdpSocket) -> Self {
let buffer = [0; 512];
Self { buffer, socket }
}
pub async fn write<T: Serialize>(
&mut self,
value: &T,
send_to: SocketAddr,
) -> Result<(), UdpSocketError> {
let buf = serialize(value)?;
self.socket.send_to(buf.as_slice(), send_to).await?;
Ok(())
}
pub async fn read<T: DeserializeOwned>(&mut self) -> Result<(T, SocketAddr), UdpSocketError> {
let (_, src) = self.socket.recv_from(&mut self.buffer).await?;
let value = deserialize::<T>(self.buffer.as_slice())?;
Ok((value, src))
}
pub fn local_addr(&self) -> Result<SocketAddr, UdpSocketError> {
Ok(self.socket.local_addr()?)
}
}
impl From<Box<bincode::ErrorKind>> for UdpSocketError {
fn from(e: Box<bincode::ErrorKind>) -> Self {
UdpSocketError::BincodeError(e)
}
}
impl From<std::io::Error> for UdpSocketError {
fn from(e: std::io::Error) -> Self {
UdpSocketError::IoError(e)
}
}