pub fn frame_request<E: From<RequestFrameError>>(
buf: &mut [u8],
id: RequestId,
encode: impl FnOnce(&mut [u8]) -> Result<usize, E>,
) -> Result<usize, E>Expand description
Frame request id in place at the front of buf, the closure form of
request_body and seal_request: encode writes the
application’s body into the region request_body returns and reports
how many bytes it wrote, then the header goes in front of them.
Returns the frame’s length, header included.
encode may fail with its own error type, which needs a conversion
from RequestFrameError for the failures decided here (a codec
using ProtocolError has one):
- a
bufshorter thanREQUEST_HEADER_LENisBufferTooSmall, andencodeis not called; - a length from
encodewider thanMAX_REQUEST_BODYisRequestTooLarge; - otherwise, a length from
encodepast the region it was handed isBufferTooSmall.
The frame limit is checked before the region, so a length that is
both is reported as RequestTooLarge. On any error the header is not
written: encode may have written into the body region, but a caller
that sends only what frame_request reported, and does not advance
its cursor on an error, sends nothing that could desync the node’s
framing.
use melin_wire_protocol::control::RequestId;
use melin_wire_protocol::error::ProtocolError;
use melin_wire_protocol::framing::{REQUEST_HEADER_LEN, frame_request};
/// A codec's request encoder: the body, then the frame around it.
fn encode_request(id: RequestId, body: &[u8], buf: &mut [u8]) -> Result<usize, ProtocolError> {
frame_request(buf, id, |out| {
let dst = out.get_mut(..body.len()).ok_or(ProtocolError::Truncated)?;
dst.copy_from_slice(body);
Ok(body.len())
})
}
let mut buf = [0u8; 24];
assert_eq!(encode_request(RequestId(1), b"abc", &mut buf)?, REQUEST_HEADER_LEN + 3);
assert!(matches!(
encode_request(RequestId(2), &[0; 64], &mut buf),
Err(ProtocolError::Truncated)
));