diff options
| author | zirkonya <zirkonya@iridium.lan> | 2026-08-25 18:41:28 +0200 |
|---|---|---|
| committer | zirkonya <zirkonya@iridium.lan> | 2026-08-25 18:41:28 +0200 |
| commit | 8bae725a803ee00bf5bc86b9fc0be6853b95115e (patch) | |
| tree | 1a62d1f61191fb3993a1e3d81f34653fe7a10991 | |
| parent | 7297bbb864778814ed59e99d0d6b05853704f06d (diff) | |
Add getset ; prepare event and backend
| -rw-r--r-- | Cargo.lock | 70 | ||||
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | src/backend.rs | 1 | ||||
| -rw-r--r-- | src/codec/decode.rs | 3 | ||||
| -rw-r--r-- | src/codec/encode.rs | 21 | ||||
| -rw-r--r-- | src/codec/error.rs | 2 | ||||
| -rw-r--r-- | src/context.rs | 5 | ||||
| -rw-r--r-- | src/event.rs | 94 | ||||
| -rw-r--r-- | src/event/handler.rs | 2 | ||||
| -rw-r--r-- | src/event/listener.rs | 1 | ||||
| -rw-r--r-- | src/lib.rs | 3 | ||||
| -rw-r--r-- | src/types/prefix/count.rs | 4 | ||||
| -rw-r--r-- | src/types/prefix/length.rs | 11 |
13 files changed, 204 insertions, 14 deletions
@@ -3,5 +3,75 @@ version = 4 [[package]] +name = "getset" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cf442baaabe4213ce7d1239afc26c039180b6456da2cededa316ae2c8a77a77" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "proc-macro2" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] name = "zr_protocol" version = "0.1.1" +dependencies = [ + "getset", + "zr_protocol_macros", +] + +[[package]] +name = "zr_protocol_macros" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] @@ -4,6 +4,7 @@ version = "0.1.1" edition = "2024" [dependencies] +getset = "0.1.7" zr_protocol_macros = { version = "0.1.0", path = "macros", optional = true } [features] diff --git a/src/backend.rs b/src/backend.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/backend.rs @@ -0,0 +1 @@ + diff --git a/src/codec/decode.rs b/src/codec/decode.rs index 31ed725..fa4ae95 100644 --- a/src/codec/decode.rs +++ b/src/codec/decode.rs @@ -1,3 +1,4 @@ +//! Decoding: reading protocol values from a byte stream. use std::{io::Read, sync::Arc}; use crate::{DEFAULT_BUFFER_LEN, codec::error::Result}; @@ -5,6 +6,7 @@ use crate::{DEFAULT_BUFFER_LEN, codec::error::Result}; macro_rules! impl_decode { ($type: ty) => { impl<Ctx> Decode<Ctx> for $type { + // decode number using big endian fn decode(reader: &mut dyn Read, _: &mut Ctx) -> Result<Self> where Self: Sized, @@ -18,6 +20,7 @@ macro_rules! impl_decode { }; } +/// Read a value from a byte stream pub trait Decode<Ctx> { fn decode(reader: &mut dyn Read, ctx: &mut Ctx) -> Result<Self> where diff --git a/src/codec/encode.rs b/src/codec/encode.rs index bd76605..c8d1c7b 100644 --- a/src/codec/encode.rs +++ b/src/codec/encode.rs @@ -1,9 +1,11 @@ +//! Encoding: writing protocol values into a byte stream. use crate::codec::error::Error; use std::{io::Write, sync::Arc}; macro_rules! impl_encode { ($t: ty) => { impl<Ctx> Encode<Ctx> for $t { + /// write number using big endian fn encode(&self, buffer: &mut dyn Write, _: &mut Ctx) -> Result<usize, Error> { let size = buffer.write(&self.to_be_bytes())?; Ok(size) @@ -12,6 +14,7 @@ macro_rules! impl_encode { }; } +/// Write a value into a byte stream pub trait Encode<Ctx> { fn encode(&self, buffer: &mut dyn Write, ctx: &mut Ctx) -> Result<usize, Error>; } @@ -24,21 +27,24 @@ impl<Ctx> Encode<Ctx> for bool { } impl<Ctx, T: Encode<Ctx>> Encode<Ctx> for Option<T> { + /// Encode `T` if Some(T) or do nothing if None fn encode(&self, buffer: &mut dyn Write, ctx: &mut Ctx) -> Result<usize, Error> { match self { Some(val) => { - let mut size = 1u8.encode(buffer, ctx)?; - size += val.encode(buffer, ctx)?; + let size = val.encode(buffer, ctx)?; Ok(size) } - None => 0u8.encode(buffer, ctx), + None => Ok(0), } } } impl<Ctx, T: Encode<Ctx>> Encode<Ctx> for Vec<T> { + /// Encode each element of vector + /// use `CountPrefix` to prefix the vector with number of elements + /// use `LenPrefix` to prefix the vector with encoded byte size fn encode(&self, buffer: &mut dyn Write, ctx: &mut Ctx) -> Result<usize, Error> { - let mut size = self.len().encode(buffer, ctx)?; + let mut size = 0; for item in self { size += item.encode(buffer, ctx)?; } @@ -47,6 +53,9 @@ impl<Ctx, T: Encode<Ctx>> Encode<Ctx> for Vec<T> { } impl<Ctx> Encode<Ctx> for String { + /// Encode the string using utf8 + /// use `CountPrefix` to prefix the string with char length + /// use `LenPrefix` to prefix the string with utf8 bytes length fn encode(&self, buffer: &mut dyn Write, _: &mut Ctx) -> Result<usize, Error> { let utf8 = self.as_bytes(); buffer.write_all(utf8)?; @@ -55,6 +64,8 @@ impl<Ctx> Encode<Ctx> for String { } impl<Ctx> Encode<Ctx> for Arc<[u8]> { + /// write raw slice into the buffer + /// use `LenPrefix` to prefix with byte length fn encode(&self, buffer: &mut dyn Write, _: &mut Ctx) -> Result<usize, Error> { let len = buffer.write(self)?; Ok(len) @@ -62,6 +73,8 @@ impl<Ctx> Encode<Ctx> for Arc<[u8]> { } impl<Ctx, const S: usize> Encode<Ctx> for [u8; S] { + /// write raw slice into the buffer + /// use `LenPrefix` to prefix with byte length fn encode(&self, buffer: &mut dyn Write, _ctx: &mut Ctx) -> Result<usize, Error> { let len = buffer.write(self)?; Ok(len) diff --git a/src/codec/error.rs b/src/codec/error.rs index 6037a9a..c1bd4f7 100644 --- a/src/codec/error.rs +++ b/src/codec/error.rs @@ -1,5 +1,7 @@ use std::fmt::Display; +// TODO : better error (using thiserror) + #[derive(Debug)] pub enum Error { IoError(std::io::Error), diff --git a/src/context.rs b/src/context.rs index 47661d0..8b13789 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,6 +1 @@ -use std::any::Any; -pub trait Context { - fn get(&self, key: &str) -> Option<&dyn Any>; - fn set(&mut self, key: &str, value: &dyn Any); -} diff --git a/src/event.rs b/src/event.rs new file mode 100644 index 0000000..bbba586 --- /dev/null +++ b/src/event.rs @@ -0,0 +1,94 @@ +use std::{io, net::SocketAddr, time::Instant}; + +use getset::{Getters, Setters}; + +pub mod handler; +pub mod listener; + +pub enum EventKind<Packet, Uid = u64> +where + Uid: PartialEq, +{ + Connection(ConnectionEvent<Uid>), + PacketReceived(PacketReceivedEvent<Packet>), + PacketSent(PacketSentEvent<Packet>), + Disconnect(DisconnectEvent<Uid>), +} + +// TODO : identification +// TODO : reason type +#[derive(Getters)] +pub struct ConnectionEvent<Uid> +where + Uid: PartialEq, +{ + #[getset(get = "pub")] + peer_addr: SocketAddr, + #[getset(get = "pub")] + local_addr: SocketAddr, + #[getset(get = "pub")] + connection_id: Uid, +} +#[derive(Getters)] +pub struct PacketReceivedEvent<Packet> { + #[getset(get = "pub")] + packet: Packet, +} +#[derive(Getters)] +pub struct PacketSentEvent<Packet> { + #[getset(get = "pub")] + packet: Packet, +} + +// TODO : better error type for protocol violation +pub type ProtocolViolation = String; + +pub enum DisconnectReason { + Normal, + Error(io::Error), + ProtocolError(ProtocolViolation), + Timeout, + ServerShutdown, +} + +#[derive(Getters)] +pub struct DisconnectEvent<Uid> +where + Uid: PartialEq, +{ + #[getset(get = "pub")] + connection_id: Uid, + #[getset(get = "pub")] + reason: DisconnectReason, +} + +#[derive(Getters, Setters)] +pub struct Event<Packet, Uid = u64> +where + Uid: PartialEq, +{ + #[getset(get = "pub")] + instant: Instant, + #[getset(get = "pub", set = "pub")] + canceled: bool, + #[getset(get = "pub")] + kind: EventKind<Packet, Uid>, +} + +impl<Packet> Event<Packet> { + pub fn new(kind: EventKind<Packet>) -> Self { + Self { + instant: Instant::now(), + canceled: false, + kind, + } + } + + pub fn differed(when: Instant, kind: EventKind<Packet>) -> Self { + Self { + instant: when, + canceled: false, + kind, + } + } +} diff --git a/src/event/handler.rs b/src/event/handler.rs new file mode 100644 index 0000000..7d8b5b5 --- /dev/null +++ b/src/event/handler.rs @@ -0,0 +1,2 @@ +// TODO : dispatch event through all listener +// TODO : maybe compile listener into one ? diff --git a/src/event/listener.rs b/src/event/listener.rs new file mode 100644 index 0000000..178dda8 --- /dev/null +++ b/src/event/listener.rs @@ -0,0 +1 @@ +// TODO : Listener ; interface to perform action when event occured @@ -1,5 +1,8 @@ +#[doc = include_str!("../README.md")] +pub mod backend; pub mod codec; pub mod context; +pub mod event; pub mod types; #[cfg(feature = "macros")] diff --git a/src/types/prefix/count.rs b/src/types/prefix/count.rs index 5f53e08..0896167 100644 --- a/src/types/prefix/count.rs +++ b/src/types/prefix/count.rs @@ -1,14 +1,18 @@ use std::{io::Read, marker::PhantomData}; +use getset::Getters; + use crate::{ codec::{Codec, decode::Decode, encode::Encode}, types::size::Size, }; +#[derive(Getters)] pub struct CountPrefix<I, L, D> where D: IntoIterator<Item = I>, { + #[getset(get = "pub")] data: D, _len: PhantomData<L>, } diff --git a/src/types/prefix/length.rs b/src/types/prefix/length.rs index 160fffc..3bb150a 100644 --- a/src/types/prefix/length.rs +++ b/src/types/prefix/length.rs @@ -1,12 +1,16 @@ use std::{io::Write, marker::PhantomData}; +use getset::Getters; + use crate::{ DEFAULT_BUFFER_LEN, codec::{self, Codec, decode::Decode, encode::Encode}, types::size::Size, }; +#[derive(Getters)] pub struct LenPrefixed<L, D> { + #[getset(get = "pub")] data: D, _len: PhantomData<L>, } @@ -46,16 +50,13 @@ impl<L, D> AsMut<D> for LenPrefixed<L, D> { impl<L, D, Ctx> Encode<Ctx> for LenPrefixed<L, D> where - L: Codec<Ctx> + Size + TryFrom<usize>, + L: Codec<Ctx> + Size, D: Codec<Ctx>, { fn encode(&self, writer: &mut dyn Write, ctx: &mut Ctx) -> Result<usize, codec::error::Error> { let mut buf = Vec::with_capacity(DEFAULT_BUFFER_LEN); self.data.encode(&mut buf, ctx)?; - let len: L = buf - .len() - .try_into() - .map_err(|_| codec::error::Error::Custom("length exceeds prefix capacity".into()))?; + let len = L::from_size(buf.len()); let mut l = len.encode(writer, ctx)?; l += writer.write(&buf)?; Ok(l) |
