liminal-server 0.27.1

Standalone server for the liminal messaging bus
Documentation
//! `[open]`: how far an exchange with no `[auth]` reaches (ACCESS-011 R1).
//!
//! ACCESS-010 made an exchange with no `[auth]` open mode and bound it to
//! loopback. This table is the operator's written choice to let that exchange
//! listen on the network as well, for building fast on more than one machine;
//! it changes nothing about what the exchange asks of anyone, which is still
//! nothing. The table is refused beside `[auth]`, so it can never read as a
//! way to loosen a gated exchange.

/// The `[open]` table.
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Deserialize)]
#[serde(deny_unknown_fields)]
pub struct OpenConfig {
    /// Where the open exchange may listen: loopback (the default without the
    /// table) or the network.
    #[serde(default)]
    pub reach: Reach,
}

/// How far an open exchange or an open seat reaches.
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Reach {
    /// This machine only: every listener on a loopback address.
    #[default]
    Loopback,
    /// Any address the operator writes; every connection is still admitted.
    Network,
}

impl Reach {
    /// The word the configuration uses.
    #[must_use]
    pub const fn word(self) -> &'static str {
        match self {
            Self::Loopback => "loopback",
            Self::Network => "network",
        }
    }
}

impl std::fmt::Display for Reach {
    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        formatter.write_str(self.word())
    }
}

impl super::ServerConfig {
    /// How far this exchange reaches: the `[open]` table's word, loopback
    /// without one. Meaningful in open mode only; a gated exchange listens
    /// where `[auth]` lets it and this answers loopback for it.
    #[must_use]
    pub fn open_reach(&self) -> Reach {
        self.open.map_or(Reach::Loopback, |open| open.reach)
    }
}