Response

The server sends exactly one response, Written or an error, once the content channel has finished, and the finish.

[0]                  written: the file is at the path
[1][error JSON …]    not written, and nothing partial is
  • The sequence. Exactly one response, followed by the response finish. The response is sent only once the content channel has finished, or the write has failed.
  • A finish with nothing. A response finish that no response precedes states that the server could not read the request.

The response is defined by diverge-sdk-rs/src/container_proxy/outside/endpoints/filesystem/write/server/response/frame.rs:

//! What a server's response frame carries for a write.

use std::fmt;

use crate::wire::decode::Decode;
use crate::wire::encode::{Encode, Writer};
use crate::shared::containers::write_path;
use crate::shared::error::Error;

/// The file landed, or it did not.
///
/// A payload leads with one byte saying which — `0` for
/// [`Written`](Self::Written), `1` for [`Error`](Self::Error) — and
/// the rest is that variant's own bytes.
///
/// # How it ends
///
/// | the scope ends with | means |
/// |---------------------|-------|
/// | a [`Written`](Self::Written), then a finish | the file is at the path |
/// | an [`Error`](Self::Error), then a finish | it is not, and nothing partial is |
///
/// Only a finish ends it, and it comes only once the content channel
/// has: the proxy answers when it knows.
///
/// # The failure is this scope's, the answer is not
///
/// [`Written`](Self::Written) carries
/// [`write_path::response::Frame`](crate::shared::containers::write_path::response::Frame),
/// which means the same thing wherever the exchange happens. The
/// [`Error`](Self::Error) beside it is the exchange's own: a missing
/// parent, a destination that cannot be replaced, content that ended
/// in an error.
#[derive(Debug, Clone, PartialEq)]
pub enum Frame {
    /// The file is at the path. Tag `0`.
    Written(write_path::response::Frame),
    /// A failure. Tag `1`.
    ///
    /// See [`shared::error::Error`](crate::shared::error::Error) for
    /// why it says so little.
    Error(Error),
}

/// Tag for [`Frame::Written`].
const WRITTEN: u8 = 0;

/// Tag for [`Frame::Error`].
const ERROR: u8 = 1;

impl Encode for Frame {
    /// The ordinary JSON failure, from the half that has one. The
    /// other cannot fail.
    type Error = serde_json::Error;

    // Spelled out rather than `Self::Error`: this enum has a variant
    // called `Error`, so the associated type is ambiguous by that name.
    fn encode(
        &self,
        out: &mut Writer<'_>,
    ) -> Result<(), serde_json::Error> {
        match self {
            Frame::Written(inner) => {
                out.extend_from_slice(&[WRITTEN]);
                // Its error is `Infallible`, and an empty match on one
                // is how you say so: there is no value to handle.
                inner.encode(out).map_err(|error| match error {})
            }
            Frame::Error(error) => {
                out.extend_from_slice(&[ERROR]);
                error.encode(out)
            }
        }
    }
}

impl Decode<'_> for Frame {
    /// Three ways to fail, and only one of them is a parse.
    type Error = FrameError;

    // Spelled out for the same reason as `encode` above.
    fn decode(bytes: &[u8]) -> Result<Self, FrameError> {
        let (tag, rest) = bytes.split_first().ok_or(FrameError::Empty)?;
        match *tag {
            WRITTEN => write_path::response::Frame::decode(rest)
                .map(Frame::Written)
                .map_err(|error| match error {}),
            ERROR => {
                Error::decode(rest).map(Frame::Error).map_err(FrameError::Error)
            }
            tag => Err(FrameError::UnknownTag(tag)),
        }
    }
}

/// A write response frame that could not be read.
#[derive(Debug)]
pub enum FrameError {
    /// No bytes at all, so not even a tag.
    Empty,
    /// A tag that is neither of this frame's two.
    UnknownTag(u8),
    /// The error did not parse.
    Error(serde_json::Error),
}

impl fmt::Display for FrameError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            FrameError::Empty => f.write_str("write response frame is empty"),
            FrameError::UnknownTag(tag) => {
                write!(f, "unknown write response frame tag {tag}")
            }
            FrameError::Error(error) => {
                write!(f, "write error did not parse: {error}")
            }
        }
    }
}

impl std::error::Error for FrameError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self {
            FrameError::Error(error) => Some(error),
            FrameError::Empty | FrameError::UnknownTag(_) => None,
        }
    }
}

and by diverge-sdk-rs/src/shared/containers/write_path/response/frame.rs:

//! What a response frame carries on a write path channel.

use std::convert::Infallible;

use crate::wire::decode::Decode;
use crate::wire::encode::{Encode, Writer};

/// The file landed.
///
/// It carries nothing, because saying so IS the whole message — no
/// fields, and no bytes on the wire either.
///
/// # Failing is not this type's business
///
/// It used to spend a tag byte against the day failure got a shape.
/// Failure has one now, and it is not here: the endpoints that allow a
/// write to fail wrap this in an enum of their own — every
/// [`containers`](crate::provider::endpoints::containers) scope does — and that
/// enum's tag does the discriminating. A byte here
/// as well would be two discriminators for one choice.
///
/// What a write can fail with is the exchange's business. What "the
/// file landed" looks like is not, and it looks like nothing.
///
/// # What a partial write leaves behind
///
/// Nothing at the destination. A provider writes to a temporary in the
/// destination's own directory and renames it into place, so the path
/// holds the old file, then nothing, then the new one — never a prefix
/// of the new one. That holds whether this frame arrives or not.
///
/// Where space is too tight for both copies, unlinking the old one
/// first frees exactly what the new one needs. That trades the old
/// contents away on failure, which is why it is worth doing only after
/// the ordinary attempt returns `ENOSPC` rather than up front.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct Frame;

impl Encode for Frame {
    /// [`Infallible`]: writing nothing has no failure mode.
    type Error = Infallible;

    fn encode(&self, _out: &mut Writer<'_>) -> Result<(), Self::Error> {
        Ok(())
    }
}

impl Decode<'_> for Frame {
    /// [`Infallible`]: there is nothing to read.
    type Error = Infallible;

    /// Whatever bytes arrive are ignored. There are none to send, so a
    /// peer that sent some knows something this version does not, and
    /// leaving room for it is cheaper than refusing it.
    fn decode(_bytes: &[u8]) -> Result<Self, Self::Error> {
        Ok(Frame)
    }
}