1use serde::Serialize;
2
3#[derive(Debug, Clone, Serialize)]
4pub struct StructLayout {
5 pub name: String,
6 pub size: u64,
7 pub alignment: Option<u64>,
8 pub members: Vec<MemberLayout>,
9 pub metrics: LayoutMetrics,
10 #[serde(skip_serializing_if = "Option::is_none")]
11 pub source_location: Option<SourceLocation>,
12}
13
14#[derive(Debug, Clone, Serialize)]
15pub struct MemberLayout {
16 pub name: String,
17 pub type_name: String,
18 pub offset: Option<u64>,
19 pub size: Option<u64>,
20 #[serde(skip_serializing_if = "Option::is_none")]
21 pub bit_offset: Option<u64>,
22 #[serde(skip_serializing_if = "Option::is_none")]
23 pub bit_size: Option<u64>,
24}
25
26#[derive(Debug, Clone, Serialize, Default)]
27pub struct LayoutMetrics {
28 pub total_size: u64,
29 pub useful_size: u64,
30 pub padding_bytes: u64,
31 pub padding_percentage: f64,
32 pub cache_lines_spanned: u32,
33 pub cache_line_density: f64,
34 pub padding_holes: Vec<PaddingHole>,
35 #[serde(skip_serializing_if = "std::ops::Not::not")]
36 pub partial: bool,
37}
38
39#[derive(Debug, Clone, Serialize)]
40pub struct PaddingHole {
41 pub offset: u64,
42 pub size: u64,
43 pub after_member: Option<String>,
44}
45
46#[derive(Debug, Clone, Serialize)]
47pub struct SourceLocation {
48 pub file: String,
49 pub line: u64,
50}
51
52impl StructLayout {
53 pub fn new(name: String, size: u64, alignment: Option<u64>) -> Self {
54 Self {
55 name,
56 size,
57 alignment,
58 members: Vec::new(),
59 metrics: LayoutMetrics::default(),
60 source_location: None,
61 }
62 }
63}
64
65impl MemberLayout {
66 pub fn new(name: String, type_name: String, offset: Option<u64>, size: Option<u64>) -> Self {
67 Self { name, type_name, offset, size, bit_offset: None, bit_size: None }
68 }
69
70 pub fn end_offset(&self) -> Option<u64> {
71 match (self.offset, self.size) {
72 (Some(off), Some(sz)) => Some(off + sz),
73 _ => None,
74 }
75 }
76}