# Client Channels

> The one channel the client opens on the scope, by tag; the server serves it as its section states and answers a channel request it cannot decode by a channel response finish with nothing before it.

Canonical: https://protocol.diverge.network/2.3.0/endpoints/volumes-list/client/
Specification revision: 2.3.0

The client opens this channel on the scope, as [Channels](/2.3.0/frames/channels/) provides. The payload of the channel request begins with one tag byte designating the channel; the remainder is the channel's request. The server serves it as its section states, and answers a channel request that does not decode by a channel response finish that no channel response precedes.

| Tag | Channel |
|-----|---------|
| `0` | [stop](/2.3.0/endpoints/volumes-list/client/stop/) |

The channel request is defined by `diverge-sdk-rs/src/provider/endpoints/volumes/list/client/channel_request/frame.rs`:

```rust
//! What a client's channel request frame carries for a volume
//! listing.

use std::fmt;

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

/// What a caller asks a provider for while a listing is open: the
/// one thing, that it is done.
///
/// | tag | asks for |
/// |-----|----------|
/// | `0` | [`Stop`](Self::Stop) |
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Frame {
    /// End the listing. Tag `0`.
    ///
    /// Carries nothing — the variant is bare — and nothing comes back
    /// on this channel. What comes back is the end of the SCOPE, a
    /// [`ResponseFinish`](crate::wire::frame::server::ServerFrame::ResponseFinish),
    /// which already means nothing bearing this scope follows on any
    /// channel. The listing has no end of its own — a caller with no
    /// volume is still watched — so this, the caller's connection
    /// ending, and the provider's error are the only ends it has;
    /// this is the one that says the caller is finished rather than
    /// gone.
    Stop,
}

/// Tag for [`Frame::Stop`].
const STOP: u8 = 0;

impl Encode for Frame {
    /// Nothing can fail: the frame is one byte.
    type Error = std::convert::Infallible;

    fn encode(&self, out: &mut Writer<'_>) -> Result<(), Self::Error> {
        match self {
            Frame::Stop => {
                out.extend_from_slice(&[STOP]);
                Ok(())
            }
        }
    }
}

impl Decode<'_> for Frame {
    /// Two ways to fail: nothing, or a tag that is not the one.
    type Error = FrameError;

    fn decode(bytes: &[u8]) -> Result<Self, Self::Error> {
        let (tag, _) = bytes.split_first().ok_or(FrameError::Empty)?;
        match *tag {
            STOP => Ok(Frame::Stop),
            tag => Err(FrameError::UnknownTag(tag)),
        }
    }
}

/// A volume listing channel request that could not be read.
#[derive(Debug)]
pub enum FrameError {
    /// No bytes at all, so not even a tag.
    Empty,
    /// A tag that is not this frame's one.
    UnknownTag(u8),
}

impl fmt::Display for FrameError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            FrameError::Empty => f.write_str("volume listing channel request frame is empty"),
            FrameError::UnknownTag(tag) => write!(f, "unknown volume listing channel request tag {tag}"),
        }
    }
}

impl std::error::Error for FrameError {}
```
