struct_audit/analysis/
padding.rs

1use crate::types::{LayoutMetrics, PaddingHole, StructLayout};
2
3pub fn analyze_layout(layout: &mut StructLayout, cache_line_size: u32) {
4    let mut padding_holes = Vec::new();
5    let mut useful_size: u64 = 0;
6    let mut current_offset: u64 = 0;
7    let mut last_member_name: Option<String> = None;
8
9    for member in &layout.members {
10        let member_offset = match member.offset {
11            Some(o) => o,
12            None => continue,
13        };
14
15        let member_size = match member.size {
16            Some(s) => s,
17            None => {
18                last_member_name = Some(member.name.clone());
19                continue;
20            }
21        };
22
23        if member_offset > current_offset {
24            let gap_size = member_offset - current_offset;
25            padding_holes.push(PaddingHole {
26                offset: current_offset,
27                size: gap_size,
28                after_member: last_member_name.clone(),
29            });
30        }
31
32        useful_size += member_size;
33        current_offset = member_offset + member_size;
34        last_member_name = Some(member.name.clone());
35    }
36
37    if current_offset < layout.size {
38        let tail_padding = layout.size - current_offset;
39        padding_holes.push(PaddingHole {
40            offset: current_offset,
41            size: tail_padding,
42            after_member: last_member_name,
43        });
44    }
45
46    let padding_bytes: u64 = padding_holes.iter().map(|h| h.size).sum();
47    let padding_percentage =
48        if layout.size > 0 { (padding_bytes as f64 / layout.size as f64) * 100.0 } else { 0.0 };
49
50    let cache_line_size_u64 = cache_line_size as u64;
51    let cache_lines_spanned =
52        if layout.size > 0 { layout.size.div_ceil(cache_line_size_u64) as u32 } else { 0 };
53
54    let total_cache_bytes = cache_lines_spanned as u64 * cache_line_size_u64;
55    let cache_line_density = if total_cache_bytes > 0 {
56        (useful_size as f64 / total_cache_bytes as f64) * 100.0
57    } else {
58        0.0
59    };
60
61    layout.metrics = LayoutMetrics {
62        total_size: layout.size,
63        useful_size,
64        padding_bytes,
65        padding_percentage,
66        cache_lines_spanned,
67        cache_line_density,
68        padding_holes,
69    };
70}