rmux-server 0.1.2

Tokio daemon and request dispatcher for the RMUX terminal multiplexer.
Documentation
pub(super) fn pane_path_from_osc7(raw_path: &str) -> Option<String> {
    let raw_path = raw_path.trim();
    if raw_path.is_empty() {
        return None;
    }

    raw_path
        .strip_prefix("file://")
        .map(path_from_file_uri)
        .or_else(|| Some(raw_path.to_owned()))
        .filter(|path| !path.is_empty())
}

fn path_from_file_uri(uri_body: &str) -> String {
    let (host, path) = split_file_uri_body(uri_body);
    platform_path_from_file_uri(&percent_decode(host), &percent_decode(path))
}

fn split_file_uri_body(uri_body: &str) -> (&str, &str) {
    let uri_body = uri_body
        .split_once('#')
        .map_or(uri_body, |(head, _)| head)
        .split_once('?')
        .map_or(uri_body, |(head, _)| head);

    if uri_body.starts_with('/') {
        return ("", uri_body);
    }

    uri_body
        .split_once('/')
        .map_or((uri_body, ""), |(host, _)| (host, &uri_body[host.len()..]))
}

fn percent_decode(value: &str) -> String {
    let bytes = value.as_bytes();
    let mut decoded = Vec::with_capacity(bytes.len());
    let mut index = 0;

    while index < bytes.len() {
        if bytes[index] == b'%' && index + 2 < bytes.len() {
            if let (Some(high), Some(low)) =
                (hex_value(bytes[index + 1]), hex_value(bytes[index + 2]))
            {
                decoded.push((high << 4) | low);
                index += 3;
                continue;
            }
        }

        decoded.push(bytes[index]);
        index += 1;
    }

    String::from_utf8_lossy(&decoded).into_owned()
}

fn hex_value(byte: u8) -> Option<u8> {
    match byte {
        b'0'..=b'9' => Some(byte - b'0'),
        b'a'..=b'f' => Some(byte - b'a' + 10),
        b'A'..=b'F' => Some(byte - b'A' + 10),
        _ => None,
    }
}

#[cfg(windows)]
fn platform_path_from_file_uri(host: &str, path: &str) -> String {
    let path = path
        .strip_prefix('/')
        .filter(|path| has_drive_prefix(path))
        .unwrap_or(path);
    if !is_local_file_uri_host(host) && !has_drive_prefix(path) {
        return format!(
            "\\\\{}\\{}",
            host,
            path.trim_start_matches('/').replace('/', "\\")
        );
    }

    path.replace('/', "\\")
}

#[cfg(windows)]
fn has_drive_prefix(path: &str) -> bool {
    let bytes = path.as_bytes();
    bytes.len() >= 2 && bytes[1] == b':' && bytes[0].is_ascii_alphabetic()
}

#[cfg(windows)]
fn is_local_file_uri_host(host: &str) -> bool {
    if host.is_empty() || host.eq_ignore_ascii_case("localhost") {
        return true;
    }

    std::env::var("COMPUTERNAME")
        .is_ok_and(|computer_name| host.eq_ignore_ascii_case(&computer_name))
}

#[cfg(not(windows))]
fn platform_path_from_file_uri(_host: &str, path: &str) -> String {
    path.to_owned()
}

#[cfg(test)]
mod tests {
    use super::pane_path_from_osc7;

    #[test]
    fn preserves_non_uri_paths() {
        assert_eq!(
            pane_path_from_osc7("/tmp/plain").as_deref(),
            Some("/tmp/plain")
        );
    }

    #[test]
    fn rejects_empty_paths() {
        assert_eq!(pane_path_from_osc7(""), None);
        assert_eq!(pane_path_from_osc7("   "), None);
    }

    #[cfg(unix)]
    #[test]
    fn unix_file_uri_decodes_path_and_ignores_host() {
        assert_eq!(
            pane_path_from_osc7("file://host.example/tmp/space%20dir").as_deref(),
            Some("/tmp/space dir")
        );
    }

    #[cfg(windows)]
    #[test]
    fn windows_file_uri_decodes_drive_path() {
        assert_eq!(
            pane_path_from_osc7("file:///C:/Users/RMUXUser%20Space").as_deref(),
            Some("C:\\Users\\RMUXUser Space")
        );
    }

    #[cfg(windows)]
    #[test]
    fn windows_file_uri_decodes_unc_path() {
        assert_eq!(
            pane_path_from_osc7("file://server/share/RMUXUser%20Space").as_deref(),
            Some("\\\\server\\share\\RMUXUser Space")
        );
    }
}