Skip to main content

memscope_rs/capture/types/
stack.rs

1//! Stack allocation tracking types.
2//!
3//! This module contains types for tracking stack allocations,
4//! including stack scope information and frame details.
5
6use serde::{Deserialize, Serialize};
7
8/// Stack allocation tracking information.
9#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
10pub struct StackAllocationInfo {
11    /// Stack frame identifier.
12    pub frame_id: usize,
13    /// Variable name on stack.
14    pub var_name: String,
15    /// Stack offset from frame pointer.
16    pub stack_offset: isize,
17    /// Size of stack allocation.
18    pub size: usize,
19    /// Function name where allocated.
20    pub function_name: String,
21    /// Stack depth level.
22    pub stack_depth: usize,
23    /// Lifetime scope information.
24    pub scope_info: StackScopeInfo,
25}
26
27/// Stack scope information.
28#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
29pub struct StackScopeInfo {
30    /// Scope type (function, block, loop, etc.).
31    pub scope_type: ScopeType,
32    /// Scope start line number.
33    pub start_line: Option<u32>,
34    /// Scope end line number.
35    pub end_line: Option<u32>,
36    /// Parent scope identifier.
37    pub parent_scope: Option<usize>,
38    /// Nested scope level.
39    pub nesting_level: usize,
40}
41
42/// Scope type enumeration.
43#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
44pub enum ScopeType {
45    /// Function scope.
46    Function,
47    /// Block scope.
48    Block,
49    /// Loop scope.
50    Loop,
51    /// Conditional scope.
52    Conditional,
53    /// Match scope.
54    Match,
55    /// Async scope.
56    Async,
57    /// Unsafe scope.
58    Unsafe,
59}
60
61// Implement From trait for converting from core::types to capture::types
62impl From<crate::core::types::StackAllocationInfo> for StackAllocationInfo {
63    fn from(old: crate::core::types::StackAllocationInfo) -> Self {
64        Self {
65            frame_id: old.frame_id,
66            var_name: old.var_name,
67            stack_offset: old.stack_offset,
68            size: old.size,
69            function_name: old.function_name,
70            stack_depth: old.stack_depth,
71            scope_info: StackScopeInfo {
72                scope_type: match old.scope_info.scope_type {
73                    crate::core::types::ScopeType::Function => ScopeType::Function,
74                    crate::core::types::ScopeType::Block => ScopeType::Block,
75                    crate::core::types::ScopeType::Loop => ScopeType::Loop,
76                    crate::core::types::ScopeType::Conditional => ScopeType::Conditional,
77                    crate::core::types::ScopeType::Match => ScopeType::Match,
78                    crate::core::types::ScopeType::Async => ScopeType::Async,
79                    crate::core::types::ScopeType::Unsafe => ScopeType::Unsafe,
80                },
81                start_line: old.scope_info.start_line,
82                end_line: old.scope_info.end_line,
83                parent_scope: old.scope_info.parent_scope,
84                nesting_level: old.scope_info.nesting_level,
85            },
86        }
87    }
88}
89
90#[cfg(test)]
91mod tests {
92    use super::*;
93
94    #[test]
95    fn test_stack_allocation_info() {
96        let info = StackAllocationInfo {
97            frame_id: 1,
98            var_name: "local_var".to_string(),
99            stack_offset: -16,
100            size: 8,
101            function_name: "main".to_string(),
102            stack_depth: 2,
103            scope_info: StackScopeInfo {
104                scope_type: ScopeType::Function,
105                start_line: Some(10),
106                end_line: Some(20),
107                parent_scope: None,
108                nesting_level: 0,
109            },
110        };
111
112        assert_eq!(info.frame_id, 1);
113        assert_eq!(info.var_name, "local_var");
114        assert_eq!(info.stack_offset, -16);
115    }
116
117    #[test]
118    fn test_scope_type_variants() {
119        let types = vec![
120            ScopeType::Function,
121            ScopeType::Block,
122            ScopeType::Loop,
123            ScopeType::Conditional,
124            ScopeType::Match,
125            ScopeType::Async,
126            ScopeType::Unsafe,
127        ];
128
129        for scope_type in types {
130            assert!(!format!("{scope_type:?}").is_empty());
131        }
132    }
133}