-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
22 changed files
with
1,695 additions
and
2,093 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,13 @@ | ||
#![no_main] | ||
|
||
use libfuzzer_sys::fuzz_target; | ||
use std::io::Write; | ||
use ansi_to_html::Renderer; | ||
|
||
fuzz_target!(|data: &[u8]| { | ||
let _ = ansi_to_html::render(String::new(), data); | ||
let mut renderer = Renderer::new(data); | ||
while let Some(line) = renderer.next_line().unwrap() { | ||
std::io::sink().write_all(&line).unwrap(); | ||
} | ||
assert!(matches!(renderer.next_line(), Ok(None))); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,60 +1,109 @@ | ||
use std::io::Write; | ||
use std::io::Read; | ||
|
||
mod ansi; | ||
mod perform; | ||
mod renderer; | ||
|
||
pub struct Handle { | ||
renderer: renderer::Renderer, | ||
pub struct Renderer<R> { | ||
inner: renderer::Renderer, | ||
parser: vte::Parser, | ||
bytes: R, | ||
state: State, | ||
title: String, | ||
} | ||
|
||
impl Handle { | ||
pub fn new() -> Self { | ||
#[rustfmt::skip] | ||
macro_rules! log_format { | ||
() => { | ||
r#"<html><head><style> | ||
body {{ | ||
background: #111; | ||
color: #eee; | ||
}} | ||
pre {{ | ||
word-wrap: break-word; | ||
white-space: pre-wrap; | ||
font-size: 14px; | ||
font-size-adjust: none; | ||
text-size-adjust: none; | ||
-webkit-text-size-adjust: 100%; | ||
-moz-text-size-adjust: 100%; | ||
-ms-text-size-adjust: 100%; | ||
}} | ||
</style><title>{}</title></head> | ||
<script> | ||
function scroll_to_ub() {{ | ||
var ub = document.getElementById("ub"); | ||
if (ub !== null) {{ | ||
ub.scrollIntoView(); | ||
}} | ||
}} | ||
</script> | ||
<body onload="scroll_to_ub()"> | ||
<pre style="text-align: center;">{}</pre> | ||
<pre>"# | ||
} | ||
} | ||
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
enum State { | ||
Fresh, | ||
Rendering, | ||
Done, | ||
} | ||
|
||
impl<R: Read> Renderer<R> { | ||
pub fn new(bytes: R, title: String) -> Self { | ||
Self { | ||
renderer: renderer::Renderer::new(String::new()), | ||
inner: renderer::Renderer::new(String::new()), | ||
parser: vte::Parser::new(), | ||
bytes, | ||
state: State::Fresh, | ||
title, | ||
} | ||
} | ||
|
||
pub fn finish<F: Write>(&self, mut output: F) -> std::io::Result<()> { | ||
output.write_all( | ||
br#"<!DOCTYPE html><html><body style="background:#111;color:#eee;"><body> | ||
<pre style="word-wrap:break-word;white-space:pre-wrap;font-size:14px;font-size-adjust:none;text-size-adjust:none;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;-ms-text-size-adjust:100%;"></style>"# | ||
)?; | ||
self.renderer.emit_html(&mut output)?; | ||
output.write_all(b"</pre></body><style>")?; | ||
self.renderer.emit_css(&mut output)?; | ||
output.write_all(b"</style></html>") | ||
pub fn is_empty(&self) -> bool { | ||
self.state == State::Done | ||
} | ||
} | ||
|
||
impl Write for Handle { | ||
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> { | ||
for b in buf { | ||
self.parser.advance(&mut self.renderer, *b); | ||
} | ||
Ok(buf.len()) | ||
fn first_line(&self) -> Vec<u8> { | ||
format!(log_format!(), self.title, self.title).into_bytes() | ||
} | ||
|
||
fn flush(&mut self) -> std::io::Result<()> { | ||
Ok(()) | ||
pub fn next_line(&mut self) -> Result<Option<Vec<u8>>, std::io::Error> { | ||
match self.state { | ||
State::Done => return Ok(None), | ||
State::Fresh => { | ||
self.state = State::Rendering; | ||
return Ok(Some(self.first_line())); | ||
} | ||
State::Rendering => {} | ||
} | ||
loop { | ||
let mut byte = [0u8]; | ||
let n = self.bytes.read(&mut byte)?; | ||
if n == 0 { | ||
let line = if let Some(line) = self.inner.remove_oldest_row() { | ||
Some(line) | ||
} else { | ||
self.state = State::Done; | ||
let mut line = Vec::new(); | ||
line.extend(b"</span></pre></body><style>"); | ||
self.inner.emit_css(&mut line)?; | ||
line.extend(b"</style></html>"); | ||
line.into() | ||
}; | ||
return Ok(line); | ||
} | ||
self.parser.advance(&mut self.inner, byte[0]); | ||
if let Some(mut line) = self.inner.pop_completed_row() { | ||
if line.is_empty() { | ||
log::warn!("renderer produced an empty line!"); | ||
line = b"\n".to_vec(); | ||
} | ||
return Ok(Some(line)); | ||
} | ||
} | ||
} | ||
} | ||
|
||
pub fn render(name: String, bytes: &[u8]) -> (String, String) { | ||
let mut h = Handle { | ||
renderer: renderer::Renderer::new(name), | ||
parser: vte::Parser::new(), | ||
}; | ||
h.write_all(&bytes).unwrap(); | ||
let mut html = Vec::new(); | ||
h.renderer.emit_html(&mut html).unwrap(); | ||
let mut css = Vec::new(); | ||
h.renderer.emit_css(&mut css).unwrap(); | ||
|
||
( | ||
String::from_utf8(css).unwrap(), | ||
String::from_utf8(html).unwrap(), | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,11 @@ | ||
use std::io::{copy, stdin, stdout}; | ||
use std::io::{stdin, stdout, Write}; | ||
|
||
fn main() { | ||
fn main() -> Result<(), std::io::Error> { | ||
env_logger::init(); | ||
let mut handle = ansi_to_html::Handle::new(); | ||
copy(&mut stdin().lock(), &mut handle).unwrap(); | ||
handle.finish(stdout().lock()).unwrap(); | ||
let mut renderer = ansi_to_html::Renderer::new(stdin().lock(), String::from("stdin")); | ||
let mut out = stdout().lock(); | ||
while let Some(line) = renderer.next_line()? { | ||
out.write_all(&line)?; | ||
} | ||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
[target.aarch64-unknown-linux-musl] | ||
linker = "aarch64-linux-gnu-gcc" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<!DOCTYPE HTML> | ||
<html><head><style> | ||
body { | ||
background: #111; | ||
color: #eee; | ||
} | ||
pre { | ||
word-wrap: break-word; | ||
white-space: pre-wrap; | ||
font-size: 14px; | ||
font-size-adjust: none; | ||
text-size-adjust: none; | ||
-webkit-text-size-adjust: 100%; | ||
-moz-text-size-adjust: 100%; | ||
-ms-text-size-adjust: 100%; | ||
} | ||
</style><title>oops</title></head> | ||
<body><pre><span style='color:#f55; font-weight:bold'>error</span>: No such file or directory (http error 404) | ||
|
||
<span style='color:#f55; font-weight:bold'>error</span>: aborting due to previous error</pre></body></html> |
Oops, something went wrong.