ドキュメント
Rust での簡単なプロトコル定義。
このクレートは型に追加できるカスタム派生を追加し、任意の IO ストリームから構造化データを送受信できるようにします。
ネットワークが組み込まれており、TCP と UDP を特別にサポートします。
定義したプロトコルはネットワークの外でも使用できます。Parcel Parcel::from_raw_bytes
とParcel::raw_bytes
メソッドを参照してください。
このクレートには次のものも含まれます。
Parcel
の送受信を容易にする TCP および UDP モジュール使用方法については、サンプル フォルダーをチェックアウトしてください。
これをCargo.toml
に追加します。
[ dependencies ]
protocol = { version = " 3.4 " , features = [ " derive " ] }
次に、 #[derive(protocol::Protocol)]
属性を使用して型を定義します。
# [ derive ( protocol :: Protocol ) ]
struct Hello {
pub a : String ,
pub b : u32 ,
}
ここで最も興味深い部分はprotocol::Parcel
特性です。この特性を実装する型はすべて、バイト ストリームとの間でシリアル化できます。すべてのプリミティブ型、標準コレクション、タプル、および配列はこの特性を実装します。
このクレートは、独自のParcel
タイプを定義する場合に特に役立ちます。 #[derive(protocol::Protocol)]
を使用してこれを行うことができます。型でParcel
実装するには、 Clone
、 Debug
、およびPartialEq
も実装する必要があることに注意してください。
# [ derive ( Parcel , Clone , Debug , PartialEq ) ]
pub struct Health ( f32 ) ;
# [ derive ( Parcel , Clone , Debug , PartialEq ) ]
pub struct SetPlayerPosition {
pub position : ( f32 , f32 ) ,
pub health : Health ,
pub values : Vec < String > ,
}
任意のユーザー定義型には、自動的に派生されたParcel
特性を含めることができます。
# [ derive ( protocol :: Protocol , Clone , Debug , PartialEq ) ]
pub struct Handshake ;
# [ derive ( protocol :: Protocol , Clone , Debug , PartialEq ) ]
pub struct Hello {
id : i64 ,
data : Vec < u8 > ,
}
# [ derive ( protocol :: Protocol , Clone , Debug , PartialEq ) ]
pub struct Goodbye {
id : i64 ,
reason : String ,
}
# [ derive ( protocol :: Protocol , Clone , Debug , PartialEq ) ]
pub struct Node {
name : String ,
enabled : bool
}
# [ protocol ( discriminant = "integer" ) ]
# [ derive ( protocol :: Protocol , Clone , Debug , PartialEq ) ]
pub enum PacketKind {
# [ protocol ( discriminator ( 0x00 ) ) ]
Handshake ( Handshake ) ,
# [ protocol ( discriminator ( 0xaa ) ) ]
Hello ( Hello ) ,
# [ protocol ( discriminator ( 0xaf ) ) ]
Goodbye ( Goodbye ) ,
}
fn main ( ) {
use std :: net :: TcpStream ;
let stream = TcpStream :: connect ( "127.0.0.1:34254" ) . unwrap ( ) ;
let mut connection = protocol :: wire :: stream :: Connection :: new ( stream , protocol :: wire :: middleware :: pipeline :: default ( ) ) ;
connection . send_packet ( & Packet :: Handshake ( Handshake ) ) . unwrap ( ) ;
connection . send_packet ( & Packet :: Hello ( Hello { id : 0 , data : vec ! [ 55 ] } ) ) . unwrap ( ) ;
connection . send_packet ( & Packet :: Goodbye ( Goodbye { id : 0 , reason : "leaving" . to_string ( ) } ) ) . unwrap ( ) ;
loop {
if let Some ( response ) = connection . receive_packet ( ) . unwrap ( ) {
println ! ( "{:?}" , response ) ;
break ;
}
}
}
Enum 値は、1 から始まるバリアント インデックスによって送信することも、各バリアントの文字列名を送信することによって送信することもできます。
注:デフォルトの動作では、バリアント名を文字列( string
) として使用します。
この動作は#[protocol(discriminant = "<type>")]
属性によって変更できます。
サポートされている判別式のタイプ:
string
(デフォルト)integer
# [ derive ( protocol :: Protocol , Clone , Debug , PartialEq ) ]
# [ protocol ( discriminant = "string" ) ]
pub enum PlayerState {
Stationary ,
Flying { velocity : ( f32 , f32 , f32 ) } ,
// Discriminators can be explicitly specified.
# [ protocol ( discriminator ( "ArbitraryOverTheWireName" ) ) ]
Jumping { height : f32 } ,
}
シリアル化に合わせてバリアントの名前を変更できます。
# [ derive ( protocol :: Protocol , Clone , Debug , PartialEq ) ]
# [ protocol ( discriminant = "string" ) ]
pub enum Foo {
Bar ,
# [ protocol ( name = "Biz" ) ] // the Bing variant will be send/received as 'Biz'.
Bing ,
Baz ,
}