# Request

> The payload of the channel request: the tag byte 4 and the request of the channel.

Canonical: https://protocol.diverge.network/2.3.0/container-proxy-endpoints/filesystem-fuse-serve/client/rename/request/
Specification revision: 2.3.0

```text
[4][from_len: u16, big-endian][from …][to …]
```

- **The form.** The bytes after the tag are exactly the bytes after
  the tag of the [FUSE rename](/2.3.0/container-proxy-endpoints/fuse-mount/server/rename/request/) ask on a
  mount scope, and mean the same; that page states every field. The
  path is UTF-8, `/`-separated, with no leading `/`; empty is the
  root of the subtree.
- **Malformed.** A channel request whose payload does not decode as
  stated is answered by a channel response finish that no channel
  response precedes, and the server does nothing else for it.

The channel request is defined by `diverge-sdk-rs/src/container_proxy/outside/endpoints/filesystem/fuse_serve/client/channel_request/frame.rs`:

```rust
//! What a client's channel request frame carries on a FUSE serve scope.

/// One of the nine asks, the stop, or the tree: the
/// [`volumes::fuse_serve`](crate::provider::endpoints::volumes::fuse_serve) scope's
/// channel request, byte for byte — `0`–`8` the mount's asks, `9`
/// the stop, `10` the tree — answered here by the proxy from the
/// container's filesystem. See
/// [`Frame`](crate::provider::endpoints::volumes::fuse_serve::client::channel_request::Frame)
/// for every tag.
///
/// An alias rather than a re-export because this module is real: the
/// path says this scope's channel request lives here, and it does,
/// rather than naming somewhere else and hoping a reader follows.
/// What the alias points at is right there in the signature. One
/// type rather than two because the whole point is that a relay
/// forwards bytes: the provider hands the proxy the caller's channel
/// request as it arrived, and nothing is re-encoded on the way.
pub type Frame<'a> = crate::provider::endpoints::volumes::fuse_serve::client::channel_request::Frame<'a>;

/// A FUSE serve channel request that could not be read: the volume
/// FUSE serve's own failures. See
/// [`FrameError`](crate::provider::endpoints::volumes::fuse_serve::client::channel_request::FrameError).
pub type FrameError = crate::provider::endpoints::volumes::fuse_serve::client::channel_request::FrameError;
```

and by `diverge-sdk-rs/src/container_proxy/outside/endpoints/fuse/mount/server/channel_request/rename.rs`:

```rust
//! Rename an entry of a mounted directory.

use std::str;

use super::{FrameEncodeError, FrameError, prefixed};
use crate::wire::encode::{Encode, Writer};

/// Move an entry within the mount, by its two paths. Answered with
/// one [`Ack`](crate::shared::containers::fuse::ack::Frame).
///
/// ```text
/// [from_len: u16 BE][from: utf8…][to: utf8…]
/// ```
///
/// Neither path is empty: the root is never moved. A file at `to` is
/// replaced whole — a program that saves by writing a temporary and
/// renaming it over the real file is doing exactly this — and a
/// directory at `to` is the caller's to refuse. The proxy sends no
/// rename across mounts.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct Rename<'a> {
    /// Where the entry is.
    pub from: &'a str,
    /// Where it goes.
    pub to: &'a str,
}

impl Encode for Rename<'_> {
    /// One way to fail: a source path longer than its prefix holds.
    type Error = FrameEncodeError;

    fn encode(&self, out: &mut Writer<'_>) -> Result<(), FrameEncodeError> {
        prefixed::put(out, self.from.as_bytes())?;
        out.extend_from_slice(self.to.as_bytes());
        Ok(())
    }
}

impl<'a> Rename<'a> {
    /// Decode from the bytes after the ask's tag. Both paths borrow
    /// from `bytes`.
    pub fn decode(bytes: &'a [u8]) -> Result<Self, FrameError> {
        let (from, to) = prefixed::take(bytes)?;
        Ok(Rename {
            from: str::from_utf8(from).map_err(|_| FrameError::PathUtf8)?,
            to: str::from_utf8(to).map_err(|_| FrameError::PathUtf8)?,
        })
    }
}
```
