Skip to main content

frame_request

Function frame_request 

Source
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):

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)
));