/fuse/read/{channel}

Kind 12: a file, whole; the server sends exactly one message and closes the connection.

The ask is kind 12 on /requests:

[12][id_len: u16, big-endian][id …][path …]

The server answers on /fuse/read/{channel} by sending exactly one message and closing the connection. In the message, a first byte of 0 is followed by the bytes of the file; a first byte of 1 states that nothing is held at the path; a first byte of 2 is followed by a message stating why the read failed. A path that the proxy or the server closes cleanly with no message before the close states that the ask was not served. An abrupt end of the path leaves the operation failed, and the proxy does not ask it again, as FUSE provides.

  • Absence. 1 states that the caller holds nothing at the path; the file reads as empty, and the first write creates it. 0 followed by no bytes is a file of zero bytes.

The ask is the target defined on FUSE: the id of the mount and the path of the entry.

The answer is defined by diverge-provider-sdk/src/shared/containers/fuse/read/response/frame.rs:

//! The answer to a read.

use std::convert::Infallible;

use super::super::super::ResponseError;
use crate::encode::{Encode, Writer};

/// The one message that answers a read.
///
/// ```text
/// [kind: u8][bytes… | message…]
/// ```
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Frame<'a> {
    /// Kind `0`. The file's bytes, verbatim. Empty is a file.
    Present(&'a [u8]),
    /// Kind `1`. The caller holds nothing under the id yet: the file
    /// reads as empty, and the first write makes it.
    Missing,
    /// Kind `2`. The read was refused or failed, and this says why,
    /// for a reader rather than a program: what a caller can refuse
    /// is its policy and not this specification's.
    Error(&'a str),
}

impl Encode for Frame<'_> {
    /// [`Infallible`]: a kind byte and bytes copied.
    type Error = Infallible;

    fn encode(&self, out: &mut Writer<'_>) -> Result<(), Infallible> {
        match self {
            Frame::Present(bytes) => {
                out.extend_from_slice(&[0]);
                out.extend_from_slice(bytes);
            }
            Frame::Missing => out.extend_from_slice(&[1]),
            Frame::Error(message) => {
                out.extend_from_slice(&[2]);
                out.extend_from_slice(message.as_bytes());
            }
        }
        Ok(())
    }
}

impl<'a> Frame<'a> {
    /// Decode the one message. The bytes or message borrow from
    /// `bytes`.
    pub fn decode(bytes: &'a [u8]) -> Result<Self, ResponseError> {
        let (kind, rest) = bytes.split_first().ok_or(ResponseError::Empty)?;
        match *kind {
            0 => Ok(Frame::Present(rest)),
            1 => Ok(Frame::Missing),
            2 => std::str::from_utf8(rest)
                .map(Frame::Error)
                .map_err(|_| ResponseError::MessageUtf8),
            other => Err(ResponseError::UnknownKind(other)),
        }
    }
}