multiversx_sc_meta/cmd/code_report/
render_code_report.rs

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
111
112
113
114
115
116
117
118
119
120
121
122
use std::fmt::Display;

pub struct CodeReportRender<'a> {
    pub file: Option<&'a mut dyn std::io::Write>,
    pub compared_reports: &'a [CodeReportJson],
    pub reports: &'a [CodeReportJson],
}

use multiversx_sc_meta_lib::code_report_json::CodeReportJson;

use super::compare::{
    allocator_status_after_comparing, panic_status_after_comparing, size_status_after_comparing,
};

impl<'a> CodeReportRender<'a> {
    pub fn new(
        file: &'a mut dyn std::io::Write,
        compared_reports: &'a [CodeReportJson],
        reports: &'a [CodeReportJson],
    ) -> Self {
        Self {
            file: Some(file),
            compared_reports,
            reports,
        }
    }

    pub fn new_without_compare(
        file: &'a mut dyn std::io::Write,
        reports: &'a [CodeReportJson],
    ) -> Self {
        Self {
            file: Some(file),
            compared_reports: &[],
            reports,
        }
    }

    pub fn render_report(&mut self) {
        self.render_header();

        self.render_reports();
    }

    pub fn compare_reports(&mut self) {
        self.render_header();

        if self.compared_reports.is_empty() {
            self.render_reports();
            self.writeln("\n:warning: Could not download the report for the base branch. Displaying only the report for the current branch. :warning:");
        } else {
            self.render_report_and_compare();
        }
    }

    fn writeln(&mut self, s: impl Display) {
        let file = self.file.as_mut().unwrap();
        file.write_all(s.to_string().as_bytes()).unwrap();
        file.write_all(b"\n").unwrap();
    }

    fn write_report_for_contract(
        &mut self,
        path: &str,
        size: &str,
        has_allocator: &str,
        has_panic: &str,
    ) {
        self.writeln(format!(
            "| {} | {} | {} | {} |",
            path.split('/').last().unwrap_or(path),
            size,
            has_allocator,
            has_panic
        ));
    }

    fn render_header(&mut self) {
        self.writeln("| Path                                                         |                                     size |                  has-allocator |                     has-format |");
        self.writeln("| :-- | --: | --: | --: |");
    }

    fn render_reports(&mut self) {
        for report in self.reports {
            self.write_report_for_contract(
                &report.path,
                &report.size.to_string(),
                &report.has_allocator.to_string(),
                &report.has_panic,
            );
        }
    }

    fn render_report_and_compare(&mut self) {
        for report in self.reports.iter() {
            if let Some(compared_report) = self
                .compared_reports
                .iter()
                .find(|cr| cr.path == report.path)
            {
                self.print_compared_output(report, compared_report);
            }
        }
    }

    fn print_compared_output(&mut self, report: &CodeReportJson, compared_report: &CodeReportJson) {
        let size_report = size_status_after_comparing(report.size, compared_report.size);

        let has_allocator_report =
            allocator_status_after_comparing(report.has_allocator, compared_report.has_allocator);

        let has_panic_report =
            panic_status_after_comparing(&report.has_panic, &compared_report.has_panic);

        self.write_report_for_contract(
            &report.path,
            &size_report,
            &has_allocator_report,
            &has_panic_report,
        );
    }
}