From e513b3b7e09087fb12c32cefa33aaa3f48c115e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E7=82=8E=E6=B3=BC?= Date: Sat, 13 Apr 2024 22:13:37 +0800 Subject: [PATCH] Improve: `declare_raft_types` allows the types in any order By rewriting the template expanding part with a `#[proc_macro]` `expand!()` defined in `openraft_macros`, `declare_raft_types` does not require the types in fixed order: Example: ``` declare_raft_types!(All: D = (), NodeId = u64, R = (), Node = (), ``` --- openraft/src/lib.rs | 1 + openraft/src/raft/declare_raft_types_test.rs | 8 +- openraft/src/raft/mod.rs | 133 +++---------------- 3 files changed, 29 insertions(+), 113 deletions(-) diff --git a/openraft/src/lib.rs b/openraft/src/lib.rs index bae568d7c..d9d1d82c2 100644 --- a/openraft/src/lib.rs +++ b/openraft/src/lib.rs @@ -21,6 +21,7 @@ macro_rules! func_name { // nn.split("::").last().unwrap_or_default() }}; } +pub extern crate openraft_macros; mod change_members; mod config; diff --git a/openraft/src/raft/declare_raft_types_test.rs b/openraft/src/raft/declare_raft_types_test.rs index 4b978fcfb..593174f35 100644 --- a/openraft/src/raft/declare_raft_types_test.rs +++ b/openraft/src/raft/declare_raft_types_test.rs @@ -7,10 +7,14 @@ use crate::TokioRuntime; declare_raft_types!( All: - D = (), - R = (), NodeId = u64, Node = (), + + /// This is AppData + D = (), + #[allow(dead_code)] + #[allow(dead_code)] + R = (), Entry = crate::Entry, SnapshotData = Cursor>, AsyncRuntime = TokioRuntime, diff --git a/openraft/src/raft/mod.rs b/openraft/src/raft/mod.rs index d16ce7fcc..138b17561 100644 --- a/openraft/src/raft/mod.rs +++ b/openraft/src/raft/mod.rs @@ -102,24 +102,20 @@ use crate::Vote; /// Node = openraft::BasicNode, /// Entry = openraft::Entry, /// SnapshotData = Cursor>, -/// AsyncRuntime = openraft::TokioRuntime, /// Responder = openraft::impls::OneshotResponder, +/// AsyncRuntime = openraft::TokioRuntime, /// ); /// ``` /// -/// **The types must be specified in the exact order**: -/// `D`, `R`, `NodeId`, `Node`, `Entry`, `SnapshotData`, `AsyncRuntime`, `Responder` -/// -/// Types can be omitted, in which case the default type will be used. -/// The default values for each type are: +/// Types can be omitted, and the following default type will be used: /// - `D`: `String` /// - `R`: `String` /// - `NodeId`: `u64` /// - `Node`: `::openraft::impls::BasicNode` /// - `Entry`: `::openraft::impls::Entry` /// - `SnapshotData`: `Cursor>` -/// - `AsyncRuntime`: `::openraft::impls::TokioRuntime` /// - `Responder`: `::openraft::impls::OneshotResponder` +/// - `AsyncRuntime`: `::openraft::impls::TokioRuntime` /// /// For example, to declare with only `D` and `R` types: /// ```ignore @@ -150,111 +146,26 @@ macro_rules! declare_raft_types { $visibility struct $id {} impl $crate::RaftTypeConfig for $id { - $crate::declare_raft_types!(@F_0, $($(#[$inner])* $type_id = $type,)* @T); - } - }; - - // Add explicit type D - (@F_0, $(#[$meta:meta])* D=$t:ty, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { - $(#[$meta])* - type D = $t; - $crate::declare_raft_types!(@F_1, $($(#[$inner])* $type_id = $type,)* @T); - }; - - // Add default type D - (@F_0, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { - type D = String; - $crate::declare_raft_types!(@F_1, $($(#[$inner])* $type_id = $type,)* @T); - }; + // `expand!(KEYED, ...)` ignores the duplicates. + // Thus by appending default types after user defined types, + // the absent user defined types are filled with default types. + $crate::openraft_macros::expand!( + KEYED, + (T, ATTR, V) => {ATTR type T = V;}, + $(($type_id, $(#[$inner])*, $type),)* + + // Default types: + (D , , String ), + (R , , String ), + (NodeId , , u64 ), + (Node , , $crate::impls::BasicNode ), + (Entry , , $crate::impls::Entry ), + (SnapshotData , , Cursor> ), + (Responder , , $crate::impls::OneshotResponder ), + (AsyncRuntime , , $crate::impls::TokioRuntime ), + ); - (@F_1, $(#[$meta:meta])* R=$t:ty, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { - $(#[$meta])* - type R = $t; - $crate::declare_raft_types!(@F_2, $($(#[$inner])* $type_id = $type,)* @T); - }; - - (@F_1, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { - type R = String; - $crate::declare_raft_types!(@F_2, $($(#[$inner])* $type_id = $type,)* @T); - }; - - (@F_2, $(#[$meta:meta])* NodeId=$t:ty, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { - $(#[$meta])* - type NodeId = $t; - $crate::declare_raft_types!(@F_3, $($(#[$inner])* $type_id = $type,)* @T); - }; - - (@F_2, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { - type NodeId = u64; - $crate::declare_raft_types!(@F_3, $($(#[$inner])* $type_id = $type,)* @T); - }; - - (@F_3, $(#[$meta:meta])* Node=$t:ty, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { - $(#[$meta])* - type Node = $t; - $crate::declare_raft_types!(@F_4, $($(#[$inner])* $type_id = $type,)* @T); - }; - - (@F_3, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { - type Node = $crate::impls::BasicNode; - $crate::declare_raft_types!(@F_4, $($(#[$inner])* $type_id = $type,)* @T); - }; - - (@F_4, $(#[$meta:meta])* Entry=$t:ty, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { - $(#[$meta])* - type Entry = $t; - $crate::declare_raft_types!(@F_5, $($(#[$inner])* $type_id = $type,)* @T); - }; - - (@F_4, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { - type Entry = $crate::impls::Entry; - $crate::declare_raft_types!(@F_5, $($(#[$inner])* $type_id = $type,)* @T); - }; - - (@F_5, $(#[$meta:meta])* SnapshotData=$t:ty, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { - $(#[$meta])* - type SnapshotData = $t; - $crate::declare_raft_types!(@F_6, $($(#[$inner])* $type_id = $type,)* @T); - }; - - (@F_5, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { - type SnapshotData = Cursor>; - $crate::declare_raft_types!(@F_6, $($(#[$inner])* $type_id = $type,)* @T); - }; - - (@F_6, $(#[$meta:meta])* AsyncRuntime=$t:ty, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { - $(#[$meta])* - type AsyncRuntime = $t; - $crate::declare_raft_types!(@F_7, $($(#[$inner])* $type_id = $type,)* @T); - }; - - (@F_6, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { - type AsyncRuntime = $crate::impls::TokioRuntime; - $crate::declare_raft_types!(@F_7, $($(#[$inner])* $type_id = $type,)* @T); - }; - - (@F_7, $(#[$meta:meta])* Responder=$t:ty, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { - $(#[$meta])* - type Responder = $t; - $crate::declare_raft_types!(@F_8, $($(#[$inner])* $type_id = $type,)* @T); - }; - - (@F_7, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T) => { - type Responder = $crate::impls::OneshotResponder; - $crate::declare_raft_types!(@F_8, $($(#[$inner])* $type_id = $type,)* @T); - }; - - (@F_8, @T ) => {}; - - // Match any non-captured items to raise compile error - (@F_8, $($(#[$inner:meta])* $type_id:ident = $type:ty,)* @T ) => { - compile_error!( - stringify!( - Type not in its expected position: - $($type_id=$type,)* - types must present in this order: D, R, NodeId, Node, Entry, SnapshotData, AsyncRuntime, Responder - ) - ); + } }; }