Code Generation
brec generates code in two stages:
-
When the
#[block]macro is used, it generates code specific to the corresponding block.
The same applies to the#[payload]macro, which generates code related to a specific payload type. -
However, the protocol also requires unified types such as
enum Block(enumerating all user-defined blocks)
andenum Payload(enumerating all payloads). These general-purpose enums allow the system to handle
various blocks and payloads dynamically.
To generate this unified code, the generate!() macro must be invoked:
pub use blocks::*;
pub use payloads::*;
brec::generate!();
This macro must be called exactly once per crate and is responsible for:
- Implementing required
brectraits for all user-definedBlocktypes - Implementing required
brectraits for all user-definedPayloadtypes - Generating unified enums for blocks:
enum Block { ... } - Generating unified enums for payloads:
enum Payload { ... } - Implementing
ProtocolSchemafor the generatedPayloadenum - Exporting several convenience type aliases to simplify usage
When context types are declared with #[context], generate!() also constructs the crate-local ProtocolContext<'a> type. See Protocol Context.
Generated Protocol Schema
The generated Payload enum is also the protocol-level schema carrier. Its ProtocolSchema implementation binds runtime context and resource limits to the generated packet API:
impl brec::ProtocolSchema for Payload {
type Context<'a> = ProtocolContext<'a>;
const MAX_PAYLOAD_LEN: u32 = brec::DEFAULT_MAX_PAYLOAD_LEN;
const MAX_PACKET_LEN: u64 = brec::DEFAULT_MAX_PACKET_LEN;
const INITIAL_PACKET_BUFFER_CAPACITY: usize =
brec::DEFAULT_INITIAL_PACKET_BUFFER_CAPACITY;
}
MAX_PAYLOAD_LEN limits the payload body length accepted by payload readers and writers. MAX_PACKET_LEN limits the packet body length accepted by packet readers before they buffer or wait for a complete packet. INITIAL_PACKET_BUFFER_CAPACITY controls only the initial allocation used by PacketBufReader; it is capped by the payload limit and can grow as needed within the configured packet limits.
Generated Aliases
The macro defines the following aliases to reduce verbosity when using brec types:
| Alias | Expanded to |
|---|---|
Packet |
PacketDef<Block, Payload, Payload> |
BorrowedPacketBufReader<'a, R, WorkflowCtx = ()> |
PacketBufReaderDef<'a, R, Block, BlockReferred<'a>, Payload, Payload, WorkflowCtx> |
PacketBufReader<'a, R, WorkflowCtx = ()> |
same as BorrowedPacketBufReader<'a, R, WorkflowCtx> |
PeekedBlocks<'a> |
PeekedBlocksDef<'a, BlockReferred<'a>> |
PeekedBlock<'a> |
PeekedBlockDef<'a, BlockReferred<'a>> |
BorrowedRules<'a, WorkflowCtx = ()> |
RulesDef<Block, BlockReferred<'a>, Payload, Payload, WorkflowCtx> |
Rules<'a, WorkflowCtx = ()> |
same as BorrowedRules<'a, WorkflowCtx> |
BorrowedRule<'a, WorkflowCtx = ()> |
RuleDef<Block, BlockReferred<'a>, Payload, Payload, WorkflowCtx> |
Rule<'a, WorkflowCtx = ()> |
same as BorrowedRule<'a, WorkflowCtx> |
RuleFnDef<D, S> |
RuleFnDef<D, S> |
BorrowedReader<'a, S> |
ReaderDef<S, Block, BlockReferred<'a>, Payload, Payload> |
Reader<S> |
ReaderDef<S, Block, BlockReferred<'static>, Payload, Payload> |
Writer<S> |
WriterDef<S, Block, Payload, Payload> |
These aliases make it easier to work with generated structures and remove the need to repeat generic parameters.
When brec is built with the observer feature, the macro also generates:
| Alias | Expanded to |
|---|---|
SubscriptionUpdate |
brec::SubscriptionUpdate |
SubscriptionErrorAction |
brec::SubscriptionErrorAction |
Subscription |
local facade over SubscriptionDef<Block, BlockReferred<'static>, Payload, Payload, ()> |
FileObserverOptions<S> |
local wrapper over brec::FileObserverOptions<..., SubscriptionWrapper<S>> |
FileObserver |
local wrapper over FileObserverDef<Block, BlockReferred<'static>, Payload, Payload, ()> |
FileObserverStream |
brec::FileObserverStreamDef<Block, BlockReferred<'static>, Payload, Payload, ()> |
Subscription uses on_* callbacks: on_update, on_packet, on_error, on_stopped, on_aborted.
Usage Constraints
- The macro must only be called once per crate. Calling it more than once will result in compilation errors due to duplicate types and impls.
- The macro must see all relevant types (
Block,Payload) in scope. You must ensure they are visible in the location where you call the macro.
Visibility Requirements
Ensure that all blocks and payloads are imported at the location where the macro is used:
pub use blocks::*;
pub use payloads::*;
brec::generate!();
Parameters
The macro can be used with the following parameters:
-
no_default_payload- Disables the built-in payloads (StringandVec<u8>).
This has no impact on runtime performance but may slightly improve compile times and reduce binary size. -
payloads_derive = "Trait"-
By default,brecautomatically collects allderiveattributes that are common across user-defined payloads and applies them to the generatedPayloadenum.
This parameter allows you to manually specify additional derives for thePayloadenum-useful if you are only using the built-in payloads (String,Vec<u8>) and do not define custom ones. -
default_max_payload_len = N- SetsPayload::MAX_PAYLOAD_LEN. The default isbrec::DEFAULT_MAX_PAYLOAD_LEN(1 MiB). Payload headers and payload write paths reject payload bodies larger than this value. -
default_max_packet_len = N- SetsPayload::MAX_PACKET_LEN. The default isbrec::DEFAULT_MAX_PACKET_LEN, currentlyDEFAULT_MAX_PAYLOAD_LEN * 2. Packet readers reject packet bodies larger than this value before buffering or allocation-heavy processing. -
default_initial_packet_buffer_capacity = N- SetsPayload::INITIAL_PACKET_BUFFER_CAPACITY. The default isbrec::DEFAULT_INITIAL_PACKET_BUFFER_CAPACITY(64 KiB). This is a preallocation hint forPacketBufReader, not a protocol validity limit.
These size parameters currently accept integer literals.
For example,
pub use blocks::*;
// You don't define any custom payloads and only want to use the built-in ones (`String`, `Vec<u8>`)
brec::generate!(payloads_derive = "Debug, Clone");
pub use blocks::*;
// You don't define any payloads and explicitly disable the built-in ones
brec::generate!(no_default_payload);
pub use blocks::*;
pub use payloads::*;
brec::generate!(
default_max_payload_len = 4_194_304,
default_max_packet_len = 8_388_608,
default_initial_packet_buffer_capacity = 131_072,
);
If the user fully disables payload support (as in the example above), the macro will not generate any packet-related types (see Generated Aliases).