Request
The payload of the channel request the server sends: the write id, four bytes, with no tag.
[write_id: u32, big-endian]
- No tag. The server opens one kind of channel on a connect scope, so its channel request carries no tag: the payload is the write id of the connector’s write channel request, four bytes, big-endian.
The channel request is defined by diverge-provider-sdk/src/endpoints/containers/tools/connect/server/channel_request/frame.rs:
//! What a server's channel request frame carries for a tool container
//! connection.
use crate::decode::Decode;
use crate::encode::{Encode, Writer};
use crate::shared::containers::write_bytes;
/// Send the content for a write.
///
/// What a provider asks a connector for, and never unprompted. A
/// provider wants nothing from a connector on its own account — the
/// image was somebody else's problem, so is deciding who may attach,
/// and so are the container's own asks, which go to its runner. This
/// exists only because a write cannot carry its own content: only a
/// responder can finish a channel, so the bytes have to travel as
/// responses on a channel the provider opened.
///
/// # A struct, and no tag
///
/// One thing to ask for is a struct; an enum of one variant would be a
/// discriminant with nothing to discriminate — and a tag byte is that
/// discriminant written on the wire, so it goes for the same reason.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Frame(
/// Which write, by the id the connector gave it.
pub write_bytes::request::Request,
);
/// The write id's four bytes, and nothing in front of them.
impl Encode for Frame {
/// [`Infallible`](std::convert::Infallible): four known bytes.
type Error = std::convert::Infallible;
fn encode(&self, out: &mut Writer<'_>) -> Result<(), Self::Error> {
self.0.encode(out)
}
}
impl Decode<'_> for Frame {
/// One way to fail: a payload that was not four bytes.
type Error = write_bytes::request::RequestError;
fn decode(bytes: &[u8]) -> Result<Self, Self::Error> {
write_bytes::request::Request::decode(bytes).map(Frame)
}
}
and by diverge-provider-sdk/src/shared/containers/write_bytes/request/request.rs:
//! The provider asking for a write's content.
use std::error::Error;
use std::fmt;
use crate::decode::Decode;
use crate::encode::{Encode, Writer};
/// Send the content for a write.
///
/// Opened by the provider, on its own channel, in answer to a
/// [`write_path::request::Request`](crate::shared::containers::write_path::request::Request)
/// the client opened on one of its.
///
/// # Why it names the write
///
/// Because a client may have several in flight, and this channel is
/// not the one the write arrived on — only a responder can finish a
/// channel, so the provider had to open one of its own to ask.
///
/// Neither side's header can name the other's channels: they are
/// numbered per SENDER, so a number in one namespace means nothing in
/// the other. The
/// [`write_id`](crate::shared::containers::write_path::request::Request::write_id)
/// belongs to the write instead of to either channel, which is what
/// lets both ends read it.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct Request {
/// The write being asked about, quoted from the
/// [`write_path::request::Request`](crate::shared::containers::write_path::request::Request)
/// that opened it.
pub write_id: u32,
}
/// The bytes a write id occupies.
const WRITE_ID_LEN: usize = 4;
/// Four big-endian bytes. No serialization, because a fixed-width
/// integer does not need one.
impl Encode for Request {
/// [`Infallible`](std::convert::Infallible): four known bytes.
type Error = std::convert::Infallible;
fn encode(&self, out: &mut Writer<'_>) -> Result<(), Self::Error> {
out.extend_from_slice(&self.write_id.to_be_bytes());
Ok(())
}
}
impl Decode<'_> for Request {
/// One way to fail: the wrong number of bytes.
type Error = RequestError;
fn decode(bytes: &[u8]) -> Result<Self, Self::Error> {
<[u8; WRITE_ID_LEN]>::try_from(bytes)
.map(|bytes| Request {
write_id: u32::from_be_bytes(bytes),
})
.map_err(|_| RequestError::Length(bytes.len()))
}
}
/// A content request that could not be read.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum RequestError {
/// A payload that was not four bytes, carrying however many there
/// were.
Length(usize),
}
impl fmt::Display for RequestError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
RequestError::Length(len) => {
write!(f, "write content request is {len} bytes, not 4")
}
}
}
}
impl Error for RequestError {}