summaryrefslogtreecommitdiff
path: root/tests/tmp/todo.md
diff options
context:
space:
mode:
authorzirkonya <zirkonya@iridium.lan>2026-09-01 09:51:18 +0200
committerzirkonya <zirkonya@iridium.lan>2026-09-01 09:51:18 +0200
commitbe62f065a62048b798e8bb2b8e3699bdd5b6d517 (patch)
tree8b3f4b05838b5fa34c3ae24e35004343baadf2af /tests/tmp/todo.md
parentfdc02f07cbd1994c1efb057f24a37a96faaa51fa (diff)
add proc macros ; benchmark ; example
Diffstat (limited to 'tests/tmp/todo.md')
-rw-r--r--tests/tmp/todo.md356
1 files changed, 0 insertions, 356 deletions
diff --git a/tests/tmp/todo.md b/tests/tmp/todo.md
deleted file mode 100644
index a0c6a83..0000000
--- a/tests/tmp/todo.md
+++ /dev/null
@@ -1,356 +0,0 @@
-# zr_protocol - Todo V1
-
-> Crate Rust de communication réseau : protocole custom, sérialisation binaire, proc-macro pour définir des packets via un format `.packet`.
-
----
-
-## Phase 0 — Workspace & Scaffold
-
-- [ ] **0.1** Créer le workspace virtuel `Cargo.toml` à la racine (members: `zr-protocol`, `zr-protocol-macros`)
-- [ ] **0.2** Créer le crate `zr-protocol/` (library, edition 2024)
- - [ ] `Cargo.toml` avec dépendances : `bytes = "1"`, `thiserror = "2"`, features optionnelles (`tokio`, `serde`, `derive`)
- - [ ] `src/lib.rs` avec modules déclarés : `encode`, `decode`, `packet`, `codec`, `framing`, `builder`, `error`, `impls`
-- [ ] **0.3** Créer le crate `zr-protocol-macros/` (proc-macro = true, edition 2024)
- - [ ] `Cargo.toml` avec dépendances : `syn = { version = "2", features = ["full"] }`, `quote = "1"`, `proc-macro2 = "1"`
- - [ ] `src/lib.rs` minimal (entry point vide)
-- [ ] **0.4** Supprimer les anciens fichiers `src/bin/client.rs` et `src/bin/server.rs` ( remplacer par des exemples dans `examples/` )
-- [ ] **0.5** Vérifier que `cargo check --workspace` compile sans erreur
-- [ ] **0.6** Créer la structure de dossiers dans les deux crates :
- - `zr-protocol/src/encode.rs`, `decode.rs`, `packet.rs`, `codec.rs`, `framing.rs`, `builder.rs`, `error.rs`
- - `zr-protocol/src/impls/mod.rs`, `primitives.rs`, `arrays.rs`, `option.rs`
- - `zr-protocol-macros/src/parser/ast.rs`, `lexer.rs`, `grammar.rs`, `mod.rs`
- - `zr-protocol-macros/src/codegen/struct_gen.rs`, `encode_gen.rs`, `decode_gen.rs`, `registry_gen.rs`, `mod.rs`
- - `examples/login/packets/`, `examples/login/server.rs`, `examples/login/client.rs`
- - `tests/` (racine workspace)
-
----
-
-## Phase 1 — Traits Core : `Encode` & `Decode`
-
-> Les traits fondamentaux de sérialisation/déserialization binaire.
-
-- [ ] **1.1** Définir `src/error.rs` — type d'erreur `ZrError`
- ```rust
- use thiserror::Error;
- #[derive(Debug, Error)]
- pub enum ZrError {
- #[error("io error: {0}")]
- Io(#[from] std::io::Error),
- #[error("invalid packet id: 0x{0:02X}")]
- InvalidPacketId(u32),
- #[error("buffer underflow: expected {expected} bytes, got {got}")]
- Underflow { expected: usize, got: usize },
- #[error("packet too large: {0} bytes (max {1})")]
- PacketTooLarge(usize, usize),
- #[error("unknown field type: {0}")]
- UnknownType(String),
- #[error("decode error: {0}")]
- Decode(String),
- }
- ```
-- [ ] **1.2** Définir `src/encode.rs` — trait `Encode`
- ```rust
- pub trait Encode {
- fn encode(&self, buf: &mut BytesMut) -> io::Result<()>;
- fn encoded_size(&self) -> usize; // optionnel, pour pré-réserver
- }
- ```
-- [ ] **1.3** Définir `src/decode.rs` — trait `Decode`
- ```rust
- pub trait Decode: Sized {
- fn decode(buf: &mut BytesMut) -> io::Result<Self>;
- }
- ```
-- [ ] **1.4** Impl `Encode` pour les types primitifs dans `src/impls/primitives.rs`
- - `u8`, `u16`, `u32`, `u64`, `u128`
- - `i8`, `i16`, `i32`, `i64`, `i128`
- - `bool` (1 octet : 0x00 = false, 0x01 = true)
- - `f32`, `f64` (via `to_be_bytes()` / `to_le_bytes()`)
- - Tous en big-endian par défaut (network byte order)
-- [ ] **1.5** Impl `Encode` pour `String` et `Vec<u8>`
- - Format : `u32` (longueur en octets) + octets bruts
-- [ ] **1.6** Impl `Encode` pour `[u8; N]` dans `src/impls/arrays.rs` (écriture directe, pas de longueur)
-- [ ] **1.7** Impl `Encode` pour `Option<T: Encode>` dans `src/impls/option.rs`
- - Format : `u8` tag (0x00 = None, 0x01 = Some) + données si Some
-- [ ] **1.8** Impl `Decode` pour tous les mêmes types (mirror de 1.4 à 1.7)
- - Avec gestion propre des erreurs (underflow → `ZrError::Underflow`)
-- [ ] **1.9** Impl `Encode`/`Decode` pour `Vec<T: Encode/Decode>`
- - Format : `u32` nombre d'éléments + sérialisation de chaque élément
-- [ ] **1.10** Tests unitaires pour chaque type implémenté
- - Roundtrip : encode → decode → assert_eq
- - Cas limites : chaîne vide, vec vide, None, MAX values
-
----
-
-## Phase 2 — Trait `PacketMeta` & Types Runtime
-
-> Métadonnées des packets et typage dynamique.
-
-- [ ] **2.1** Définir `src/packet.rs` — trait `PacketMeta`
- ```rust
- pub trait PacketMeta {
- const ID: u32;
- const NAME: &'static str;
- const SIZE_HINT: Option<usize>;
- }
- ```
-- [ ] **2.2** Définir un enum `PacketId` (ou type alias `u32`) pour les IDs réservés
- - Réservé `0x00` = Reserved, `0xFF` = KeepAlive/Ping
-- [ ] **2.3** Définir `pub struct ZrPacket` (wrapper type-érasé pour le codec)
- ```rust
- pub struct ZrPacket {
- pub id: u32,
- pub payload: BytesMut,
- }
- ```
-- [ ] **2.4** Définir `pub trait IntoZrPacket: PacketMeta + Encode` pour convertir un typed packet → `ZrPacket`
-- [ ] **2.5** Tests pour `PacketMeta` et `ZrPacket`
-
----
-
-## Phase 3 — Format `.packet` : Lexer & Parser
-
-> Parsing du format texte de définition de protocole.
-
-- [ ] **3.1** Définir l'AST dans `zr-protocol-macros/src/parser/ast.rs`
- ```rust
- pub struct ProtocolFile {
- pub packets: Vec<PacketDef>,
- }
- pub struct PacketDef {
- pub attributes: Vec<Attribute>,
- pub name: Ident,
- pub id: u32,
- pub fields: Vec<FieldDef>,
- }
- pub struct FieldDef {
- pub attributes: Vec<Attribute>,
- pub name: Ident,
- pub ty: TypeRef,
- }
- pub enum TypeRef {
- Primitive(String), // u32, String, bool, etc.
- Option(Box<TypeRef>), // Option<T>
- Vec(Box<TypeRef>), // Vec<T>
- Array(String, usize), // [u8; 64]
- Custom(String), // un autre type packet
- }
- pub struct Attribute {
- pub name: String,
- pub value: Option<String>,
- }
- ```
-- [ ] **3.2** Implémenter le lexer dans `zr-protocol-macros/src/parser/lexer.rs`
- - Tokens : `Packet`, `Ident`, `Number` (hex 0x.. et décimal), `Colon`, `BraceOpen`, `BraceClose`, `BracketOpen`, `BracketClose`, `Eq`, `String`, `Comma`, `EndAttribute`, `Hash`
- - Whitespace et comments (`//`) ignorés
-- [ ] **3.3** Implémenter le parser dans `zr-protocol-macros/src/parser/grammar.rs`
- - Parse un `ProtocolFile` à partir de tokens
- - Validation : nom unique, ID unique, types connus
- - Erreurs avec span (ligne/colonne) pour de bons messages d'erreur
-- [ ] **3.4** Tests du parser :
- - [ ] Format valide basique
- - [ ] Attributs optionnels (`#[endian = "big"]`)
- - [ ] Types `Option<T>`, `Vec<T>`, `[u8; N]`
- - [ ] Erreur : type inconnu
- - [ ] Erreur : syntaxe invalide
- - [ ] Erreur : ID manquant
- - [ ] Fichier vide (pas de packet)
-
----
-
-## Phase 4 — Proc-macro `packet!`
-
-> Génération de code Rust à partir du format `.packet`.
-
-- [ ] **4.1** Implémenter l'entry point `packet!` dans `zr-protocol-macros/src/lib.rs`
- - Accepte `include!("path/to/file.packet")` OU du code inline
- - Lit le fichier via `CARGO_MANIFEST_DIR` + chemin relatif
-- [ ] **4.2** Codegen struct dans `zr-protocol-macros/src/codegen/struct_gen.rs`
- - Génère `#[derive(Debug, Clone)] pub struct NomPacket { pub field: Type, ... }`
- - Gère `Option<T>` → `Option<T>`, `Vec<T>` → `Vec<T>`, `[u8; N]` → `[u8; N]`
-- [ ] **4.3** Codegen `impl PacketMeta` dans `zr-protocol-macros/src/codegen/registry_gen.rs`
- - `const ID: u32 = ...; const NAME: &'static str = "..."; const SIZE_HINT: Option<usize> = None;`
-- [ ] **4.4** Codegen `impl Encode` dans `zr-protocol-macros/src/codegen/encode_gen.rs`
- - Pour chaque champ : `Encode::encode(&self.champ, buf)?;`
-- [ ] **4.5** Codegen `impl Decode` dans `zr-protocol-macros/src/codegen/decode_gen.rs`
- - Pour chaque champ : `champ: Decode::decode(buf)?`
-- [ ] **4.6** Codegen registry globale (un seul `match` ID → nom) dans `registry_gen.rs`
- - Fonction `pub fn packet_name_by_id(id: u32) -> Option<&'static str>`
-- [ ] **4.7** Codegen `impl IntoZrPacket` pour chaque packet
- - Sérialise → `ZrPacket { id, payload }`
-- [ ] **4.8** Gestion des attributs dans le codegen
- - `#[endian = "big"]` → big-endian (défaut), `#[endian = "little"]` → little-endian
- - `#[skip_if_none]` → ne sérialise pas le champ si `None` (sans le tag)
-- [ ] **4.9** Tests d'intégration :
- - [ ] Un fichier `.packet` simple → compiles, encode/decode roundtrip
- - [ ] Fichier avec `Option<T>` et `Vec<T>`
- - [ ] Compilation échoue sur type inconnu (trybuild)
- - [ ] Compilation échoue sur syntaxe invalide (trybuild)
-- [ ] **4.10** Macro `packet!` inline (pour les petits définitions sans fichier)
- ```rust
- packet! {
- packet Ping 0xFF {
- sequence: u32,
- }
- }
- ```
-
----
-
-## Phase 5 — Builder Pattern (secondaire)
-
-> API alternative pour construire des packets sans struct literals.
-
-- [ ] **5.1** Définir le trait `PacketBuilder` dans `src/builder.rs`
- ```rust
- pub trait PacketBuilder: Sized {
- type Packet: Encode + PacketMeta;
- fn new() -> Self;
- fn field<T: IntoFieldValue>(mut self, name: &str, value: T) -> Self;
- fn build(self) -> io::Result<Self::Packet>;
- }
- ```
-- [ ] **5.2** Codegen du builder dans `zr-protocol-macros/src/codegen/builder_gen.rs`
- - Génère une struct `NomPacketBuilder { username: Option<String>, ... }` avec chaque champ en `Option`
- - `field()` matche sur le nom (string) et set la valeur
- - `build()` vérifie que tous les champs sont présents, sinon erreur
-- [ ] **5.3** Opt-out via attribute : `#[packet(no_builder)]` désactive la génération du builder
-- [ ] **5.4** Tests :
- - [ ] Builder crée un packet valide
- - [ ] Builder erreur si champ manquant
- - [ ] `#[packet(no_builder)]` ne génère pas le builder
-
----
-
-## Phase 6 — Feature Flags & Extensibilité
-
-> Support optionnel de crates externes.
-
-- [ ] **6.1** Feature `tokio` : active les dépendances `tokio` + `tokio-util`
- - Active le module `codec.rs` et `framing.rs`
-- [ ] **6.2** Feature `serde` : active `serde` + `bincode`
- - Génère `#[derive(serde::Serialize, serde::Deserialize)]` sur les structs via le proc-macro
- - Attribut `#[packet(serde)]` pour forcer ou `#[packet(no_serde)]` pour désactiver par packet
-- [ ] **6.3** Feature `derive` : active `zr-protocol-macros`
- - Les macros `packet!`, `include_packets!` ne sont disponibles que avec cette feature
-- [ ] **6.4** Feature `std` (défaut) : support `String`, `Vec`, etc.
- - Feature `no_std` future (pas v1) : uniquement `[u8; N]`, `u8`, etc.
-- [ ] **6.5** Documentation des features dans le `Cargo.toml` et `lib.rs`
-
----
-
-## Phase 7 — Codec & Framing (tokio-util)
-
-> Intégration avec tokio pour la communication async.
-
-- [ ] **7.1** Implémenter `src/framing.rs` — length-prefix framing
- - Header : `u32` big-endian = longueur du payload
- - Configurable : taille du header (2 ou 4 octets), endianness
- - `max_packet_size` avec défaut (ex: 16 Mo)
-- [ ] **7.2** Implémenter `src/codec.rs` — `ZrCodec`
- - `impl Encoder<Box<dyn Encode>> for ZrCodec` — écrit header + payload
- - `impl Decoder for ZrCodec` — lit header, vérifie taille, lit payload, retourne `ZrPacket`
- - Gestion propre de `BytesMut` (reserve, split_to, advance)
-- [ ] **7.3** Type `FramedPacket` pour le dispatch dynamique
- - Le codec lit l'ID depuis le payload, lookup dans la registry
- - Retourne un `ZrPacket` (type-érasé) que l'utilisateur cast avec un match sur l'ID
-- [ ] **7.4** Helper `fn framed_read(stream) -> impl Stream<Item = ZrPacket>` (optionnel, wrapper)
-- [ ] **7.5** Tests :
- - [ ] Roundtrip TCP : encode → send → receive → decode → assert_eq
- - [ ] Rejet des packets trop gros
- - [ ] Gestion des reads partiels (TCP peut diviser les données)
-
----
-
-## Phase 8 — Client & Server Helpers
-
-> Utilitaires pour simplifier l'usage réseau.
-
-- [ ] **8.1** Struct `ZrConnection` wrapper autour de `Framed<TcpStream, ZrCodec>`
- ```rust
- pub struct ZrConnection {
- framed: Framed<TcpStream, ZrCodec>,
- }
- impl ZrConnection {
- pub async fn connect(addr: &str) -> io::Result<Self>;
- pub async fn send_packet<P: Encode + PacketMeta>(&mut self, packet: &P) -> io::Result<()>;
- pub async fn next_packet(&mut self) -> io::Result<Option<ZrPacket>>;
- }
- ```
-- [ ] **8.2** Struct `ZrListener` wrapper autour de `TcpListener`
- ```rust
- pub struct ZrListener { listener: TcpListener }
- impl ZrListener {
- pub async fn bind(addr: &str) -> io::Result<Self>;
- pub async fn accept(&self) -> io::Result<(ZrConnection, SocketAddr)>;
- }
- ```
-- [ ] **8.3** Macro `#[tokio::main]` compatible — les helpers utilisent tokio derrière
-- [ ] **8.4** Tests d'intégration : client/server qui s'échangent des packets
-
----
-
-## Phase 9 — Exemples
-
-> Démonstrations complètes d'utilisation.
-
-- [ ] **9.1** Exemple `examples/simple.rs` — packet inline, encode/decode sans réseau
-- [ ] **9.2** Exemple `examples/login/` — client/server complet
- - Fichiers `.packet` de définition
- - Server qui écoute, reçoit `LoginRequest`, répond `LoginResponse`
- - Client qui se connecte, envoie `LoginRequest`, lit `LoginResponse`
-- [ ] **9.3** Exemple avec `Option<T>` et `Vec<T>` pour montrer les types composés
-- [ ] **9.4** README avec badges, description, et example usage
-
----
-
-## Phase 10 — Tests & Qualité
-
-> Fiabilité et robustesse.
-
-- [ ] **10.1** Tests unitaires : chaque type primitif encode/decode roundtrip
-- [ ] **10.2** Tests du parser lexer/grammar (bonne et mauvaise syntaxe)
-- [ ] **10.3** Tests trybuild : erreurs de compilation avec bons messages
- - [ ] Type inconnu dans `.packet`
- - [ ] Syntaxe invalide
- - [ ] ID manquant
- - [ ] Champ dupliqué
-- [ ] **10.4** Tests d'intégration TCP : client ↔ server roundtrip
-- [ ] **10.5** Benchmark (criterion) : throughput sérialisation vs bincode
-- [ ] **10.6** `cargo clippy --workspace` sans warning
-- [ ] **10.7** `cargo fmt --check` passe
-
----
-
-## Phase 11 — Documentation
-
-- [ ] **11.1** `README.md` avec description, quick start, features
-- [ ] **11.2** Doc comments (`///`) sur tous les traits publics
-- [ ] **11.3** Doc comments sur le format `.packet` (guide de syntaxe)
-- [ ] **11.4** Exemples dans les doc comments (doc-tests)
-- [ ] **11.5** CHANGELOG.md
-
----
-
-## Ordre d'exécution recommandé
-
-```
-Phase 0 → Phase 1 → Phase 2 → Phase 3 → Phase 4 → Phase 5
- ↓
- Phase 6 (features)
- ↓
- Phase 7 (codec)
- ↓
- Phase 8 → Phase 9 → Phase 10 → Phase 11
-```
-
-**Dépendances critiques :**
-- Phase 4 (proc-macro) dépend de Phase 1 (traits) et Phase 2 (AST)
-- Phase 7 (codec) dépend de Phase 1 (Encode/Decode) et Phase 4 (PacketMeta)
-- Phase 8 (helpers) dépend de Phase 7 (codec)
-- Phase 9-11 dépendent de tout le reste
-
-**Peut être fait en parallèle :**
-- Phase 5 (builder) peut démarrer après Phase 4
-- Phase 6 (features) peut démarrer après Phase 4
-- Les tests (Phase 10) peuvent être écrits au fur et à mesure de chaque phase