2015-12-31 05:40:23 +08:00
|
|
|
use std::path::{Path, PathBuf};
|
2015-12-31 21:04:11 +08:00
|
|
|
use std::fs::File;
|
|
|
|
use std::io::Read;
|
2015-12-31 05:40:23 +08:00
|
|
|
|
2016-01-01 02:25:02 +08:00
|
|
|
|
|
|
|
pub fn render_playpen(s: &str, path: &Path) -> String {
|
2015-12-31 21:04:11 +08:00
|
|
|
// When replacing one thing in a string by something with a different length, the indices
|
|
|
|
// after that will not correspond, we therefore have to store the difference to correct this
|
2016-01-01 02:25:02 +08:00
|
|
|
let mut previous_end_index = 0;
|
|
|
|
let mut replaced = String::new();
|
2015-12-31 05:40:23 +08:00
|
|
|
|
2015-12-31 21:04:11 +08:00
|
|
|
for playpen in find_playpens(s, path) {
|
|
|
|
|
2016-01-01 08:40:37 +08:00
|
|
|
if playpen.escaped {
|
2016-03-18 05:31:28 +08:00
|
|
|
replaced.push_str(&s[previous_end_index..playpen.start_index - 1]);
|
2016-01-01 08:40:37 +08:00
|
|
|
replaced.push_str(&s[playpen.start_index..playpen.end_index]);
|
|
|
|
previous_end_index = playpen.end_index;
|
2016-03-18 05:31:28 +08:00
|
|
|
continue;
|
2016-01-01 08:40:37 +08:00
|
|
|
}
|
|
|
|
|
2015-12-31 21:04:11 +08:00
|
|
|
// Check if the file exists
|
|
|
|
if !playpen.rust_file.exists() || !playpen.rust_file.is_file() {
|
2016-08-14 21:40:08 +08:00
|
|
|
warn!("[-] No file exists for {{{{#playpen }}}}\n {}", playpen.rust_file.to_str().unwrap());
|
2016-03-18 05:31:28 +08:00
|
|
|
continue;
|
2015-12-31 21:04:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Open file & read file
|
2016-03-18 05:31:28 +08:00
|
|
|
let mut file = if let Ok(f) = File::open(&playpen.rust_file) {
|
|
|
|
f
|
|
|
|
} else {
|
|
|
|
continue;
|
|
|
|
};
|
2015-12-31 21:04:11 +08:00
|
|
|
let mut file_content = String::new();
|
2017-02-16 11:01:26 +08:00
|
|
|
if file.read_to_string(&mut file_content).is_err() {
|
2016-03-18 05:31:28 +08:00
|
|
|
continue;
|
|
|
|
};
|
2015-12-31 21:04:11 +08:00
|
|
|
|
2017-04-16 20:47:59 +08:00
|
|
|
let replacement = String::new() + "<pre><code class=\"language-rust\">" + &file_content +
|
2016-03-18 05:31:28 +08:00
|
|
|
"</code></pre>";
|
2016-01-01 02:25:02 +08:00
|
|
|
|
|
|
|
replaced.push_str(&s[previous_end_index..playpen.start_index]);
|
|
|
|
replaced.push_str(&replacement);
|
|
|
|
previous_end_index = playpen.end_index;
|
2016-03-18 05:31:28 +08:00
|
|
|
// println!("Playpen{{ {}, {}, {:?}, {} }}", playpen.start_index, playpen.end_index, playpen.rust_file,
|
|
|
|
// playpen.editable);
|
2015-12-31 05:40:23 +08:00
|
|
|
}
|
|
|
|
|
2016-01-01 02:25:02 +08:00
|
|
|
replaced.push_str(&s[previous_end_index..]);
|
|
|
|
|
|
|
|
replaced
|
2015-12-31 05:40:23 +08:00
|
|
|
}
|
|
|
|
|
2015-12-31 19:00:09 +08:00
|
|
|
#[derive(PartialOrd, PartialEq, Debug)]
|
2016-03-18 05:31:28 +08:00
|
|
|
struct Playpen {
|
2016-01-01 02:25:02 +08:00
|
|
|
start_index: usize,
|
|
|
|
end_index: usize,
|
2015-12-31 05:40:23 +08:00
|
|
|
rust_file: PathBuf,
|
2016-01-01 08:40:37 +08:00
|
|
|
editable: bool,
|
|
|
|
escaped: bool,
|
2015-12-31 05:40:23 +08:00
|
|
|
}
|
|
|
|
|
2015-12-31 21:04:11 +08:00
|
|
|
fn find_playpens(s: &str, base_path: &Path) -> Vec<Playpen> {
|
2015-12-31 05:40:23 +08:00
|
|
|
let mut playpens = vec![];
|
|
|
|
for (i, _) in s.match_indices("{{#playpen") {
|
2015-12-31 21:04:11 +08:00
|
|
|
debug!("[*]: find_playpen");
|
2015-12-31 05:40:23 +08:00
|
|
|
|
2016-01-01 08:40:37 +08:00
|
|
|
let mut escaped = false;
|
|
|
|
|
|
|
|
if i > 0 {
|
2016-03-18 05:31:28 +08:00
|
|
|
if let Some(c) = s[i - 1..].chars().nth(0) {
|
|
|
|
if c == '\\' {
|
|
|
|
escaped = true
|
|
|
|
}
|
2016-01-01 08:40:37 +08:00
|
|
|
}
|
|
|
|
}
|
2015-12-31 05:40:23 +08:00
|
|
|
// DON'T forget the "+ i" else you have an index out of bounds error !!
|
2016-03-18 05:31:28 +08:00
|
|
|
let end_i = if let Some(n) = s[i..].find("}}") {
|
|
|
|
n
|
|
|
|
} else {
|
|
|
|
continue;
|
|
|
|
} + i + 2;
|
2015-12-31 05:40:23 +08:00
|
|
|
|
2015-12-31 21:04:11 +08:00
|
|
|
debug!("s[{}..{}] = {}", i, end_i, s[i..end_i].to_string());
|
2015-12-31 05:40:23 +08:00
|
|
|
|
|
|
|
// If there is nothing between "{{#playpen" and "}}" skip
|
2016-03-18 05:31:28 +08:00
|
|
|
if end_i - 2 - (i + 10) < 1 {
|
|
|
|
continue;
|
|
|
|
}
|
2017-02-16 11:01:26 +08:00
|
|
|
if s[i + 10..end_i - 2].trim().is_empty() {
|
2016-03-18 05:31:28 +08:00
|
|
|
continue;
|
|
|
|
}
|
2015-12-31 05:40:23 +08:00
|
|
|
|
2016-03-18 05:31:28 +08:00
|
|
|
debug!("{}", s[i + 10..end_i - 2].to_string());
|
2015-12-31 05:40:23 +08:00
|
|
|
|
|
|
|
// Split on whitespaces
|
2016-03-18 05:31:28 +08:00
|
|
|
let params: Vec<&str> = s[i + 10..end_i - 2].split_whitespace().collect();
|
2017-02-16 11:01:26 +08:00
|
|
|
let editable = params
|
|
|
|
.get(1)
|
|
|
|
.map(|p| p.find("editable").is_some())
|
|
|
|
.unwrap_or(false);
|
2015-12-31 05:40:23 +08:00
|
|
|
|
2016-03-18 05:31:28 +08:00
|
|
|
playpens.push(Playpen {
|
|
|
|
start_index: i,
|
|
|
|
end_index: end_i,
|
|
|
|
rust_file: base_path.join(PathBuf::from(params[0])),
|
|
|
|
editable: editable,
|
|
|
|
escaped: escaped,
|
|
|
|
})
|
2015-12-31 05:40:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
playpens
|
|
|
|
}
|
2015-12-31 19:00:09 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-03-18 05:31:28 +08:00
|
|
|
// ---------------------------------------------------------------------------------
|
2015-12-31 19:00:09 +08:00
|
|
|
// Tests
|
|
|
|
//
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_find_playpens_no_playpen() {
|
|
|
|
let s = "Some random text without playpen...";
|
2015-12-31 21:04:11 +08:00
|
|
|
assert!(find_playpens(s, Path::new("")) == vec![]);
|
2015-12-31 19:00:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_find_playpens_partial_playpen() {
|
|
|
|
let s = "Some random text with {{#playpen...";
|
2015-12-31 21:04:11 +08:00
|
|
|
assert!(find_playpens(s, Path::new("")) == vec![]);
|
2015-12-31 19:00:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_find_playpens_empty_playpen() {
|
|
|
|
let s = "Some random text with {{#playpen}} and {{#playpen }}...";
|
2015-12-31 21:04:11 +08:00
|
|
|
assert!(find_playpens(s, Path::new("")) == vec![]);
|
2015-12-31 19:00:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_find_playpens_simple_playpen() {
|
|
|
|
let s = "Some random text with {{#playpen file.rs}} and {{#playpen test.rs }}...";
|
|
|
|
|
2015-12-31 21:04:11 +08:00
|
|
|
println!("\nOUTPUT: {:?}\n", find_playpens(s, Path::new("")));
|
2015-12-31 19:00:09 +08:00
|
|
|
|
2016-03-18 05:31:28 +08:00
|
|
|
assert!(find_playpens(s, Path::new("")) ==
|
|
|
|
vec![Playpen {
|
|
|
|
start_index: 22,
|
|
|
|
end_index: 42,
|
|
|
|
rust_file: PathBuf::from("file.rs"),
|
|
|
|
editable: false,
|
|
|
|
escaped: false,
|
|
|
|
},
|
|
|
|
Playpen {
|
|
|
|
start_index: 47,
|
|
|
|
end_index: 68,
|
|
|
|
rust_file: PathBuf::from("test.rs"),
|
|
|
|
editable: false,
|
|
|
|
escaped: false,
|
|
|
|
}]);
|
2015-12-31 19:00:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_find_playpens_complex_playpen() {
|
|
|
|
let s = "Some random text with {{#playpen file.rs editable}} and {{#playpen test.rs editable }}...";
|
|
|
|
|
2015-12-31 21:04:11 +08:00
|
|
|
println!("\nOUTPUT: {:?}\n", find_playpens(s, Path::new("dir")));
|
2015-12-31 19:00:09 +08:00
|
|
|
|
2016-03-18 05:31:28 +08:00
|
|
|
assert!(find_playpens(s, Path::new("dir")) ==
|
|
|
|
vec![Playpen {
|
|
|
|
start_index: 22,
|
|
|
|
end_index: 51,
|
|
|
|
rust_file: PathBuf::from("dir/file.rs"),
|
|
|
|
editable: true,
|
|
|
|
escaped: false,
|
|
|
|
},
|
|
|
|
Playpen {
|
|
|
|
start_index: 56,
|
|
|
|
end_index: 86,
|
|
|
|
rust_file: PathBuf::from("dir/test.rs"),
|
|
|
|
editable: true,
|
|
|
|
escaped: false,
|
|
|
|
}]);
|
2016-01-01 08:40:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_find_playpens_escaped_playpen() {
|
|
|
|
let s = "Some random text with escaped playpen \\{{#playpen file.rs editable}} ...";
|
|
|
|
|
|
|
|
println!("\nOUTPUT: {:?}\n", find_playpens(s, Path::new("")));
|
|
|
|
|
2016-03-18 05:31:28 +08:00
|
|
|
assert!(find_playpens(s, Path::new("")) ==
|
|
|
|
vec![
|
2016-01-01 08:40:37 +08:00
|
|
|
Playpen{start_index: 39, end_index: 68, rust_file: PathBuf::from("file.rs"), editable: true, escaped: true},
|
2015-12-31 19:00:09 +08:00
|
|
|
]);
|
|
|
|
}
|