use crate::{
codec::{decode_u16_be, encode_u16_be, Decodable, Encodable},
error::DecodeResult,
reader::TdfReader,
};
use bytes::Bytes;
#[cfg(feature = "sync")]
use std::io::{Read, Write};
use std::{fmt::Debug, hash::Hash};
use std::{io, ops::Deref};
#[cfg(feature = "async")]
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
pub trait PacketComponent: Debug {
fn command(&self) -> u16;
fn from_value(value: u16, notify: bool) -> Self;
}
pub trait PacketComponents: Debug + Eq + Sized + Hash {
fn values(&self) -> (u16, u16);
fn from_values(component: u16, command: u16, notify: bool) -> Self;
fn from_header(header: &PacketHeader) -> Self {
Self::from_values(
header.component,
header.command,
matches!(&header.ty, PacketType::Notify),
)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum PacketType {
Request,
Response,
Notify,
Error,
Unknown(u16),
}
impl PacketType {
pub fn value(&self) -> u16 {
match self {
PacketType::Request => 0x0000,
PacketType::Response => 0x1000,
PacketType::Notify => 0x2000,
PacketType::Error => 0x3000,
PacketType::Unknown(value) => *value,
}
}
pub fn from_value(value: u16) -> PacketType {
match value {
0x0000 => PacketType::Request,
0x1000 => PacketType::Response,
0x2000 => PacketType::Notify,
0x3000 => PacketType::Error,
value => PacketType::Unknown(value),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct PacketHeader {
pub component: u16,
pub command: u16,
pub error: u16,
pub ty: PacketType,
pub id: u16,
}
impl PacketHeader {
pub const fn notify(component: u16, command: u16) -> Self {
Self {
component,
command,
error: 0,
ty: PacketType::Notify,
id: 0,
}
}
pub const fn request(id: u16, component: u16, command: u16) -> Self {
Self {
component,
command,
error: 0,
ty: PacketType::Request,
id,
}
}
#[inline]
pub const fn response(&self) -> Self {
self.with_type(PacketType::Response)
}
pub const fn with_type(&self, ty: PacketType) -> Self {
Self {
component: self.component,
command: self.command,
error: self.error,
ty,
id: self.id,
}
}
pub const fn with_error(&self, error: u16) -> Self {
Self {
component: self.component,
command: self.command,
error,
ty: PacketType::Error,
id: self.id,
}
}
pub fn path_matches(&self, other: &PacketHeader) -> bool {
self.component.eq(&other.component) && self.command.eq(&other.command)
}
pub fn write_bytes(&self, output: &mut Vec<u8>, length: usize) {
let is_extended = length > 0xFFFF;
encode_u16_be(&(length as u16), output);
encode_u16_be(&self.component, output);
encode_u16_be(&self.command, output);
encode_u16_be(&self.error, output);
output.push((self.ty.value() >> 8) as u8);
output.push(if is_extended { 0x10 } else { 0x00 });
encode_u16_be(&self.id, output);
if is_extended {
output.push(((length & 0xFF000000) >> 24) as u8);
output.push(((length & 0x00FF0000) >> 16) as u8);
}
}
pub fn encode_bytes(&self, length: usize) -> Vec<u8> {
let mut header = Vec::with_capacity(12);
self.write_bytes(&mut header, length);
header
}
#[cfg(feature = "sync")]
pub fn read<R: Read>(input: &mut R) -> io::Result<(PacketHeader, usize)>
where
Self: Sized,
{
let mut header = [0u8; 12];
input.read_exact(&mut header)?;
let mut length = decode_u16_be(&header[0..2])? as usize;
let component = decode_u16_be(&header[2..4])?;
let command = decode_u16_be(&header[4..6])?;
let error = decode_u16_be(&header[6..8])?;
let q_type = decode_u16_be(&header[8..10])?;
let id = decode_u16_be(&header[10..12])?;
if q_type & 0x10 != 0 {
let mut buffer = [0; 2];
input.read_exact(&mut buffer)?;
let ext_length = u16::from_be_bytes(buffer);
length += (ext_length as usize) << 16;
}
let ty = PacketType::from_value(q_type);
let header = PacketHeader {
component,
command,
error,
ty,
id,
};
Ok((header, length))
}
#[cfg(feature = "async")]
pub async fn read_async<R: AsyncRead + Unpin>(
input: &mut R,
) -> io::Result<(PacketHeader, usize)>
where
Self: Sized,
{
let mut header = [0u8; 12];
input.read_exact(&mut header).await?;
let mut length = decode_u16_be(&header[0..2])? as usize;
let component = decode_u16_be(&header[2..4])?;
let command = decode_u16_be(&header[4..6])?;
let error = decode_u16_be(&header[6..8])?;
let q_type = decode_u16_be(&header[8..10])?;
let id = decode_u16_be(&header[10..12])?;
if q_type & 0x10 != 0 {
let mut buffer = [0; 2];
input.read_exact(&mut buffer).await?;
let ext_length = u16::from_be_bytes(buffer);
length += (ext_length as usize) << 16;
}
let ty = PacketType::from_value(q_type);
let header = PacketHeader {
component,
command,
error,
ty,
id,
};
Ok((header, length))
}
}
#[derive(Debug, Clone)]
pub struct Packet {
pub header: PacketHeader,
pub contents: Bytes,
}
impl Packet {
pub fn raw(header: PacketHeader, contents: Vec<u8>) -> Self {
Self {
header,
contents: Bytes::from(contents),
}
}
pub const fn raw_empty(header: PacketHeader) -> Self {
Self {
header,
contents: Bytes::new(),
}
}
pub fn response<C: Encodable>(packet: &Packet, contents: C) -> Self {
Self {
header: packet.header.response(),
contents: Bytes::from(contents.encode_bytes()),
}
}
#[inline]
pub fn respond<C: Encodable>(&self, contents: C) -> Self {
Self::response(self, contents)
}
pub fn response_raw(packet: &Packet, contents: Vec<u8>) -> Self {
Self {
header: packet.header.response(),
contents: Bytes::from(contents),
}
}
pub const fn response_empty(packet: &Packet) -> Self {
Self {
header: packet.header.response(),
contents: Bytes::new(),
}
}
#[inline]
pub const fn respond_empty(&self) -> Self {
Self::response_empty(self)
}
pub fn error<C: Encodable>(packet: &Packet, error: u16, contents: C) -> Self {
Self {
header: packet.header.with_error(error),
contents: Bytes::from(contents.encode_bytes()),
}
}
#[inline]
pub fn respond_error<C: Encodable>(&self, error: u16, contents: C) -> Self {
Self::error(self, error, contents)
}
pub fn error_raw(packet: &Packet, error: u16, contents: Vec<u8>) -> Self {
Self {
header: packet.header.with_error(error),
contents: Bytes::from(contents),
}
}
#[inline]
pub const fn error_empty(packet: &Packet, error: u16) -> Packet {
Self {
header: packet.header.with_error(error),
contents: Bytes::new(),
}
}
#[inline]
pub const fn respond_error_empty(&self, error: u16) -> Packet {
Self::error_empty(self, error)
}
pub fn notify<C: Encodable, T: PacketComponents>(component: T, contents: C) -> Packet {
let (component, command) = component.values();
Self {
header: PacketHeader::notify(component, command),
contents: Bytes::from(contents.encode_bytes()),
}
}
pub fn notify_raw<T: PacketComponents>(component: T, contents: Vec<u8>) -> Packet {
let (component, command) = component.values();
Self {
header: PacketHeader::notify(component, command),
contents: Bytes::from(contents),
}
}
#[inline]
pub fn notify_empty<T: PacketComponents>(component: T) -> Packet {
let (component, command) = component.values();
Self {
header: PacketHeader::notify(component, command),
contents: Bytes::new(),
}
}
pub fn request<C: Encodable, T: PacketComponents>(
id: u16,
component: T,
contents: C,
) -> Packet {
let (component, command) = component.values();
Self {
header: PacketHeader::request(id, component, command),
contents: Bytes::from(contents.encode_bytes()),
}
}
pub fn request_raw<T: PacketComponents>(id: u16, component: T, contents: Vec<u8>) -> Packet {
let (component, command) = component.values();
Self {
header: PacketHeader::request(id, component, command),
contents: Bytes::from(contents),
}
}
pub fn request_empty<T: PacketComponents>(id: u16, component: T) -> Packet {
let (component, command) = component.values();
Self {
header: PacketHeader::request(id, component, command),
contents: Bytes::new(),
}
}
pub fn decode<C: Decodable>(&self) -> DecodeResult<C> {
let mut reader = TdfReader::new(&self.contents);
C::decode(&mut reader)
}
#[cfg(feature = "sync")]
pub fn read<R: Read>(input: &mut R) -> io::Result<Self>
where
Self: Sized,
{
let (header, length) = PacketHeader::read(input)?;
let mut contents = vec![0u8; length];
input.read_exact(&mut contents)?;
Ok(Self {
header,
contents: Bytes::from(contents),
})
}
#[cfg(feature = "async")]
pub async fn read_async<R: AsyncRead + Unpin>(input: &mut R) -> io::Result<Self>
where
Self: Sized,
{
let (header, length) = PacketHeader::read_async(input).await?;
let mut contents = vec![0u8; length];
input.read_exact(&mut contents).await?;
Ok(Self {
header,
contents: Bytes::from(contents),
})
}
#[cfg(feature = "sync")]
pub fn read_typed<T: PacketComponents, R: Read>(input: &mut R) -> io::Result<(T, Self)>
where
Self: Sized,
{
let (header, length) = PacketHeader::read(input)?;
let mut contents = vec![0u8; length];
input.read_exact(&mut contents)?;
let component = T::from_header(&header);
Ok((
component,
Self {
header,
contents: Bytes::from(contents),
},
))
}
#[cfg(feature = "async")]
pub async fn read_async_typed<T: PacketComponents, R: AsyncRead + Unpin>(
input: &mut R,
) -> io::Result<(T, Self)>
where
Self: Sized,
{
let (header, length) = PacketHeader::read_async(input).await?;
let mut contents = vec![0u8; length];
input.read_exact(&mut contents).await?;
let component = T::from_header(&header);
Ok((
component,
Self {
header,
contents: Bytes::from(contents),
},
))
}
#[cfg(feature = "sync")]
pub fn write<W: Write>(&self, output: &mut W) -> io::Result<()>
where
Self: Sized,
{
let contents = &self.contents;
let header = self.header.encode_bytes(contents.len());
output.write_all(&header)?;
output.write_all(contents)?;
Ok(())
}
#[cfg(feature = "async")]
pub async fn write_async<W: AsyncWrite + Unpin>(&self, output: &mut W) -> io::Result<()>
where
Self: Sized,
{
let content = &self.contents;
let header = self.header.encode_bytes(content.len());
output.write_all(&header).await?;
output.write_all(content).await?;
Ok(())
}
pub fn write_bytes(&self, output: &mut Vec<u8>) {
let content = &self.contents;
let length = content.len();
self.header.write_bytes(output, length);
output.extend_from_slice(content);
}
pub fn encode_bytes(&self) -> Vec<u8> {
let mut output = Vec::with_capacity(14 + self.contents.len());
self.write_bytes(&mut output);
output
}
}
pub struct Request<T: FromRequest> {
pub req: T,
pub header: PacketHeader,
}
impl<T: FromRequest> Deref for Request<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.req
}
}
impl<T: FromRequest> Request<T> {
pub fn response<E>(&self, res: E) -> Response
where
E: IntoResponse,
{
Response(res.into_response(&self.header))
}
}
pub struct Response(Packet);
impl IntoResponse for Response {
fn into_response(self, _header: &PacketHeader) -> Packet {
self.0
}
}
impl<T: FromRequest> FromRequest for Request<T> {
fn from_request(req: &Packet) -> DecodeResult<Self> {
let inner = T::from_request(req)?;
let header = req.header.clone();
Ok(Self { req: inner, header })
}
}
pub trait FromRequest: Sized {
fn from_request(req: &Packet) -> DecodeResult<Self>;
}
impl<D> FromRequest for D
where
D: Decodable,
{
fn from_request(req: &Packet) -> DecodeResult<Self> {
req.decode()
}
}
impl FromRequest for () {
fn from_request(_: &Packet) -> DecodeResult<Self> {
Ok(())
}
}
pub trait IntoResponse {
fn into_response(self, header: &PacketHeader) -> Packet;
}
impl IntoResponse for () {
fn into_response(self, header: &PacketHeader) -> Packet {
Packet {
header: header.response(),
contents: Bytes::new(),
}
}
}
impl<E> IntoResponse for E
where
E: Encodable,
{
fn into_response(self, header: &PacketHeader) -> Packet {
Packet {
header: header.response(),
contents: Bytes::from(self.encode_bytes()),
}
}
}
impl<S, E> IntoResponse for Result<S, E>
where
S: IntoResponse,
E: IntoResponse,
{
fn into_response(self, header: &PacketHeader) -> Packet {
match self {
Ok(value) => value.into_response(header),
Err(value) => value.into_response(header),
}
}
}
impl<S> IntoResponse for Option<S>
where
S: IntoResponse,
{
fn into_response(self, header: &PacketHeader) -> Packet {
match self {
Some(value) => value.into_response(header),
None => Packet {
header: header.response(),
contents: Bytes::new(),
},
}
}
}