repe-rs
Rust implementation of the REPE RPC protocol, focused on JSON as the body format.
- Spec reference: https://github.com/beve-org/beve
- Crate: repe on crates.io
This crate provides:
- REPE header and message types with correct little-endian encoding
- Message encode/decode to/from bytes and I/O helpers for streams
- JSON body helpers using
serde/serde_json - Error codes and formats aligned with the spec
Installation
Add to your Cargo.toml:
[dependencies]
repe = "0.1.1"
Quick start
use ;
// Build a JSON message
let msg = builder
.id
.query_str
.query_format
.body_json?
.build;
// Serialize to bytes and back
let bytes = msg.to_vec;
let parsed = from_slice?;
assert_eq!;
assert_eq!;
let val: Value = parsed.json_body?;
assert_eq!;
Examples
examples/json_roundtrip.rs– construct/serialize/parse a JSON message.examples/server.rs– run a JSON-pointer server (TCP).examples/client.rs– call the server routes.examples/async_server.rs– tokio-based async server.examples/async_client.rs– tokio-based async client.
Notes
- Only JSON, UTF-8 (for error messages), and raw bytes helpers are implemented. BEVE is intentionally not implemented.
- The header
reservedfield is currently ignored (per spec receivers must not reject non-zero values). - The header length is validated to be
48 + query_length + body_length.
JSON Pointer Routing and Typed Handlers
-
Router keys are JSON Pointer paths (e.g.,
/ping,/echo,/status). Raw-binary queries are rejected with an explicitInvalid queryerror. -
Add JSON Value handlers with
.with("/path", |v: serde_json::Value| -> Result<Value, (ErrorCode,String)>). -
Add typed handlers with
.with_typed("/path", |req: T| -> Result<R, (ErrorCode,String)>)whereT: Deserialize,R: Serialize.- Typed handlers auto-deserialize JSON bodies into
Tand serializeRto JSON responses. - If a non-JSON body is sent to a typed/JSON handler, the server returns
Invalid body.
- Typed handlers auto-deserialize JSON bodies into
-
Implement the pluggable trait
JsonTypedHandlerto attach methods from a service type:
use ;
use ;
;
let router = new.with_handler;
Async (tokio)
- Use
AsyncServerandAsyncClientfor asynchronous operation with tokio. - See
examples/async_server.rsandexamples/async_client.rs.
Server
- Build a router and serve TCP:
use ;
use json;
use Duration;
let router = new
.with
.with
.with;
let server = new
.read_timeout
.write_timeout;
let listener = server.listen?;
server.serve?;
Client
- Connect and call JSON-pointer routes with JSON bodies:
use Client;
use json;
let mut client = connect?;
let pong = client.call_json?;
assert_eq!;
Notify semantics
- If a request is marked
notify = true, the server will process the handler but will not send a response. - In the protocol, the
idstill increments client-side, but no matching response should be expected. - The
Client::notify_jsonandAsyncClient::notify_jsonhelpers set the flag accordingly.
Error handling
- Errors are returned “in-band” as responses with
ec != Okand a UTF‑8 body describing the error. - Common mappings:
- Header parse/validation issues →
InvalidHeaderorParseError. - JSON deserialization/serialization issues →
ParseError. - Missing routes →
MethodNotFoundwith the requested path in the message. - Application failures from handlers → return
(ErrorCode, String)to control both fields.
- Header parse/validation issues →
- Clients also surface mismatched response IDs as
RepeError::ResponseIdMismatchand mismatched protocol versions asRepeError::VersionMismatch.
Async usage (minimal end‑to‑end)
use ;
use json;
#
# async
Running the examples
cargo run --example server
cargo run --example client
cargo run --example async_server
cargo run --example async_client
Design overview
- Fixed header size is
48bytes (HEADER_SIZE) followed byqueryandbodypayloads. - All numeric fields are little‑endian. Header
lengthequals48 + query_length + body_lengthand is validated. query_format/body_formatuse the enums inrepe::constants.- Suggested query format is JSON Pointer (
/path/to/resource).
JSON Pointer helpers
parse_json_pointersplits a pointer into unescaped tokens.eval_json_pointerindexes into aserde_json::Valueusing array indices or object keys.
Testing
- Run
cargo testto execute unit and integration tests. The crate denies warnings and includes async tests; you’ll need a recent tokio. - Example integration tests cover sync/async server + client calls, unknown routes, handler error mapping, ID mismatches, and timeouts.
License
- MIT, see
LICENSE.