1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
// Enable some rust 2018 idioms.
#![warn(bare_trait_objects)]
#![warn(unused_extern_crates)]
// Calm down clippy.
#![allow(clippy::new_ret_no_self)]
#![allow(clippy::single_match)]
#![allow(clippy::type_complexity)]

#[macro_use]
extern crate log;

use parser::Namespace;

pub use parser::{File, Result};

mod code;
mod filter;

mod print;
pub use self::print::file::{diff, print};
pub use self::print::{DiffPrefix, HtmlPrinter, Printer, TextPrinter};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Sort {
    None,
    Name,
    Size,
}

impl Default for Sort {
    fn default() -> Self {
        Sort::None
    }
}

#[derive(Debug, Default, Clone)]
pub struct Options<'a> {
    pub print_source: bool,
    pub print_file_address: bool,
    pub print_unit_address: bool,
    pub print_function_calls: bool,
    pub print_function_instructions: bool,
    pub print_function_variables: bool,
    pub print_function_stack_frame: bool,
    pub print_inlined_function_parameters: bool,
    pub print_variable_locations: bool,
    pub inline_depth: usize,
    pub html: bool,

    pub category_file: bool,
    pub category_unit: bool,
    pub category_type: bool,
    pub category_function: bool,
    pub category_variable: bool,

    pub filter_function_inline: Option<bool>,
    pub filter_name: Option<&'a str>,
    pub filter_namespace: Vec<&'a str>,
    pub filter_unit: Option<&'a str>,

    pub sort: Sort,

    pub ignore_added: bool,
    pub ignore_deleted: bool,
    pub ignore_function_address: bool,
    pub ignore_function_size: bool,
    pub ignore_function_inline: bool,
    pub ignore_function_symbol_name: bool,
    pub ignore_variable_address: bool,
    pub ignore_variable_symbol_name: bool,
    pub prefix_map: Vec<(&'a str, &'a str)>,
}

impl<'a> Options<'a> {
    pub fn unit(&mut self, unit: &'a str) -> &mut Self {
        self.filter_unit = Some(unit);
        self
    }

    pub fn name(&mut self, name: &'a str) -> &mut Self {
        self.filter_name = Some(name);
        self
    }

    fn filter_function_inline(&self, inline: bool) -> bool {
        self.filter_function_inline.is_none() || self.filter_function_inline == Some(inline)
    }

    fn filter_name(&self, name: Option<&str>) -> bool {
        self.filter_name.is_none() || self.filter_name == name
    }

    fn filter_namespace(&self, namespace: Option<&Namespace>) -> bool {
        self.filter_namespace.is_empty() || {
            match namespace {
                Some(namespace) => namespace.is_within(&self.filter_namespace),
                None => false,
            }
        }
    }

    fn prefix_map<'name>(&self, name: &'name str) -> (&'a str, &'name str) {
        for &(old, new) in &self.prefix_map {
            if name.starts_with(old) {
                return (new, &name[old.len()..]);
            }
        }
        ("", name)
    }
}