summaryrefslogtreecommitdiff
path: root/plugins/warp/src/report.rs
diff options
context:
space:
mode:
authorMason Reed <mason@vector35.com>2026-03-13 12:24:18 -0700
committerMason Reed <35282038+emesare@users.noreply.github.com>2026-03-24 18:46:48 -0700
commit3c88b11e5df33116580ac008e36092775df66135 (patch)
treecd64fbe149f05683ddabcccd0db7b87356f1f8cf /plugins/warp/src/report.rs
parentf325aa7b6026a1daef84931baeb1f50d7da10c10 (diff)
[WARP] Improved UX and API
- Exposes WARP type objects directly - Adds processor API (for generating warp files directly) - Adds file and chunk API - Misc cleanup - Simplified the amount of commands - Replaced the "Create" commands with a purpose built processor dialog - Added a native QT viewer for WARP files - Simplified committing to a remote with a purpose built commit dialog
Diffstat (limited to 'plugins/warp/src/report.rs')
-rw-r--r--plugins/warp/src/report.rs185
1 files changed, 0 insertions, 185 deletions
diff --git a/plugins/warp/src/report.rs b/plugins/warp/src/report.rs
deleted file mode 100644
index 8ba9cc8b..00000000
--- a/plugins/warp/src/report.rs
+++ /dev/null
@@ -1,185 +0,0 @@
-use binaryninja::interaction::{Form, FormInputField};
-use minijinja::Environment;
-use serde::Serialize;
-use warp::chunk::{Chunk, ChunkKind};
-use warp::r#type::guid::TypeGUID;
-use warp::WarpFile;
-
-#[derive(Debug, Clone, Copy, PartialEq, Default)]
-pub enum ReportKindField {
- None,
- #[default]
- Html,
- Markdown,
- Json,
-}
-
-impl ReportKindField {
- pub fn to_field(&self) -> FormInputField {
- FormInputField::Choice {
- prompt: "Generated Report".to_string(),
- choices: vec![
- "None".to_string(),
- "HTML".to_string(),
- "Markdown".to_string(),
- "JSON".to_string(),
- ],
- default: Some(match self {
- Self::None => 0,
- Self::Html => 1,
- Self::Markdown => 2,
- Self::Json => 3,
- }),
- value: 0,
- }
- }
-
- pub fn from_form(form: &Form) -> Option<Self> {
- let field = form.get_field_with_name("Generated Report")?;
- let field_value = field.try_value_index()?;
- match field_value {
- 3 => Some(Self::Json),
- 2 => Some(Self::Markdown),
- 1 => Some(Self::Html),
- _ => Some(Self::None),
- }
- }
-}
-
-#[derive(Debug, Clone)]
-pub struct ReportGenerator {
- environment: Environment<'static>,
-}
-
-impl ReportGenerator {
- pub fn new() -> Self {
- let mut environment = Environment::new();
- // Remove trailing lines for blocks, this is required for Markdown tables.
- environment.set_trim_blocks(true);
- minijinja_embed::load_templates!(&mut environment);
- Self { environment }
- }
-
- pub fn report(&self, kind: &ReportKindField, file: &WarpFile) -> Option<String> {
- match kind {
- ReportKindField::None => None,
- ReportKindField::Html => self.html_report(file),
- ReportKindField::Markdown => self.markdown_report(file),
- ReportKindField::Json => self.json_report(file),
- }
- }
-
- pub fn report_extension(&self, kind: &ReportKindField) -> Option<&'static str> {
- match kind {
- ReportKindField::None => None,
- ReportKindField::Html => Some("html"),
- ReportKindField::Markdown => Some("md"),
- ReportKindField::Json => Some("json"),
- }
- }
-
- pub fn html_report(&self, file: &WarpFile) -> Option<String> {
- let data = FileReportData::new(file);
- let tmpl = self.environment.get_template("file.html").ok()?;
- tmpl.render(data).ok()
- }
-
- pub fn markdown_report(&self, file: &WarpFile) -> Option<String> {
- let data = FileReportData::new(file);
- let tmpl = self.environment.get_template("file.md").ok()?;
- tmpl.render(data).ok()
- }
-
- pub fn json_report(&self, file: &WarpFile) -> Option<String> {
- let data = FileReportData::new(file);
- let tmpl = self.environment.get_template("file.json").ok()?;
- tmpl.render(data).ok()
- }
-}
-
-#[derive(Debug, Clone, Serialize)]
-pub struct FileReportData {
- pub title: String,
- // pub header: WarpFileHeader,
- pub chunks: Vec<ChunkReportData>,
-}
-
-impl FileReportData {
- pub fn new(file: &WarpFile) -> Self {
- Self {
- title: "Warp File Report".to_string(),
- // header: file.header.clone(),
- chunks: file
- .chunks
- .iter()
- .map(|chunk| ChunkReportData::new(chunk))
- .collect(),
- }
- }
-}
-
-#[derive(Debug, Clone, Serialize)]
-pub struct ChunkReportData {
- pub title: String,
- // pub header: ChunkHeader,
- pub target: String,
- pub total_item_count: usize,
- /// View into a (possible subset) of chunk items.
- pub item_view: Vec<ItemReportData>,
-}
-
-impl ChunkReportData {
- pub fn new(chunk: &Chunk) -> Self {
- // TODO: Set a limit for the number of items so we dont construct 10000000 items in the report.
- let items: Vec<_> = match &chunk.kind {
- ChunkKind::Signature(sc) => sc
- .raw_functions()
- .map(|f| ItemReportData {
- name: f.symbol().and_then(|s| s.name().map(|n| n.to_string())),
- guid: f.guid().to_string(),
- note: None,
- })
- .collect(),
- ChunkKind::Type(tc) => tc
- .raw_types()
- .map(|t| ItemReportData {
- name: t.type_().and_then(|s| s.name().map(|n| n.to_string())),
- guid: TypeGUID::from(t.guid()).to_string(),
- note: None,
- })
- .collect(),
- };
-
- let chunk_type = match &chunk.kind {
- ChunkKind::Signature(_) => "Signature".to_string(),
- ChunkKind::Type(_) => "Type".to_string(),
- };
-
- let size_in_kb = chunk.header.size as f64 / 1024.0;
- let formatted_size = format!("{:.1}kb", size_in_kb);
-
- // For the target show the platform, or the architecture if available.
- let target = chunk
- .header
- .target
- .platform
- .clone()
- .or_else(|| chunk.header.target.architecture.clone())
- .unwrap_or_else(|| "None".to_string());
-
- Self {
- title: format!("{} Chunk ({})", chunk_type, formatted_size),
- target,
- // header: chunk.header.clone(),
- total_item_count: items.len(),
- item_view: items,
- }
- }
-}
-
-#[derive(Debug, Clone, Serialize)]
-pub struct ItemReportData {
- pub guid: String,
- pub name: Option<String>,
- pub note: Option<String>,
-}