pub mod client;
pub mod os_bytes;
pub mod protocol;
pub mod server;
use std::path::PathBuf;
pub const ENDPOINT_ENV: &str = "STOW_SUPERVISOR_ENDPOINT";
pub const TOKEN_ENV: &str = "STOW_SUPERVISOR_TOKEN";
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Endpoint {
#[cfg(unix)]
Unix(PathBuf),
Loopback(u16),
}
impl Endpoint {
#[must_use]
pub fn encode(&self) -> String {
match self {
#[cfg(unix)]
Self::Unix(path) => format!("unix:{}", path.display()),
Self::Loopback(port) => format!("tcp:{port}"),
}
}
pub fn parse(raw: &str) -> Result<Self, String> {
if let Some(port) = raw.strip_prefix("tcp:") {
return port
.parse::<u16>()
.map(Self::Loopback)
.map_err(|error| format!("supervisor endpoint port {port:?}: {error}"));
}
#[cfg(unix)]
if let Some(path) = raw.strip_prefix("unix:") {
return Ok(Self::Unix(PathBuf::from(path)));
}
Err(format!("unrecognised supervisor endpoint {raw:?}"))
}
}
pub fn from_env() -> Result<Option<(Endpoint, String)>, String> {
let Some(raw) = std::env::var_os(ENDPOINT_ENV) else {
return Ok(None);
};
let raw = raw
.to_str()
.ok_or_else(|| format!("{ENDPOINT_ENV} is not valid Unicode"))?;
if raw.is_empty() {
return Ok(None);
}
let endpoint = Endpoint::parse(raw)?;
let token = std::env::var(TOKEN_ENV)
.map_err(|_| format!("{ENDPOINT_ENV} is set but {TOKEN_ENV} is not"))?;
Ok(Some((endpoint, token)))
}
#[cfg(test)]
mod tests {
use super::Endpoint;
#[test]
fn a_loopback_endpoint_round_trips() {
let endpoint = Endpoint::Loopback(54321);
assert_eq!(endpoint.encode(), "tcp:54321");
assert_eq!(Endpoint::parse("tcp:54321").expect("parse"), endpoint);
}
#[cfg(unix)]
#[test]
fn a_unix_endpoint_round_trips() {
let endpoint = Endpoint::Unix(std::path::PathBuf::from("/tmp/stow-build/sock"));
assert_eq!(endpoint.encode(), "unix:/tmp/stow-build/sock");
assert_eq!(
Endpoint::parse("unix:/tmp/stow-build/sock").expect("parse"),
endpoint
);
}
#[test]
fn an_unknown_scheme_is_refused() {
let error = Endpoint::parse("http://localhost:1").expect_err("unknown scheme");
assert!(error.contains("unrecognised"), "{error}");
}
}