NAME
Linux::Event::Framer::Varint - Frame messages with an unsigned LEB128 payload length
SYNOPSIS
package CompactStream;
use parent 'Linux::Event::IO::Sock::Stream';
use Linux::Event::Framer 'Varint',
max_frame => 1_048_576;
sub on_message ($self, $message) {
...
}
DESCRIPTION
Linux::Event::Framer::Varint prefixes every message with its payload length encoded as canonical unsigned LEB128.
Small lengths use fewer prefix bytes.
For example:
payload length 0 prefix 00
payload length 1 prefix 01
payload length 127 prefix 7f
payload length 128 prefix 80 01
The encoded number is the payload length in bytes.
The payload follows immediately after the variable-width prefix.
WHAT IS LEB128?
LEB128 stores an integer in groups of seven data bits.
The high bit of each prefix byte indicates whether another prefix byte follows.
For example, decimal 128 is encoded as:
80 01
The first byte has its continuation bit set, so the parser knows another prefix byte follows.
The second byte completes the length.
Applications normally do not need to encode or decode this themselves. send and the native inbound parser handle it automatically.
DECLARING THE FRAMER
Declare Varint after the ordered-byte parent class:
package CompactStream;
use parent 'Linux::Event::IO::Sock::Stream';
use Linux::Event::Framer 'Varint';
The same framing policy can also be used with ordered-byte Pipe and TTY subclasses.
RECEIVING
Linux::Event reads enough prefix bytes to decode one canonical unsigned LEB128 length.
It then waits until the declared number of payload bytes are available.
For example, a 128-byte payload begins with:
80 01
If Linux receives:
first read: 80
second read: 01 <some payload bytes>
later reads: <remaining payload bytes>
the message is not delivered until all 128 payload bytes are present.
The application does not need to preserve partial prefix or payload state.
VARIABLE PREFIX WIDTH
Unlike LengthPrefix, the number of prefix bytes is not fixed.
Smaller values require less wire space.
For example:
5 05
127 7f
128 80 01
256 80 02
16_383 ff 7f
16_384 80 80 01
This makes Varint useful for protocols where small messages are common and a fixed four-byte length prefix would be unnecessarily large.
ZERO-LENGTH MESSAGES
The canonical encoding of zero is one byte:
00
Therefore:
$self->send('');
produces:
00
with no payload bytes following it.
Inbound 00 likewise represents one empty message.
CANONICAL ENCODING
Linux::Event accepts only the canonical unsigned LEB128 representation of a length.
For example, zero must be encoded as:
00
An overlong representation such as:
80 00
is rejected even though it could mathematically decode to the same numeric value.
This gives every payload length one normal wire representation.
PREFIX LENGTH AND OVERFLOW
Linux::Event bounds the Varint prefix parser.
The native parser accepts an unsigned LEB128 wire value of at most 64 bits and uses no more than ten prefix bytes.
Malformed prefixes that:
continue for too many bytes
overflow the supported unsigned value
exceed the native Perl unsigned integer range
use a noncanonical overlong representation
are rejected as framing errors.
The parser does not continue consuming an arbitrary number of continuation bytes.
INCLUDING THE PREFIX
include_prefix
By default, on_message receives only the payload.
For example, a 128-byte payload beginning on the wire with:
80 01
is delivered as exactly those 128 payload bytes.
To include the encoded Varint prefix in the inbound message:
use Linux::Event::Framer 'Varint',
include_prefix => 1;
the callback receives:
prefix bytes + payload bytes
For a 128-byte payload, the delivered message therefore begins with:
80 01
and has a total size of 130 bytes.
include_prefix affects inbound delivery only.
LIMITING PAYLOAD SIZE
max_frame
An optional max_frame limits the decoded payload length:
use Linux::Event::Framer 'Varint',
max_frame => 1_048_576;
When the prefix has been decoded, Linux::Event checks the declared payload length immediately.
If it exceeds max_frame, a framing error is reported without waiting for the oversized payload to arrive.
send also rejects payloads larger than max_frame.
max_frame must be a non-negative integer.
MAX_FRAME AND MAX_BUFFER
max_frame limits the protocol payload.
The ordered-byte resource's max_buffer separately limits native input storage.
A complete Varint frame includes:
variable-width prefix
payload
so the resource buffer limit also protects the complete framed representation.
SENDING
send calculates the payload byte length and prepends its canonical unsigned LEB128 encoding.
For example:
$self->send('x' x 127);
starts the wire frame with:
7f
while:
$self->send('x' x 128);
starts it with:
80 01
The application supplies only the payload.
RAW WRITE
write bypasses framing:
$self->write($bytes);
For example:
$self->write("\x80\x01" . ('x' x 128));
writes that exact wire representation.
Ordinary Varint protocol output should normally use send so the length prefix is guaranteed to match the payload.
INCLUDE_PREFIX DOES NOT CHANGE SENDING
include_prefix affects only inbound delivery.
For example:
use Linux::Event::Framer 'Varint',
include_prefix => 1;
still means:
$self->send('x' x 128);
creates:
80 01 <128 payload bytes>
The application should not prepend the Varint itself before calling send.
BYTE LENGTH, NOT CHARACTER COUNT
The Varint represents payload bytes.
This framer does not define text encoding or serialization.
If the application sends text, it is responsible for converting that text into the protocol's intended byte encoding before calling send.
MULTIPLE MESSAGES MAY ARRIVE AT ONCE
One kernel read may contain several complete Varint-framed messages.
For example, conceptually:
<length><payload><length><payload><length><payload>
can produce several consecutive on_message callbacks from one native input drain.
Kernel read boundaries do not become application message boundaries.
MALFORMED INPUT
Linux::Event rejects malformed Varint prefixes rather than attempting to repair them.
Examples include:
an overlong encoding such as
80 00for zeroa prefix that continues beyond the supported maximum width
a numeric overflow
a decoded length larger than
max_framea complete frame that violates the ordered-byte buffer limit
These use the normal ordered-byte framing error path.
ERROR BEHAVIOR
Malformed or oversized inbound framing produces a Linux::Event::Error with type:
framing
The resource then follows its ordinary framing-error lifecycle.
Outbound send rejects a payload that violates max_frame rather than emitting an invalid frame.
WHEN TO USE VARINT
Varint framing is useful when:
the protocol specifies unsigned LEB128 lengths
message sizes vary substantially
small messages are common
saving prefix bytes on small messages is useful
payload contents must remain binary-safe
If the protocol uses a fixed one-, two-, or four-byte integer length instead, use Linux::Event::Framer::LengthPrefix.
If it specifically uses a four-byte network-order length, use Linux::Event::Framer::U32BE.
PERFORMANCE MODEL
Inbound Varint decoding runs in Linux::Event's native ordered-byte parser.
The parser maintains partial prefix and payload state without repeatedly crossing into Perl.
Canonical-form validation, overflow checks, max_frame enforcement, and frame boundary detection happen before semantic message delivery.
Outbound send has a one-byte fast path for payload lengths below 128 and generates additional LEB128 bytes only when required.
SEE ALSO
Linux::Event::Framer, Linux::Event::Framer::LengthPrefix, Linux::Event::Framer::U32BE, Linux::Event::Framer::Netstring, Linux::Event::Framer::DecimalLength, Linux::Event::IO::Sock::Stream, Linux::Event::IO::Pipe, Linux::Event::IO::TTY, docs/FRAMING.md, docs/CHOOSING-A-FRAMER.md.