{"id":13439862,"url":"https://github.com/dylanmckay/protocol","last_synced_at":"2025-04-04T16:16:02.332Z","repository":{"id":45866409,"uuid":"67912021","full_name":"dylanmckay/protocol","owner":"dylanmckay","description":"Easy protocol definitions in Rust","archived":false,"fork":false,"pushed_at":"2022-09-11T04:35:01.000Z","size":314,"stargazers_count":191,"open_issues_count":12,"forks_count":20,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-28T15:09:57.824Z","etag":null,"topics":["network-programming","rust","tcp","udp"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dylanmckay.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-09-11T05:27:14.000Z","updated_at":"2025-02-27T08:29:16.000Z","dependencies_parsed_at":"2022-09-14T12:01:47.610Z","dependency_job_id":null,"html_url":"https://github.com/dylanmckay/protocol","commit_stats":null,"previous_names":[],"tags_count":67,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dylanmckay%2Fprotocol","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dylanmckay%2Fprotocol/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dylanmckay%2Fprotocol/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dylanmckay%2Fprotocol/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dylanmckay","download_url":"https://codeload.github.com/dylanmckay/protocol/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247208181,"owners_count":20901570,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["network-programming","rust","tcp","udp"],"created_at":"2024-07-31T03:01:17.730Z","updated_at":"2025-04-04T16:16:02.309Z","avatar_url":"https://github.com/dylanmckay.png","language":"Rust","readme":"# protocol\n\n[![Build Status](https://travis-ci.org/dylanmckay/protocol.svg?branch=master)](https://travis-ci.org/dylanmckay/protocol)\n[![Crates.io](https://img.shields.io/crates/v/protocol.svg)](https://crates.io/crates/protocol)\n[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)\n\n[Documentation](https://docs.rs/protocol)\n\nEasy protocol definitions in Rust.\n\nThis crate adds a custom derive that can be added to types, allowing\nstructured data to be sent and received from any IO stream.\n\nNetworking is built-in, with special support for TCP and UDP.\n\nThe protocol you define can be used outside of networking too - see the `Parcel::from_raw_bytes` and `Parcel::raw_bytes` methods.\n\nThis crate also provides:\n\n* [TCP](https://docs.rs/protocol/latest/protocol/wire/stream/index.html) and [UDP](https://docs.rs/protocol/latest/protocol/wire/dgram/index.html) modules for easy sending and receiving of `Parcel`s\n* A generic [middleware](https://docs.rs/protocol/latest/protocol/wire/middleware/index.html) library for automatic transformation of sent/received data\n  * Middleware has already been written to support [compression](https://docs.rs/protocol/latest/protocol/wire/middleware/compression/index.html)\n  * Custom middleware can be implemented via a trait with two methods\n\nCheckout the [examples](./examples) folder for usage.\n\n## Usage\n\nAdd this to your `Cargo.toml`:\n\n```toml\n[dependencies]\nprotocol = { version = \"3.4\", features = [\"derive\"] }\n```\n\nAnd then define a type with the `#[derive(protocol::Protocol)]` attribute:\n\n```rust\n#[derive(protocol::Protocol)]\nstruct Hello {\n    pub a: String,\n    pub b: u32,\n}\n```\n\n## Under the hood\n\nThe most interesting part here is the [`protocol::Parcel`](https://docs.rs/protocol/latest/protocol/trait.Parcel.html) trait. Any type that implements this trait can then be serialized to and from a byte stream. All primitive types, standard collections, tuples, and arrays implement this trait.\n\nThis crate becomes particularly useful when you define your own `Parcel` types. You can use `#[derive(protocol::Protocol)]` to do this. Note that in order for a type to implement `Parcel`, it must also implement `Clone`, `Debug`, and `PartialEq`.\n\n```rust\n#[derive(Parcel, Clone, Debug, PartialEq)]\npub struct Health(f32);\n\n#[derive(Parcel, Clone, Debug, PartialEq)]\npub struct SetPlayerPosition {\n    pub position: (f32, f32),\n    pub health: Health,\n    pub values: Vec\u003cString\u003e,\n}\n```\n\n### Custom derive\n\nAny user-defined type can have the `Parcel` trait automatically derived.\n\n## Example\n\n```rust\n#[derive(protocol::Protocol, Clone, Debug, PartialEq)]\npub struct Handshake;\n\n#[derive(protocol::Protocol, Clone, Debug, PartialEq)]\npub struct Hello {\n    id: i64,\n    data: Vec\u003cu8\u003e,\n}\n\n#[derive(protocol::Protocol, Clone, Debug, PartialEq)]\npub struct Goodbye {\n    id: i64,\n    reason: String,\n}\n\n#[derive(protocol::Protocol, Clone, Debug, PartialEq)]\npub struct Node {\n    name: String,\n    enabled: bool\n}\n\n#[protocol(discriminant = \"integer\")]\n#[derive(protocol::Protocol, Clone, Debug, PartialEq)]\npub enum PacketKind {\n    #[protocol(discriminator(0x00))]\n    Handshake(Handshake),\n    #[protocol(discriminator(0xaa))]\n    Hello(Hello),\n    #[protocol(discriminator(0xaf))]\n    Goodbye(Goodbye),\n}\n\nfn main() {\n    use std::net::TcpStream;\n\n    let stream = TcpStream::connect(\"127.0.0.1:34254\").unwrap();\n    let mut connection = protocol::wire::stream::Connection::new(stream, protocol::wire::middleware::pipeline::default());\n\n    connection.send_packet(\u0026Packet::Handshake(Handshake)).unwrap();\n    connection.send_packet(\u0026Packet::Hello(Hello { id: 0, data: vec![ 55 ]})).unwrap();\n    connection.send_packet(\u0026Packet::Goodbye(Goodbye { id: 0, reason: \"leaving\".to_string() })).unwrap();\n\n    loop {\n        if let Some(response) = connection.receive_packet().unwrap() {\n            println!(\"{:?}\", response);\n            break;\n        }\n    }\n}\n```\n\n## Enums\n\n### Discriminators\n\nEnum values can be transmitted either by their 1-based variant index, or by transmitting the string name of each variant.\n\n**NOTE:** The default behaviour is to use *the variant name as a string* (`string`).\n\nThis behaviour can be changed by the `#[protocol(discriminant = \"\u003ctype\u003e\")]` attribute.\n\nSupported discriminant types:\n\n* `string` (default)\n    * This transmits the enum variant name as the over-the-wire discriminant\n    * This uses more bytes per message, but it very flexible\n* `integer`\n    * This transmits the 1-based variant number as the over-the-wire discriminant\n    * If enum variants have explicit discriminators, the\n    * Enum variants cannot be reordered in the source without breaking the protocol\n\n\n```rust\n#[derive(protocol::Protocol, Clone, Debug, PartialEq)]\n#[protocol(discriminant = \"string\")]\npub enum PlayerState {\n  Stationary,\n  Flying { velocity: (f32,f32,f32) },\n  // Discriminators can be explicitly specified.\n  #[protocol(discriminator(\"ArbitraryOverTheWireName\"))]\n  Jumping { height: f32 },\n}\n```\n\n### Misc\n\nYou can rename the variant for their serialisation.\n\n```rust\n#[derive(protocol::Protocol, Clone, Debug, PartialEq)]\n#[protocol(discriminant = \"string\")]\npub enum Foo {\n  Bar,\n  #[protocol(name = \"Biz\")] // the Bing variant will be send/received as 'Biz'.\n  Bing,\n  Baz,\n}\n```\n","funding_links":[],"categories":["Libraries","Libraries \u0026 Frameworks:","库 Libraries","库"],"sub_categories":["Network programming","rust","网络编程 Network programming","网络编程"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdylanmckay%2Fprotocol","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdylanmckay%2Fprotocol","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdylanmckay%2Fprotocol/lists"}