use std::borrow::Cow;
use std::io::{self, Result, Write};
use base64::engine::general_purpose::STANDARD;
use base64::Engine;
use tracing::{event, instrument, Level};
use crate::resources::{svg, InlineImageProtocol};
use crate::terminal::osc::write_osc;
use crate::ResourceUrlHandler;
#[derive(Debug, Copy, Clone)]
pub struct ITerm2Protocol;
impl ITerm2Protocol {
pub fn set_mark<W: Write>(self, writer: &mut W) -> io::Result<()> {
write_osc(writer, "1337;SetMark")
}
}
impl InlineImageProtocol for ITerm2Protocol {
#[instrument(skip(self, writer, _terminal_size, resource_handler), fields(url = %url))]
fn write_inline_image(
&self,
writer: &mut dyn Write,
resource_handler: &dyn ResourceUrlHandler,
url: &url::Url,
_terminal_size: crate::TerminalSize,
) -> Result<()> {
let mime_data = resource_handler.read_resource(url)?;
event!(
Level::DEBUG,
"Received data of mime type {:?}",
mime_data.mime_type
);
let name = url
.path_segments()
.and_then(|mut s| s.next_back())
.map(Cow::Borrowed);
let (name, contents) = if let Some("image/svg+xml") = mime_data.mime_type_essence() {
event!(Level::DEBUG, "Rendering SVG from {}", url);
(
name.map(|n| {
let mut name = String::new();
name.push_str(&n);
name.push_str(".png");
Cow::Owned(name)
}),
Cow::Owned(svg::render_svg_to_png(&mime_data.data)?),
)
} else {
event!(Level::DEBUG, "Rendering mime data literally");
(name, Cow::Borrowed(&mime_data.data))
};
let data = STANDARD.encode(contents.as_ref());
write_osc(
writer,
&name.map_or_else(
|| format!("1337;File=size={};inline=1:{}", contents.len(), data),
|name| {
format!(
"1337;File=name={};size={};inline=1:{}",
STANDARD.encode(name.as_bytes()),
contents.len(),
data
)
},
),
)
}
}