# Response

> The server sends exactly one response, whose payload begins with the byte 0 followed by the listing in the postcard wire format or with the byte 1 followed by an error as one JSON value, and the response finish follows it.

Canonical: https://provider.diverge.network/2.3.0/endpoints/volumes-list/response/
Specification revision: 2.3.0

The server sends exactly one response on the scope. The response
finish follows the response, and no frame follows the finish.

```text
[0][listing, postcard …]
[1][error JSON …]
```

- **The sequence.** Exactly one response precedes the response
  finish, and nothing follows the finish. A response finish that no
  response precedes states that the request was not served, as
  [Endpoints](/2.3.0/endpoints/) provides.
- **The listing.** A payload whose first byte is `0` carries the
  listing after that byte, running to the end of the payload. The
  listing is the `Vec<Volume>` defined below, encoded as the
  postcard reading of [Notation](/2.3.0/endpoints/#notation) provides: a
  varint count, followed by that many volumes; each volume is its
  `name` as a varint byte length followed by that many bytes of
  UTF-8, followed by `bytes` as a varint, followed by `created` as a
  varint. A count of `0` is the empty listing, and the payload is
  then exactly the one byte `0`.
- **`name`.** The name of the volume, UTF-8. The name is the only
  handle of a volume: every request of this specification that names
  a volume names it by this string. No two volumes in one listing
  share a name.
- **`bytes`.** The size of the volume, in bytes. For a volume the
  client created, `bytes` is the size the client last stated for it,
  in its [volumes::create](/2.3.0/endpoints/volumes-create/) request or in
  a later [volumes::edit](/2.3.0/endpoints/volumes-edit/) request. The number of bytes in use is
  reported by [volumes::stat](/2.3.0/endpoints/volumes-stat/).
- **`created`.** The time at which the volume came into being, in
  seconds since `1970-01-01T00:00:00Z`, unsigned. What "came into
  being" marks is the server's to determine.
- **Order.** The order of the volumes in the listing is not
  prescribed. A client reads nothing into the position of a volume.
- **The error.** A payload whose first byte is `1` carries an error
  after that byte, running to the end of the payload. The error is
  exactly one JSON value. This revision prescribes nothing about its
  content.
- **Malformed.** A payload with no byte, a payload whose first byte
  is neither `0` nor `1`, a payload whose bytes after `0` do not
  decode as the listing, and a payload whose bytes after `1` are not
  one JSON value are malformed.

The response frame is defined by
`diverge-provider-sdk/src/endpoints/volumes/list/server/response/frame.rs`:

```rust
//! What a server's response frame carries for a volume listing.

use std::fmt;

use super::Volume;
use crate::decode::Decode;
use crate::encode::{Encode, Writer};
use crate::shared::error::Error;

/// Every volume a provider will let this caller watch, or the news
/// that it could not say.
///
/// One of these on channel `0`, then the scope finishes. A payload
/// leads with one byte saying which — `0` for
/// [`Volumes`](Self::Volumes), `1` for [`Error`](Self::Error) — and
/// the rest is that variant's own bytes.
///
/// A listing is not a stream: a provider knows what it offers before
/// it is asked, so there is nothing to discover incrementally and
/// nothing to hold a channel open for.
///
/// An empty list is an ANSWER and means the provider offers nothing.
/// It is not an [`Error`](Self::Error), which means the provider could
/// not tell — a caller that confuses them stops asking when it should
/// retry.
#[derive(Debug, Clone, PartialEq)]
pub enum Frame {
    /// The volumes, in whatever order the provider chose. Tag `0`.
    ///
    /// Nothing promises an order and nothing should be read into one.
    Volumes(Vec<Volume>),
    /// A failure. Tag `1`.
    ///
    /// See [`shared::error::Error`](crate::shared::error::Error) for
    /// why it says so little.
    Error(Error),
}

/// Tag for [`Frame::Volumes`].
const VOLUMES: u8 = 0;

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

/// Two variants, two formats, and the tag chooses between them.
///
/// The volumes are **postcard**, matching
/// [`filetree`](crate::shared::filetree) rather than the JSON the rest
/// of the crate uses: this relays nothing, so no byte of it has to
/// survive a round trip unchanged, and nothing downstream reads it as
/// text.
///
/// The error is JSON, and has to be. A
/// [`serde_json::Value`] deserializes through `deserialize_any`, which
/// a format with no self-description cannot answer — so postcard can
/// carry the listing and cannot carry the failure, and each variant
/// gets the format it needs.
impl Encode for Frame {
    /// One failure per half, and they are different libraries'.
    type Error = FrameEncodeError;

    // 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<(), FrameEncodeError> {
        match self {
            Frame::Volumes(volumes) => {
                out.extend_from_slice(&[VOLUMES]);
                postcard::to_io(volumes, &mut *out)
                    .map(|_| ())
                    .map_err(FrameEncodeError::Volumes)
            }
            Frame::Error(error) => {
                out.extend_from_slice(&[ERROR]);
                error.encode(out).map_err(FrameEncodeError::Error)
            }
        }
    }
}

impl Decode<'_> for Frame {
    /// Four ways to fail, and each names which half failed.
    type Error = FrameDecodeError;

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

/// A volume listing that could not be written.
#[derive(Debug)]
pub enum FrameEncodeError {
    /// The listing did not serialize.
    Volumes(postcard::Error),
    /// The error did not serialize.
    Error(serde_json::Error),
}

impl fmt::Display for FrameEncodeError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            FrameEncodeError::Volumes(error) => {
                write!(f, "volume listing did not serialize: {error}")
            }
            FrameEncodeError::Error(error) => {
                write!(f, "volume listing error did not serialize: {error}")
            }
        }
    }
}

impl std::error::Error for FrameEncodeError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self {
            FrameEncodeError::Volumes(error) => Some(error),
            FrameEncodeError::Error(error) => Some(error),
        }
    }
}

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

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

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

A volume is defined by `diverge-provider-sdk/src/endpoints/volumes/list/server/response/volume.rs`:

```rust
//! One volume a provider offers.

use serde::{Deserialize, Serialize};

/// A directory a caller may watch, under the name a provider gave it.
///
/// [`name`](Self::name) is what to call it, [`bytes`](Self::bytes) is
/// how big it is, and [`created`](Self::created) is how old it is.
/// That is the whole of what a listing says about one, and the
/// omissions are the interesting part.
///
/// # What is inside it is a stat away
///
/// How much of it is used and the hash of its content are what a
/// [`stat`](crate::endpoints::volumes::stat) reports, because each
/// costs a walk of the volume and a listing does not pay for one. A
/// listing is what a provider knows without looking.
///
/// # Where it is, is not here
///
/// A volume carries no path. Not a private one, not an opaque one —
/// none, because a caller has nothing to do with one.
///
/// Everything a caller does with a volume goes through its name: a
/// [`watch`](crate::endpoints::volumes::watch) names it, a
/// [`delete`](crate::endpoints::volumes::delete) names it, and a
/// [`VolumeMount`](crate::shared::containers::request::VolumeMount)
/// names it, and a provider looks the name up rather than resolving
/// anything. A path would be the one field nothing consumes, and a
/// field nothing consumes is one that gets consumed anyway — a caller
/// building strings out of it, a provider then unable to move a volume
/// without breaking someone.
///
/// The paths inside a watch still mean what they meant. They are
/// relative to the volume; the volume is simply no longer described in
/// terms of anywhere else.
///
/// # Why a volume rather than a directory
///
/// Because the name is the point. A directory is a thing on a disk; a
/// volume is a thing a provider decided to OFFER, and the offering is
/// what a caller interacts with. It is also what a
/// [`VolumeMount`](crate::shared::containers::request::VolumeMount)
/// names, which is where the word already meant this.
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Volume {
    /// What to call this volume, and how to ask for it.
    ///
    /// A label, and nothing derives it from anything: for a volume the
    /// provider offers, the provider chose it; for one a
    /// [`create`](crate::endpoints::volumes::create) made, the caller
    /// did. Nothing here says which, and nothing should.
    ///
    /// It is also the HANDLE, and the only one. A
    /// [`watch`](crate::endpoints::volumes::watch) names a volume by
    /// this and by nothing else, so two volumes in one listing sharing
    /// a name would make one of them unreachable.
    pub name: String,
    /// How big it is, in BYTES.
    ///
    /// For a volume a
    /// [`create`](crate::endpoints::volumes::create::client::request::Frame::bytes)
    /// made, the number that was asked for.
    pub bytes: u64,
    /// When the volume came into being, in SECONDS since the Unix
    /// epoch.
    ///
    /// What "came into being" means is the provider's to decide and
    /// the provider's alone — the directory's own creation time where
    /// that is knowable, when it was first offered where it is not.
    /// Nothing here can distinguish the two, and a caller that needs
    /// to has asked a question this listing does not answer.
    ///
    /// # Seconds, and an integer
    ///
    /// Seconds because nothing sorts volumes at finer resolution than
    /// that, and a field's precision is a promise about what varies
    /// between two values rather than about how many digits fit.
    ///
    /// An integer rather than a formatted timestamp because this rides
    /// a binary format. A date written as text inside postcard would
    /// be a text format smuggled into a binary one, carrying a
    /// timezone offset that is always the same, at a width that varies
    /// with the number it holds.
    ///
    /// Unsigned, so a volume cannot predate 1970. Nothing a provider
    /// offers does, and the alternative is a signed field whose
    /// negative half exists to represent a state that never occurs.
    pub created: u64,
}
```

The error is defined by `diverge-provider-sdk/src/shared/error.rs`:

```rust
//! What went wrong, as far as this specification describes it.

use serde::{Deserialize, Serialize};

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

/// An error, carrying one JSON value and nothing else.
///
/// This specification does not say what is inside it. Not "not yet" —
/// it says nothing, and a reader should not expect a shape to appear
/// here later.
///
/// # Why a value rather than a vocabulary
///
/// Because the alternative is this crate tracking every failure every
/// provider can have. A typed enum would have to name what a container
/// runtime, a kernel, a filesystem, a registry and an upstream model
/// can each go wrong with, and would be wrong the first time any of
/// them added one. What a caller does about most of them is the same
/// thing anyway — stop, or try again later — and that decision does
/// not need the protocol to have a word for the cause.
///
/// So a provider puts in whatever it knows. A caller that understands
/// a particular provider reads it; one that does not still has
/// something to log, surface, or hand to a person, which is more than
/// a bare failure gives it.
///
/// # It is JSON, and that is not a free choice
///
/// [`serde_json::Value`] deserializes through `deserialize_any`, which
/// a format with no self-description cannot answer. So this decodes
/// from JSON and not from [`postcard`], whatever module it ends up
/// riding in — a postcard payload that wanted to carry one would have
/// to tunnel it through a string, and would be inventing a second
/// encoding for a value that already has one.
///
/// # It is a message, not a Rust error
///
/// Deliberately no [`std::error::Error`] impl. This is a thing that
/// arrives on a wire; the `Error` types elsewhere in this crate are
/// what a decoder returns when it cannot read one. Giving both the
/// same trait would blur two ideas that share only a name.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
pub struct Error(
    /// Whatever the provider had to say.
    ///
    /// [`Value::Null`](serde_json::Value::Null) is legal and is what
    /// [`Default`] gives — an error whose sender had nothing to add.
    pub serde_json::Value,
);

impl Encode for Error {
    /// The ordinary JSON failure.
    type Error = serde_json::Error;

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

impl Decode<'_> for Error {
    /// The ordinary JSON failure.
    type Error = serde_json::Error;

    fn decode(bytes: &[u8]) -> Result<Self, Self::Error> {
        serde_json::from_slice(bytes)
    }
}
```
