Something went wrong. Try again.
Something went wrong. Try again.
7.3 kB · 268 lines
Rust
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269#![no_std]
use core::str::from_utf8;
use thiserror::Error;
#[allow(async_fn_in_trait)]pub trait PacketSocket { async fn write_all(&mut self, buf: &[u8]) -> bool; async fn read_exact(&mut self, buf: &mut [u8]) -> bool; async fn flush(&mut self) -> bool;}
#[derive(Debug)]pub enum Packet<'a> { Register { ip: [u8; 4], port: u16, id: &'a str }, Ok, TimeSync(i64), State(State),}
#[derive(Debug, Clone)]pub struct Color(pub u8, pub u8, pub u8);
#[derive(Debug, Error)]pub enum ColorError { #[error("invalid hex")] InvalidHex,}
impl Color { pub fn from_hex(hex: &str) -> Result<Color, ColorError> { let r = u8::from_str_radix(&hex[1..3], 16).map_err(|_| ColorError::InvalidHex)?; let g = u8::from_str_radix(&hex[3..5], 16).map_err(|_| ColorError::InvalidHex)?; let b = u8::from_str_radix(&hex[5..7], 16).map_err(|_| ColorError::InvalidHex)?;
Ok(Color(r, g, b)) }}
#[derive(Debug, Clone)]pub enum State { Off, Color(Color), Sun(u8),}
#[derive(Debug, Error)]pub enum PacketError { #[error("unknown type")] UnknownType, #[error("buffer too small")] BufferTooSmall, #[error("no ok received")] NoOkRecieved, #[error("failed to write")] FailedToWrite, #[error("failed to read")] FailedToRead, #[error("data too large")] DataTooLarge, #[error("id too large")] IdTooLarge,}
impl<'a> Packet<'a> { pub async fn send<'b>( socket: &mut impl PacketSocket, buf: &'b mut [u8], packet: Packet<'b>, ) -> Result<(), PacketError> { let length = packet.encode(&mut buf[4..])?; Self::write_u32( buf, 0, u32::try_from(length + 4).map_err(|_| PacketError::DataTooLarge)?, );
if !socket.write_all(&buf[..length + 4]).await { return Err(PacketError::FailedToWrite); } if !socket.flush().await { return Err(PacketError::FailedToWrite); }
Ok(()) }
pub async fn save_send( socket: &mut impl PacketSocket, buf: &'a mut [u8], packet: Packet<'a>, ) -> Result<(), PacketError> { Self::send(socket, buf, packet).await?;
let Some(Packet::Ok) = Packet::read(socket, buf).await? else { return Err(PacketError::NoOkRecieved); };
Ok(()) }
pub async fn read( socket: &mut impl PacketSocket, buf: &'a mut [u8], ) -> Result<Option<Packet<'a>>, PacketError> { if !socket.read_exact(&mut buf[..4]).await { return Ok(None); }
let target_length = Self::read_u32(buf, 0) as usize; if target_length > buf.len() - 4 { return Err(PacketError::DataTooLarge); }
if !socket.read_exact(&mut buf[4..target_length]).await { return Err(PacketError::FailedToRead); }
Ok(Some(Packet::decode(&buf[4..target_length])?)) }
fn encode(&self, buf: &mut [u8]) -> Result<usize, PacketError> { let len = match self { Packet::Ok => { Self::write_u8(buf, 0, 1);
1 } Packet::Register { ip, port, id } => { Self::write_u8(buf, 0, 2);
Self::write_u8(buf, 1, ip[0]); Self::write_u8(buf, 2, ip[1]); Self::write_u8(buf, 3, ip[2]); Self::write_u8(buf, 4, ip[3]);
Self::write_u16(buf, 5, *port);
let id_bytes = id.as_bytes(); Self::write_u8( buf, 7, u8::try_from(id_bytes.len()).map_err(|_| PacketError::IdTooLarge)?, ); Self::write(buf, 8, id_bytes);
8 + id_bytes.len() } Packet::TimeSync(timestamp) => { Self::write_u8(buf, 0, 3); Self::write_i64(buf, 1, *timestamp);
9 } Packet::State(State::Off) => { Self::write_u8(buf, 0, 4); 1 } Packet::State(State::Color(Color(r, g, b))) => { Self::write_u8(buf, 0, 5);
Self::write_u8(buf, 1, *r); Self::write_u8(buf, 2, *g); Self::write_u8(buf, 3, *b);
4 } Packet::State(State::Sun(brightness)) => { Self::write_u8(buf, 0, 6); Self::write_u8(buf, 1, *brightness);
2 } };
Ok(len) }
fn write(buf: &mut [u8], offset: usize, value: &[u8]) { buf[offset..offset + value.len()].copy_from_slice(value); }
fn write_i64(buf: &mut [u8], offset: usize, value: i64) { Self::write(buf, offset, &value.to_be_bytes()); }
fn write_u32(buf: &mut [u8], offset: usize, value: u32) { Self::write(buf, offset, &value.to_be_bytes()); }
fn write_u16(buf: &mut [u8], offset: usize, value: u16) { Self::write(buf, offset, &value.to_be_bytes()); }
fn write_u8(buf: &mut [u8], offset: usize, value: u8) { buf[offset] = value; }
fn decode(buf: &'a [u8]) -> Result<Self, PacketError> { match Self::read_u8(buf, 0) { 1 => Ok(Packet::Ok), 2 => { let ip = [ Self::read_u8(buf, 1), Self::read_u8(buf, 2), Self::read_u8(buf, 3), Self::read_u8(buf, 4), ]; let port = Self::read_u16(buf, 5);
let id_len = Self::read_u8(buf, 7) as usize; let id = from_utf8(&buf[8..8 + id_len]).map_err(|_| PacketError::FailedToRead)?;
Ok(Packet::Register { ip, port, id }) } 3 => { let timestamp = Self::read_i64(buf, 1);
Ok(Packet::TimeSync(timestamp)) } 4 => Ok(Packet::State(State::Off)), 5 => { let red = Self::read_u8(buf, 1); let green = Self::read_u8(buf, 2); let blue = Self::read_u8(buf, 3);
Ok(Packet::State(State::Color(Color(red, green, blue)))) } 6 => { let brightness = Self::read_u8(buf, 1);
Ok(Packet::State(State::Sun(brightness))) } _ => Err(PacketError::UnknownType), } }
fn read_i64(buf: &[u8], offset: usize) -> i64 { i64::from_be_bytes([ buf[offset], buf[offset + 1], buf[offset + 2], buf[offset + 3], buf[offset + 4], buf[offset + 5], buf[offset + 6], buf[offset + 7], ]) }
fn read_u32(buf: &[u8], offset: usize) -> u32 { u32::from_be_bytes([ buf[offset], buf[offset + 1], buf[offset + 2], buf[offset + 3], ]) }
fn read_u16(buf: &[u8], offset: usize) -> u16 { u16::from_be_bytes([buf[offset], buf[offset + 1]]) }
fn read_u8(buf: &[u8], offset: usize) -> u8 { buf[offset] }}