summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzirkonya <zirkonya@iridium.lan>2026-08-25 18:41:28 +0200
committerzirkonya <zirkonya@iridium.lan>2026-08-25 18:41:28 +0200
commit8bae725a803ee00bf5bc86b9fc0be6853b95115e (patch)
tree1a62d1f61191fb3993a1e3d81f34653fe7a10991
parent7297bbb864778814ed59e99d0d6b05853704f06d (diff)
Add getset ; prepare event and backend
-rw-r--r--Cargo.lock70
-rw-r--r--Cargo.toml1
-rw-r--r--src/backend.rs1
-rw-r--r--src/codec/decode.rs3
-rw-r--r--src/codec/encode.rs21
-rw-r--r--src/codec/error.rs2
-rw-r--r--src/context.rs5
-rw-r--r--src/event.rs94
-rw-r--r--src/event/handler.rs2
-rw-r--r--src/event/listener.rs1
-rw-r--r--src/lib.rs3
-rw-r--r--src/types/prefix/count.rs4
-rw-r--r--src/types/prefix/length.rs11
13 files changed, 204 insertions, 14 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 218b486..b9bf857 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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",
+]
diff --git a/Cargo.toml b/Cargo.toml
index 07c20eb..776e589 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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
diff --git a/src/lib.rs b/src/lib.rs
index ce2b14c..6ec9647 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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)