diff options
| author | Mason Reed <mason@vector35.com> | 2026-03-13 12:24:18 -0700 |
|---|---|---|
| committer | Mason Reed <35282038+emesare@users.noreply.github.com> | 2026-03-24 18:46:48 -0700 |
| commit | 3c88b11e5df33116580ac008e36092775df66135 (patch) | |
| tree | cd64fbe149f05683ddabcccd0db7b87356f1f8cf /plugins/warp/src/report.rs | |
| parent | f325aa7b6026a1daef84931baeb1f50d7da10c10 (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.rs | 185 |
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>, -} |
