use std::io::{Result, Write};
use url::{Host, Url};
pub fn write_osc<W: Write + ?Sized>(writer: &mut W, command: &str) -> Result<()> {
writer.write_all(&[0x1b, 0x5d])?; writer.write_all(command.as_bytes())?;
writer.write_all(&[0x1b, b'\\'])?; Ok(())
}
fn url_needs_explicit_host(url: &Url) -> bool {
url.scheme() == "file"
&& match url.host() {
None => true,
Some(Host::Domain("localhost")) => true,
Some(Host::Ipv4(addr)) if addr.is_loopback() => true,
Some(Host::Ipv6(addr)) if addr.is_loopback() => true,
_ => false,
}
}
pub fn set_link_url<W: Write>(writer: &mut W, mut destination: Url, hostname: &str) -> Result<()> {
if url_needs_explicit_host(&destination) {
destination.set_host(Some(hostname)).unwrap();
}
set_link(writer, destination.as_str())
}
pub fn clear_link<W: Write>(writer: &mut W) -> Result<()> {
set_link(writer, "")
}
fn set_link<W: Write>(writer: &mut W, destination: &str) -> Result<()> {
write_osc(writer, &format!("8;;{destination}"))
}
#[cfg(test)]
mod tests {
#[test]
fn url_needs_explicit_host() {
let checks = [
("http://example.com/foo/bar", false),
("file:///foo/bar", true),
("file://localhost/foo/bar", true),
("file://127.0.0.1/foo/bar", true),
("file://[::1]/foo/bar", true),
];
for (url, expected) in &checks {
let parsed = super::Url::parse(url).unwrap();
let needs_host = super::url_needs_explicit_host(&parsed);
similar_asserts::assert_eq!(
needs_host,
*expected,
"{:?} needs host? {}, but got {}",
parsed,
expected,
needs_host
);
}
}
}