Skip to main content

protocol

Attribute Macro protocol 

Source
#[protocol]
Expand description

Generates message types and blanket implementations from a protocol trait.

#[protocol] transforms a trait definition into a full message-passing interface. Each trait method becomes a message struct, and any ActorRef<A> where A handles those messages automatically implements the trait — so you call methods directly on the actor reference.

§What It Generates

For a trait FooProtocol, the macro generates:

  1. Message structs in a foo_protocol submodule — one per method, with public fields matching the method parameters. Each implements Message. Unit structs (methods with no parameters beyond &self) automatically derive Clone.
  2. Type alias pub type FooRef = Arc<dyn FooProtocol> — a type-erased reference.
  3. Converter trait ToFooRef with a to_foo_ref(&self) -> FooRef method.
  4. Blanket implsimpl FooProtocol for ActorRef<A> and impl ToFooRef for ActorRef<A> for any actor A that handles all the generated message types.

§Type Resolution in Generated Structs

The generated message module uses use super::* to access types from the parent scope. Types used in method parameters are qualified with super:: in the generated structs — this means any type you reference in a protocol method signature must be in scope where the #[protocol] trait is defined.

Prelude types (String, Vec, Option, Result, Box, bool, u32, etc.) and fully qualified paths (std::, core::, alloc::) are used as-is without super:: prefixing.

§Return Type Conventions

The return type on each method determines the message kind:

Return typeKindRuntimeCaller behavior
Response<T>RequestBoth.await.unwrap() (tasks) / .unwrap() (threads) — 5s default timeout
Result<(), ActorError>SendBothReturns send result
(none) / -> ()SendBothFire-and-forget (discards send result)

§Naming

  • Module: trait name → snake_case (e.g., ChatRoomProtocolchat_room_protocol)
  • Structs: method name → PascalCase (e.g., send_messageSendMessage)
  • XRef alias: strips Protocol suffix → {Base}Ref (e.g., ChatRoomProtocolChatRoomRef)
  • Converter: To{Base}Ref with to_{snake_base}_ref() method

§Example

use spawned_concurrency::Response;
use spawned_concurrency::protocol;

#[protocol]
pub trait CounterProtocol: Send + Sync {
    fn increment(&self, amount: u64);                     // send (fire-and-forget)
    fn get_count(&self) -> Response<u64>;                 // request (both modes)
}

// Generated:
// - pub mod counter_protocol { pub struct Increment { pub amount: u64 }, pub struct GetCount }
// - pub type CounterRef = Arc<dyn CounterProtocol>;
// - pub trait ToCounterRef { fn to_counter_ref(&self) -> CounterRef; }
// - impl CounterProtocol for ActorRef<A> where A: Handler<Increment> + Handler<GetCount>