rmux-server 0.1.1

Tokio daemon and request dispatcher for the RMUX terminal multiplexer.
Documentation
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub(crate) struct ClientFlags(u8);

impl ClientFlags {
    pub(crate) const READONLY: Self = Self(1 << 0);
    pub(crate) const IGNORESIZE: Self = Self(1 << 1);
    pub(crate) const ACTIVEPANE: Self = Self(1 << 2);
    pub(crate) const NO_DETACH_ON_DESTROY: Self = Self(1 << 3);

    #[must_use]
    pub(crate) const fn contains(self, other: Self) -> bool {
        (self.0 & other.0) == other.0
    }

    pub(crate) fn insert(&mut self, other: Self) {
        self.0 |= other.0;
    }

    pub(crate) fn remove(&mut self, other: Self) {
        self.0 &= !other.0;
    }

    #[must_use]
    pub(crate) fn with_read_only(mut self) -> Self {
        self.insert(Self::READONLY);
        self.insert(Self::IGNORESIZE);
        self
    }

    pub(crate) fn toggle_read_only(&mut self) {
        if self.contains(Self::READONLY) {
            self.remove(Self::READONLY);
            self.remove(Self::IGNORESIZE);
        } else {
            self.insert(Self::READONLY);
            self.insert(Self::IGNORESIZE);
        }
    }

    pub(crate) fn insert_named(&mut self, name: &str) -> Result<(), rmux_proto::RmuxError> {
        match name {
            "read-only" | "readonly" => self.insert(Self::READONLY),
            "ignore-size" | "ignoresize" => self.insert(Self::IGNORESIZE),
            "active-pane" | "activepane" => self.insert(Self::ACTIVEPANE),
            "no-detach-on-destroy" | "nodetachondestroy" => {
                self.insert(Self::NO_DETACH_ON_DESTROY);
            }
            other => {
                return Err(rmux_proto::RmuxError::Server(format!(
                    "unknown client flag: {other}"
                )));
            }
        }
        Ok(())
    }

    pub(crate) fn apply_named(&mut self, name: &str) -> Result<(), rmux_proto::RmuxError> {
        if let Some(name) = name.strip_prefix('!') {
            match name {
                "read-only" | "readonly" => self.remove(Self::READONLY),
                "ignore-size" | "ignoresize" => self.remove(Self::IGNORESIZE),
                "active-pane" | "activepane" => self.remove(Self::ACTIVEPANE),
                "no-detach-on-destroy" | "nodetachondestroy" => {
                    self.remove(Self::NO_DETACH_ON_DESTROY);
                }
                other => {
                    return Err(rmux_proto::RmuxError::Server(format!(
                        "unknown client flag: {other}"
                    )));
                }
            }
            return Ok(());
        }

        self.insert_named(name)
    }

    pub(crate) fn from_flag_names(values: &[String]) -> Result<Self, rmux_proto::RmuxError> {
        let mut flags = Self::default();
        for raw in values {
            for value in raw.split(',').filter(|value| !value.is_empty()) {
                flags.apply_named(value)?;
            }
        }
        Ok(flags)
    }
}