profile-inspect 0.1.2

Analyze V8 CPU and heap profiles from Node.js/Chrome DevTools
Documentation
use std::path::PathBuf;

use bpaf::Bpaf;

use profile_inspect::ir::FrameCategory;

/// Output format and directory options shared across commands
#[derive(Debug, Clone, Bpaf)]
pub struct OutputOptions {
    /// Output formats (can specify multiple)
    #[bpaf(short('f'), long("format"), argument("FORMAT"), many)]
    pub format: Vec<String>,

    /// Output directory
    #[bpaf(short('o'), long("output"), argument("DIR"))]
    pub output: Option<PathBuf>,
}

impl OutputOptions {
    /// Get the output formats, defaulting to markdown if none specified
    pub fn formats(&self) -> Vec<String> {
        if self.format.is_empty() {
            vec!["markdown".to_string()]
        } else {
            self.format.clone()
        }
    }
}

/// Analysis configuration options shared across commands
#[derive(Debug, Clone, Bpaf)]
pub struct AnalysisOptions {
    /// Include Node.js and V8 internals
    #[bpaf(long, switch)]
    pub include_internals: bool,

    /// Minimum percentage to show
    #[bpaf(long, fallback(0.0))]
    pub min_percent: f64,

    /// Maximum number of functions to show
    #[bpaf(long, fallback(50_usize))]
    pub top: usize,
}

/// Parse comma-separated category filter string into `FrameCategory` list
pub fn parse_categories(filter_str: &str) -> Vec<FrameCategory> {
    filter_str
        .split(',')
        .filter_map(|s| match s.trim().to_lowercase().as_str() {
            "app" => Some(FrameCategory::App),
            "deps" => Some(FrameCategory::Deps),
            "node" => Some(FrameCategory::NodeInternal),
            "v8" => Some(FrameCategory::V8Internal),
            "native" => Some(FrameCategory::Native),
            _ => None,
        })
        .collect()
}