Skip to main content

memscope_rs/capture/types/
allocation.rs

1//! Allocation types for memory tracking.
2//!
3//! This module contains types related to memory allocation tracking,
4//! including allocation information, borrow tracking, and clone tracking.
5
6use serde::{Deserialize, Serialize};
7use std::thread;
8
9// Import related types from other modules
10use super::access_tracking::MemoryAccessTrackingInfo;
11use super::drop_chain::DropChainAnalysis;
12use super::dynamic_type::DynamicTypeInfo;
13use super::fragmentation::EnhancedFragmentationAnalysis;
14use super::generic::{GenericInstantiationInfo, GenericTypeInfo};
15use super::lifecycle::ObjectLifecycleInfo;
16use super::memory_layout::MemoryLayoutInfo;
17use super::ownership::TypeRelationshipInfo;
18use super::runtime_state::RuntimeStateInfo;
19use super::smart_pointer::SmartPointerInfo;
20use super::stack::StackAllocationInfo;
21use super::temporary::TemporaryObjectInfo;
22use super::tracking::FunctionCallTrackingInfo;
23
24/// Enhanced borrowing information for allocations.
25///
26/// Tracks borrow patterns including immutable and mutable borrows,
27/// concurrent borrow counts, and timestamp information.
28#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
29pub struct BorrowInfo {
30    /// Total number of immutable borrows during lifetime.
31    pub immutable_borrows: usize,
32    /// Total number of mutable borrows during lifetime.
33    pub mutable_borrows: usize,
34    /// Peak number of simultaneous borrows observed.
35    pub max_concurrent_borrows: usize,
36    /// Timestamp of the last borrow event.
37    pub last_borrow_timestamp: Option<u64>,
38
39    /// Source of this data (captured or inferred)
40    #[serde(default)]
41    pub _source: Option<String>,
42    /// Confidence level for inferred data
43    #[serde(default)]
44    pub _confidence: Option<String>,
45}
46
47/// Enhanced cloning information for allocations.
48///
49/// Tracks clone operations including clone counts, original source
50/// tracking, and clone relationships.
51#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
52pub struct CloneInfo {
53    /// Number of times this object was cloned.
54    pub clone_count: usize,
55    /// Whether this allocation itself is a result of a clone.
56    pub is_clone: bool,
57    /// If is_clone is true, points to the original object's pointer.
58    pub original_ptr: Option<usize>,
59
60    /// Source of this data (captured or inferred)
61    #[serde(default)]
62    pub _source: Option<String>,
63    /// Confidence level for inferred data
64    #[serde(default)]
65    pub _confidence: Option<String>,
66}
67
68/// Information about a memory allocation.
69///
70/// Comprehensive tracking information for a single memory allocation,
71/// including size, type, scope, lifecycle, and various analysis metadata.
72#[derive(Debug, Clone, PartialEq)]
73pub struct AllocationInfo {
74    /// Memory address of the allocation.
75    pub ptr: usize,
76    /// Size of the allocation in bytes.
77    pub size: usize,
78    /// Optional variable name associated with this allocation.
79    pub var_name: Option<String>,
80    /// Optional type name of the allocated data.
81    pub type_name: Option<String>,
82    /// Optional scope name where the allocation occurred.
83    pub scope_name: Option<String>,
84    /// Timestamp when the allocation was made.
85    pub timestamp_alloc: u64,
86    /// Optional timestamp when the allocation was deallocated.
87    pub timestamp_dealloc: Option<u64>,
88    /// Thread ID where the allocation occurred.
89    pub thread_id: thread::ThreadId,
90    /// Thread ID as u64 (original value from tracking).
91    pub thread_id_u64: u64,
92    /// Number of active borrows for this allocation.
93    pub borrow_count: usize,
94    /// Optional stack trace at the time of allocation.
95    pub stack_trace: Option<Vec<String>>,
96    /// Whether this allocation is considered leaked.
97    pub is_leaked: bool,
98    /// Precise lifetime in milliseconds (calculated from creation to destruction).
99    pub lifetime_ms: Option<u64>,
100    /// Enhanced borrowing information.
101    pub borrow_info: Option<BorrowInfo>,
102    /// Enhanced cloning information.
103    pub clone_info: Option<CloneInfo>,
104    /// Flag indicating if detailed ownership history is available in lifetime.json.
105    pub ownership_history_available: bool,
106    /// Smart pointer specific information.
107    pub smart_pointer_info: Option<SmartPointerInfo>,
108    /// Detailed memory layout information.
109    pub memory_layout: Option<MemoryLayoutInfo>,
110    /// Generic type information.
111    pub generic_info: Option<GenericTypeInfo>,
112    /// Dynamic type information (trait objects).
113    pub dynamic_type_info: Option<DynamicTypeInfo>,
114    /// Runtime state information.
115    pub runtime_state: Option<RuntimeStateInfo>,
116    /// Stack allocation information (if allocated on stack).
117    pub stack_allocation: Option<StackAllocationInfo>,
118    /// Temporary object information (if this is a temporary).
119    pub temporary_object: Option<TemporaryObjectInfo>,
120    /// Memory fragmentation analysis.
121    pub fragmentation_analysis: Option<EnhancedFragmentationAnalysis>,
122    /// Enhanced generic instantiation tracking.
123    pub generic_instantiation: Option<GenericInstantiationInfo>,
124    /// Type relationship information.
125    pub type_relationships: Option<TypeRelationshipInfo>,
126    /// Type usage information.
127    pub type_usage: Option<TypeUsageInfo>,
128    /// Function call tracking (if allocation is function-related).
129    pub function_call_tracking: Option<FunctionCallTrackingInfo>,
130    /// Object lifecycle tracking.
131    pub lifecycle_tracking: Option<ObjectLifecycleInfo>,
132    /// Memory access pattern tracking.
133    pub access_tracking: Option<MemoryAccessTrackingInfo>,
134    /// Drop chain analysis (when object is dropped).
135    pub drop_chain_analysis: Option<DropChainAnalysis>,
136}
137
138impl From<crate::core::types::AllocationInfo> for AllocationInfo {
139    fn from(old: crate::core::types::AllocationInfo) -> Self {
140        // For thread_id, we use a default value since ThreadId cannot be reliably reconstructed from String
141        // In a production system, this would require proper thread ID tracking
142        let thread_id = thread::current().id();
143
144        // Convert borrow_info
145        let borrow_info = old.borrow_info.map(|b| BorrowInfo {
146            immutable_borrows: b.immutable_borrows,
147            mutable_borrows: b.mutable_borrows,
148            max_concurrent_borrows: b.max_concurrent_borrows,
149            last_borrow_timestamp: b.last_borrow_timestamp,
150            _source: None,
151            _confidence: None,
152        });
153
154        // Convert clone_info
155        let clone_info = old.clone_info.map(|c| CloneInfo {
156            clone_count: c.clone_count,
157            is_clone: c.is_clone,
158            original_ptr: c.original_ptr,
159            _source: None,
160            _confidence: None,
161        });
162
163        // For complex nested types, we set them to None to avoid complex conversions
164        // In a production system, these would need proper conversion implementations
165        let smart_pointer_info =
166            old.smart_pointer_info
167                .map(|s| super::smart_pointer::SmartPointerInfo {
168                    data_ptr: s.data_ptr,
169                    cloned_from: s.cloned_from,
170                    clones: s.clones,
171                    ref_count_history: s
172                        .ref_count_history
173                        .iter()
174                        .map(|r| super::smart_pointer::RefCountSnapshot {
175                            timestamp: r.timestamp,
176                            strong_count: r.strong_count,
177                            weak_count: r.weak_count,
178                        })
179                        .collect(),
180                    weak_count: s.weak_count,
181                    is_weak_reference: s.is_weak_reference,
182                    is_data_owner: s.is_data_owner,
183                    is_implicitly_deallocated: s.is_implicitly_deallocated,
184                    pointer_type: match s.pointer_type {
185                        crate::core::types::SmartPointerType::Rc => {
186                            super::smart_pointer::SmartPointerType::Rc
187                        }
188                        crate::core::types::SmartPointerType::Arc => {
189                            super::smart_pointer::SmartPointerType::Arc
190                        }
191                        crate::core::types::SmartPointerType::RcWeak => {
192                            super::smart_pointer::SmartPointerType::RcWeak
193                        }
194                        crate::core::types::SmartPointerType::ArcWeak => {
195                            super::smart_pointer::SmartPointerType::ArcWeak
196                        }
197                        crate::core::types::SmartPointerType::Box => {
198                            super::smart_pointer::SmartPointerType::Box
199                        }
200                    },
201                });
202
203        Self {
204            ptr: old.ptr,
205            size: old.size,
206            var_name: old.var_name,
207            type_name: old.type_name,
208            scope_name: old.scope_name,
209            timestamp_alloc: old.timestamp_alloc,
210            timestamp_dealloc: old.timestamp_dealloc,
211            thread_id,
212            thread_id_u64: old.thread_id.parse().unwrap_or_else(|_| {
213                tracing::warn!(
214                    "Failed to parse thread_id: '{}', defaulting to 0",
215                    old.thread_id
216                );
217                0
218            }),
219            borrow_count: old.borrow_count,
220            stack_trace: old.stack_trace,
221            is_leaked: old.is_leaked,
222            lifetime_ms: old.lifetime_ms,
223            borrow_info,
224            clone_info,
225            ownership_history_available: old.ownership_history_available,
226            smart_pointer_info,
227            // Complex nested types - use Into::into for complete conversion
228            memory_layout: old.memory_layout.map(Into::into),
229            generic_info: old.generic_info.map(Into::into),
230            dynamic_type_info: old.dynamic_type_info.map(Into::into),
231            runtime_state: old.runtime_state.map(Into::into),
232            stack_allocation: old.stack_allocation.map(Into::into),
233            temporary_object: old.temporary_object.map(Into::into),
234            fragmentation_analysis: old.fragmentation_analysis.map(Into::into),
235            generic_instantiation: old.generic_instantiation.map(Into::into),
236            type_relationships: old.type_relationships.map(Into::into),
237            type_usage: old.type_usage.map(Into::into),
238            function_call_tracking: old.function_call_tracking.map(Into::into),
239            lifecycle_tracking: old.lifecycle_tracking.map(Into::into),
240            access_tracking: old.access_tracking.map(Into::into),
241            drop_chain_analysis: old.drop_chain_analysis.map(Into::into),
242        }
243    }
244}
245
246impl From<crate::capture::backends::core_types::AllocationInfo> for AllocationInfo {
247    fn from(info: crate::capture::backends::core_types::AllocationInfo) -> Self {
248        Self {
249            ptr: info.ptr,
250            size: info.size,
251            var_name: info.var_name,
252            type_name: info.type_name,
253            scope_name: None,
254            timestamp_alloc: info.allocated_at_ns,
255            timestamp_dealloc: None,
256            thread_id: std::thread::current().id(),
257            thread_id_u64: info.thread_id,
258            borrow_count: 0,
259            stack_trace: info.stack_trace,
260            is_leaked: false,
261            lifetime_ms: None,
262            borrow_info: None,
263            clone_info: None,
264            ownership_history_available: false,
265            smart_pointer_info: None,
266            memory_layout: None,
267            generic_info: None,
268            dynamic_type_info: None,
269            runtime_state: None,
270            stack_allocation: None,
271            temporary_object: None,
272            fragmentation_analysis: None,
273            generic_instantiation: None,
274            type_relationships: None,
275            type_usage: None,
276            function_call_tracking: None,
277            lifecycle_tracking: None,
278            access_tracking: None,
279            drop_chain_analysis: None,
280        }
281    }
282}
283
284/// Type usage information for tracking how types are used across the codebase.
285#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
286pub struct TypeUsageInfo {
287    /// Type name.
288    pub type_name: String,
289    /// Total usage count.
290    pub total_usage_count: u64,
291    /// Usage contexts.
292    pub usage_contexts: Vec<UsageContext>,
293    /// Usage patterns over time.
294    pub usage_timeline: Vec<UsageTimePoint>,
295    /// Hot paths where type is used.
296    pub hot_paths: Vec<HotPath>,
297    /// Performance impact of usage.
298    pub performance_impact: TypePerformanceImpact,
299}
300
301/// Usage context information.
302#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
303pub struct UsageContext {
304    /// Context type.
305    pub context_type: ContextType,
306    /// Function or module name.
307    pub location: String,
308    /// Usage frequency in this context.
309    pub frequency: u32,
310    /// Performance characteristics in this context.
311    pub performance_metrics: ContextPerformanceMetrics,
312}
313
314/// Context types where types are used.
315#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
316pub enum ContextType {
317    /// Function parameter context.
318    FunctionParameter,
319    /// Function return context.
320    FunctionReturn,
321    /// Local variable context.
322    LocalVariable,
323    /// Struct field context.
324    StructField,
325    /// Enum variant context.
326    EnumVariant,
327    /// Trait method context.
328    TraitMethod,
329    /// Generic constraint context.
330    GenericConstraint,
331    /// Closure capture context.
332    ClosureCapture,
333    /// Async context.
334    AsyncContext,
335    /// Unsafe context.
336    UnsafeContext,
337}
338
339/// Performance metrics within specific contexts.
340#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
341pub struct ContextPerformanceMetrics {
342    /// Average execution time in this context.
343    pub avg_execution_time_ns: f64,
344    /// Memory allocation frequency.
345    pub allocation_frequency: f64,
346    /// Cache miss rate in this context.
347    pub cache_miss_rate: f64,
348    /// Branch misprediction rate.
349    pub branch_misprediction_rate: f64,
350}
351
352/// Usage time point for timeline analysis.
353#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
354pub struct UsageTimePoint {
355    /// Timestamp.
356    pub timestamp: u64,
357    /// Usage count at this time.
358    pub usage_count: u32,
359    /// Memory usage at this time.
360    pub memory_usage: usize,
361    /// Performance metrics at this time.
362    pub performance_snapshot: PerformanceSnapshot,
363}
364
365/// Performance snapshot at a specific time.
366#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
367pub struct PerformanceSnapshot {
368    /// CPU usage percentage.
369    pub cpu_usage: f64,
370    /// Memory usage percentage.
371    pub memory_usage: f64,
372    /// Cache hit rate.
373    pub cache_hit_rate: f64,
374    /// Throughput (operations per second).
375    pub throughput: f64,
376}
377
378/// Hot path information.
379#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
380pub struct HotPath {
381    /// Path identifier.
382    pub path_id: String,
383    /// Function call sequence.
384    pub call_sequence: Vec<String>,
385    /// Execution frequency.
386    pub execution_frequency: u64,
387    /// Total execution time.
388    pub total_execution_time_ns: u64,
389    /// Average execution time.
390    pub avg_execution_time_ns: f64,
391    /// Memory allocations in this path.
392    pub memory_allocations: u32,
393    /// Performance bottlenecks.
394    pub bottlenecks: Vec<PerformanceBottleneck>,
395}
396
397/// Performance bottleneck information.
398#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
399pub struct PerformanceBottleneck {
400    /// Bottleneck type.
401    pub bottleneck_type: BottleneckType,
402    /// Location in code.
403    pub location: String,
404    /// Impact severity.
405    pub severity: ImpactLevel,
406    /// Description.
407    pub description: String,
408    /// Suggested optimization.
409    pub optimization_suggestion: String,
410}
411
412/// Types of performance bottlenecks.
413#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
414pub enum BottleneckType {
415    /// Memory allocation bottleneck.
416    MemoryAllocation,
417    /// Memory deallocation bottleneck.
418    MemoryDeallocation,
419    /// Cache miss bottleneck.
420    CacheMiss,
421    /// Branch misprediction bottleneck.
422    BranchMisprediction,
423    /// Function call bottleneck.
424    FunctionCall,
425    /// Data movement bottleneck.
426    DataMovement,
427    /// Synchronization bottleneck.
428    Synchronization,
429    /// I/O bottleneck.
430    IO,
431}
432
433/// Impact level enumeration.
434#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
435pub enum ImpactLevel {
436    /// Low impact level.
437    Low,
438    /// Medium impact level.
439    Medium,
440    /// High impact level.
441    High,
442    /// Critical impact level.
443    Critical,
444}
445
446/// Type performance impact assessment.
447#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
448pub struct TypePerformanceImpact {
449    /// Overall performance score (0-100).
450    pub performance_score: f64,
451    /// Memory efficiency score (0-100).
452    pub memory_efficiency_score: f64,
453    /// CPU efficiency score (0-100).
454    pub cpu_efficiency_score: f64,
455    /// Cache efficiency score (0-100).
456    pub cache_efficiency_score: f64,
457    /// Optimization recommendations.
458    pub optimization_recommendations: Vec<OptimizationRecommendation>,
459}
460
461/// Optimization recommendation.
462#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
463pub struct OptimizationRecommendation {
464    /// Recommendation type.
465    pub recommendation_type: RecommendationType,
466    /// Priority level.
467    pub priority: Priority,
468    /// Description.
469    pub description: String,
470    /// Expected performance improvement.
471    pub expected_improvement: f64,
472    /// Implementation difficulty.
473    pub implementation_difficulty: ImplementationDifficulty,
474}
475
476/// Types of optimization recommendations.
477#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
478pub enum RecommendationType {
479    /// Memory layout optimization.
480    MemoryLayout,
481    /// Algorithm change recommendation.
482    AlgorithmChange,
483    /// Data structure change recommendation.
484    DataStructureChange,
485    /// Caching strategy recommendation.
486    CachingStrategy,
487    /// Memory pooling recommendation.
488    MemoryPooling,
489    /// Lazy initialization recommendation.
490    LazyInitialization,
491    /// Inlining recommendation.
492    Inlining,
493    /// Vectorization recommendation.
494    Vectorization,
495    /// Parallelization recommendation.
496    Parallelization,
497}
498
499/// Priority levels.
500#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
501pub enum Priority {
502    /// Low priority.
503    Low,
504    /// Medium priority.
505    Medium,
506    /// High priority.
507    High,
508    /// Critical priority.
509    Critical,
510}
511
512/// Implementation difficulty levels.
513#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
514pub enum ImplementationDifficulty {
515    /// Easy implementation difficulty.
516    Easy,
517    /// Medium implementation difficulty.
518    Medium,
519    /// Hard implementation difficulty.
520    Hard,
521    /// Very hard implementation difficulty.
522    VeryHard,
523}
524
525// Custom Serialize implementation for AllocationInfo to handle thread::ThreadId
526impl Serialize for AllocationInfo {
527    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
528    where
529        S: serde::Serializer,
530    {
531        use serde::ser::SerializeStruct;
532        let mut state = serializer.serialize_struct("AllocationInfo", 25)?;
533        state.serialize_field("ptr", &self.ptr)?;
534        state.serialize_field("size", &self.size)?;
535        state.serialize_field("var_name", &self.var_name)?;
536        state.serialize_field("type_name", &self.type_name)?;
537        state.serialize_field("scope_name", &self.scope_name)?;
538        state.serialize_field("timestamp_alloc", &self.timestamp_alloc)?;
539        state.serialize_field("timestamp_dealloc", &self.timestamp_dealloc)?;
540        state.serialize_field("thread_id", &format!("{:?}", self.thread_id))?;
541        state.serialize_field("borrow_count", &self.borrow_count)?;
542        state.serialize_field("stack_trace", &self.stack_trace)?;
543        state.serialize_field("is_leaked", &self.is_leaked)?;
544        state.serialize_field("lifetime_ms", &self.lifetime_ms)?;
545        state.serialize_field("borrow_info", &self.borrow_info)?;
546        state.serialize_field("clone_info", &self.clone_info)?;
547        state.serialize_field(
548            "ownership_history_available",
549            &self.ownership_history_available,
550        )?;
551        state.serialize_field("smart_pointer_info", &self.smart_pointer_info)?;
552        state.serialize_field("memory_layout", &self.memory_layout)?;
553        state.serialize_field("generic_info", &self.generic_info)?;
554        state.serialize_field("dynamic_type_info", &self.dynamic_type_info)?;
555        state.serialize_field("runtime_state", &self.runtime_state)?;
556        state.serialize_field("stack_allocation", &self.stack_allocation)?;
557        state.serialize_field("temporary_object", &self.temporary_object)?;
558        state.serialize_field("fragmentation_analysis", &self.fragmentation_analysis)?;
559        state.serialize_field("generic_instantiation", &self.generic_instantiation)?;
560        state.serialize_field("type_relationships", &self.type_relationships)?;
561        state.serialize_field("type_usage", &self.type_usage)?;
562        state.serialize_field("function_call_tracking", &self.function_call_tracking)?;
563        state.serialize_field("lifecycle_tracking", &self.lifecycle_tracking)?;
564        state.serialize_field("access_tracking", &self.access_tracking)?;
565        state.serialize_field("drop_chain_analysis", &self.drop_chain_analysis)?;
566        state.end()
567    }
568}
569
570// Custom Deserialize implementation for AllocationInfo due to complex field handling
571impl<'de> Deserialize<'de> for AllocationInfo {
572    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
573    where
574        D: serde::Deserializer<'de>,
575    {
576        #[derive(Deserialize)]
577        struct AllocationInfoHelper {
578            ptr: usize,
579            size: usize,
580            var_name: Option<String>,
581            type_name: Option<String>,
582            scope_name: Option<String>,
583            timestamp_alloc: u64,
584            timestamp_dealloc: Option<u64>,
585            #[serde(default)]
586            thread_id: String,
587            #[serde(default)]
588            thread_id_u64: u64,
589            borrow_count: usize,
590            stack_trace: Option<Vec<String>>,
591            is_leaked: bool,
592            lifetime_ms: Option<u64>,
593            borrow_info: Option<BorrowInfo>,
594            clone_info: Option<CloneInfo>,
595            ownership_history_available: Option<bool>,
596            smart_pointer_info: Option<SmartPointerInfo>,
597            memory_layout: Option<MemoryLayoutInfo>,
598            generic_info: Option<GenericTypeInfo>,
599            dynamic_type_info: Option<DynamicTypeInfo>,
600            runtime_state: Option<RuntimeStateInfo>,
601            stack_allocation: Option<StackAllocationInfo>,
602            temporary_object: Option<TemporaryObjectInfo>,
603            fragmentation_analysis: Option<EnhancedFragmentationAnalysis>,
604            generic_instantiation: Option<GenericInstantiationInfo>,
605            type_relationships: Option<TypeRelationshipInfo>,
606            type_usage: Option<TypeUsageInfo>,
607            function_call_tracking: Option<FunctionCallTrackingInfo>,
608            lifecycle_tracking: Option<ObjectLifecycleInfo>,
609            access_tracking: Option<MemoryAccessTrackingInfo>,
610            drop_chain_analysis: Option<DropChainAnalysis>,
611        }
612
613        let helper = AllocationInfoHelper::deserialize(deserializer)?;
614        // Parse thread_id from string format, default to current thread if parsing fails
615        let thread_id = if !helper.thread_id.is_empty() {
616            // Try to parse the thread_id from format like "ThreadId(1234567890)"
617            // Since we can't reconstruct the actual ThreadId, we use the current thread
618            thread::current().id()
619        } else {
620            thread::current().id()
621        };
622
623        Ok(AllocationInfo {
624            ptr: helper.ptr,
625            size: helper.size,
626            var_name: helper.var_name,
627            type_name: helper.type_name,
628            scope_name: helper.scope_name,
629            timestamp_alloc: helper.timestamp_alloc,
630            timestamp_dealloc: helper.timestamp_dealloc,
631            thread_id,
632            thread_id_u64: helper.thread_id_u64,
633            borrow_count: helper.borrow_count,
634            stack_trace: helper.stack_trace,
635            is_leaked: helper.is_leaked,
636            lifetime_ms: helper.lifetime_ms,
637            borrow_info: helper.borrow_info,
638            clone_info: helper.clone_info,
639            ownership_history_available: helper.ownership_history_available.unwrap_or(false),
640            smart_pointer_info: helper.smart_pointer_info,
641            memory_layout: helper.memory_layout,
642            generic_info: helper.generic_info,
643            dynamic_type_info: helper.dynamic_type_info,
644            runtime_state: helper.runtime_state,
645            stack_allocation: helper.stack_allocation,
646            temporary_object: helper.temporary_object,
647            fragmentation_analysis: helper.fragmentation_analysis,
648            generic_instantiation: helper.generic_instantiation,
649            type_relationships: helper.type_relationships,
650            type_usage: helper.type_usage,
651            function_call_tracking: helper.function_call_tracking,
652            lifecycle_tracking: helper.lifecycle_tracking,
653            access_tracking: helper.access_tracking,
654            drop_chain_analysis: helper.drop_chain_analysis,
655        })
656    }
657}
658
659impl AllocationInfo {
660    /// Create a new AllocationInfo instance with improved field enhancements.
661    ///
662    /// # Arguments
663    ///
664    /// * `ptr` - Memory address of the allocation
665    /// * `size` - Size of the allocation in bytes
666    ///
667    /// # Examples
668    ///
669    /// ```
670    /// use memscope_rs::capture::types::AllocationInfo;
671    ///
672    /// let info = AllocationInfo::new(0x1000, 1024);
673    /// assert_eq!(info.ptr, 0x1000);
674    /// assert_eq!(info.size, 1024);
675    /// assert!(info.is_active());
676    /// ```
677    pub fn new(ptr: usize, size: usize) -> Self {
678        let timestamp = std::time::SystemTime::now()
679            .duration_since(std::time::UNIX_EPOCH)
680            .unwrap_or_default()
681            .as_nanos() as u64;
682
683        Self {
684            ptr,
685            size,
686            var_name: None,
687            type_name: None,
688            scope_name: None,
689            timestamp_alloc: timestamp,
690            timestamp_dealloc: None,
691            thread_id: thread::current().id(),
692            thread_id_u64: {
693                use std::hash::{Hash, Hasher};
694                let mut hasher = std::collections::hash_map::DefaultHasher::new();
695                thread::current().id().hash(&mut hasher);
696                hasher.finish()
697            },
698            borrow_count: 0,
699            stack_trace: None,
700            is_leaked: false,
701            lifetime_ms: Some(1), // Default: 1ms (just allocated)
702            borrow_info: None,    // No borrow info available by default
703            clone_info: Some(CloneInfo {
704                clone_count: 0,
705                is_clone: false,
706                original_ptr: None,
707                _source: None,
708                _confidence: None,
709            }),
710            ownership_history_available: false, // Not available without tracking
711            smart_pointer_info: None,
712            memory_layout: None,
713            generic_info: None,
714            dynamic_type_info: None,
715            runtime_state: None,
716            stack_allocation: None,
717            temporary_object: None,
718            fragmentation_analysis: None,
719            generic_instantiation: None,
720            type_relationships: None,
721            type_usage: None,
722            function_call_tracking: None,
723            lifecycle_tracking: None,
724            access_tracking: None,
725            drop_chain_analysis: None,
726        }
727    }
728
729    /// Set source location (file and line) for this allocation.
730    pub fn set_source_location(&mut self, file: &str, line: u32) {
731        let frame = format!("{}:{}", file, line);
732        self.stack_trace.get_or_insert_with(Vec::new).push(frame);
733    }
734
735    /// Set smart pointer information for this allocation.
736    pub fn set_smart_pointer_info(&mut self, info: SmartPointerInfo) {
737        self.smart_pointer_info = Some(info);
738    }
739
740    /// Mark this allocation as deallocated with current timestamp.
741    pub fn mark_deallocated(&mut self) {
742        self.timestamp_dealloc = Some(
743            std::time::SystemTime::now()
744                .duration_since(std::time::UNIX_EPOCH)
745                .unwrap_or_default()
746                .as_nanos() as u64,
747        );
748    }
749
750    /// Check if this allocation is still active (not deallocated).
751    pub fn is_active(&self) -> bool {
752        self.timestamp_dealloc.is_none()
753    }
754
755    /// Update allocation with type-specific enhancements using inference engine.
756    ///
757    /// ⚠️ WARNING: This method uses inference/heuristics. Data may be WRONG.
758    /// All inferred data is marked with `_source: "inferred"` and confidence level.
759    ///
760    /// Detects common patterns for Rc/Arc, Vec, String, HashMap, and Box types.
761    pub fn enhance_with_type_info(&mut self, type_name: &str) {
762        if self.timestamp_dealloc.is_none() {
763            let current_time = std::time::SystemTime::now()
764                .duration_since(std::time::UNIX_EPOCH)
765                .unwrap_or_default()
766                .as_nanos() as u64;
767            let elapsed_ns = current_time.saturating_sub(self.timestamp_alloc);
768            let elapsed_ms = elapsed_ns / 1_000_000;
769            self.lifetime_ms = Some(if elapsed_ms == 0 { 1 } else { elapsed_ms });
770        }
771
772        // Use inference engine for borrow and clone info
773        // ⚠️ All data below is INFERRED, not captured
774        if type_name.contains("Rc<") || type_name.contains("Arc<") {
775            self.clone_info = Some(CloneInfo {
776                clone_count: 2,
777                is_clone: false,
778                original_ptr: None,
779                _source: Some("inferred".to_string()),
780                _confidence: Some("low".to_string()),
781            });
782
783            self.borrow_info = Some(BorrowInfo {
784                immutable_borrows: 5,
785                mutable_borrows: 0,
786                max_concurrent_borrows: 5,
787                last_borrow_timestamp: Some(self.timestamp_alloc + 1000000),
788                _source: Some("inferred".to_string()),
789                _confidence: Some("low".to_string()),
790            });
791        } else if type_name.contains("Vec<")
792            || type_name.contains("String")
793            || type_name.contains("HashMap")
794        {
795            self.borrow_info = Some(BorrowInfo {
796                immutable_borrows: 4,
797                mutable_borrows: 2,
798                max_concurrent_borrows: 3,
799                last_borrow_timestamp: Some(self.timestamp_alloc + 800000),
800                _source: Some("inferred".to_string()),
801                _confidence: Some("low".to_string()),
802            });
803        } else if type_name.contains("Box<") {
804            self.clone_info = Some(CloneInfo {
805                clone_count: 0,
806                is_clone: false,
807                original_ptr: None,
808                _source: Some("inferred".to_string()),
809                _confidence: Some("low".to_string()),
810            });
811
812            self.borrow_info = Some(BorrowInfo {
813                immutable_borrows: 2,
814                mutable_borrows: 1,
815                max_concurrent_borrows: 1,
816                last_borrow_timestamp: Some(self.timestamp_alloc + 300000),
817                _source: Some("inferred".to_string()),
818                _confidence: Some("low".to_string()),
819            });
820        }
821    }
822
823    /// Enhance with inference engine (explicit inference)
824    ///
825    /// ⚠️ WARNING: All data from this method is INFERRED.
826    pub fn enhance_with_inference(&mut self, engine: &crate::capture::inference::InferenceEngine) {
827        let type_name = self.type_name.as_deref();
828
829        let inferred_borrow = engine.infer_borrow_info(type_name);
830        self.borrow_info = Some(BorrowInfo {
831            immutable_borrows: inferred_borrow.immutable_borrows,
832            mutable_borrows: inferred_borrow.mutable_borrows,
833            max_concurrent_borrows: inferred_borrow.max_concurrent_borrows,
834            last_borrow_timestamp: None,
835            _source: Some("inferred".to_string()),
836            _confidence: Some(format!("{:?}", inferred_borrow._confidence).to_lowercase()),
837        });
838
839        let inferred_sp = engine.infer_smart_pointer(type_name);
840        if inferred_sp.pointer_type != crate::capture::inference::SmartPointerType::Unknown {
841            self.clone_info = Some(CloneInfo {
842                clone_count: inferred_sp.ref_count.unwrap_or(0),
843                is_clone: false,
844                original_ptr: None,
845                _source: Some("inferred".to_string()),
846                _confidence: Some(format!("{:?}", inferred_sp._confidence).to_lowercase()),
847            });
848        }
849    }
850}
851
852/// Risk distribution analysis for memory allocations.
853#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
854pub struct RiskDistribution {
855    /// Low risk allocations count.
856    pub low_risk: usize,
857    /// Medium risk allocations count.
858    pub medium_risk: usize,
859    /// High risk allocations count.
860    pub high_risk: usize,
861    /// Critical risk allocations count.
862    pub critical_risk: usize,
863}
864
865// Implement From trait for converting from core::types to capture::types
866impl From<crate::core::types::TypeUsageInfo> for TypeUsageInfo {
867    fn from(old: crate::core::types::TypeUsageInfo) -> Self {
868        Self {
869            type_name: old.type_name,
870            total_usage_count: old.total_usage_count,
871            usage_contexts: old
872                .usage_contexts
873                .into_iter()
874                .map(|c| UsageContext {
875                    context_type: match c.context_type {
876                        crate::core::types::ContextType::FunctionParameter => {
877                            ContextType::FunctionParameter
878                        }
879                        crate::core::types::ContextType::FunctionReturn => {
880                            ContextType::FunctionReturn
881                        }
882                        crate::core::types::ContextType::LocalVariable => {
883                            ContextType::LocalVariable
884                        }
885                        crate::core::types::ContextType::StructField => ContextType::StructField,
886                        crate::core::types::ContextType::EnumVariant => ContextType::EnumVariant,
887                        crate::core::types::ContextType::TraitMethod => ContextType::TraitMethod,
888                        crate::core::types::ContextType::GenericConstraint => {
889                            ContextType::GenericConstraint
890                        }
891                        crate::core::types::ContextType::ClosureCapture => {
892                            ContextType::ClosureCapture
893                        }
894                        crate::core::types::ContextType::AsyncContext => ContextType::AsyncContext,
895                        crate::core::types::ContextType::UnsafeContext => {
896                            ContextType::UnsafeContext
897                        }
898                    },
899                    location: c.location,
900                    frequency: c.frequency,
901                    performance_metrics: ContextPerformanceMetrics {
902                        avg_execution_time_ns: c.performance_metrics.avg_execution_time_ns,
903                        allocation_frequency: c.performance_metrics.allocation_frequency,
904                        cache_miss_rate: c.performance_metrics.cache_miss_rate,
905                        branch_misprediction_rate: c.performance_metrics.branch_misprediction_rate,
906                    },
907                })
908                .collect(),
909            usage_timeline: old
910                .usage_timeline
911                .into_iter()
912                .map(|t| UsageTimePoint {
913                    timestamp: t.timestamp,
914                    usage_count: t.usage_count,
915                    memory_usage: t.memory_usage,
916                    performance_snapshot: PerformanceSnapshot {
917                        cpu_usage: t.performance_snapshot.cpu_usage,
918                        memory_usage: t.performance_snapshot.memory_usage,
919                        cache_hit_rate: t.performance_snapshot.cache_hit_rate,
920                        throughput: t.performance_snapshot.throughput,
921                    },
922                })
923                .collect(),
924            hot_paths: old
925                .hot_paths
926                .into_iter()
927                .map(|h| HotPath {
928                    path_id: h.path_id,
929                    call_sequence: h.call_sequence,
930                    execution_frequency: h.execution_frequency,
931                    total_execution_time_ns: h.total_execution_time_ns,
932                    avg_execution_time_ns: h.avg_execution_time_ns,
933                    memory_allocations: h.memory_allocations,
934                    bottlenecks: h
935                        .bottlenecks
936                        .into_iter()
937                        .map(|b| PerformanceBottleneck {
938                            bottleneck_type: match b.bottleneck_type {
939                                crate::core::types::BottleneckType::MemoryAllocation => {
940                                    BottleneckType::MemoryAllocation
941                                }
942                                crate::core::types::BottleneckType::MemoryDeallocation => {
943                                    BottleneckType::MemoryDeallocation
944                                }
945                                crate::core::types::BottleneckType::CacheMiss => {
946                                    BottleneckType::CacheMiss
947                                }
948                                crate::core::types::BottleneckType::BranchMisprediction => {
949                                    BottleneckType::BranchMisprediction
950                                }
951                                crate::core::types::BottleneckType::FunctionCall => {
952                                    BottleneckType::FunctionCall
953                                }
954                                crate::core::types::BottleneckType::DataMovement => {
955                                    BottleneckType::DataMovement
956                                }
957                                crate::core::types::BottleneckType::Synchronization => {
958                                    BottleneckType::Synchronization
959                                }
960                                crate::core::types::BottleneckType::IO => BottleneckType::IO,
961                            },
962                            location: b.location,
963                            severity: match b.severity {
964                                crate::core::types::ImpactLevel::Low => ImpactLevel::Low,
965                                crate::core::types::ImpactLevel::Medium => ImpactLevel::Medium,
966                                crate::core::types::ImpactLevel::High => ImpactLevel::High,
967                                crate::core::types::ImpactLevel::Critical => ImpactLevel::Critical,
968                            },
969                            description: b.description,
970                            optimization_suggestion: b.optimization_suggestion,
971                        })
972                        .collect(),
973                })
974                .collect(),
975            performance_impact: TypePerformanceImpact {
976                performance_score: old.performance_impact.performance_score,
977                memory_efficiency_score: old.performance_impact.memory_efficiency_score,
978                cpu_efficiency_score: old.performance_impact.cpu_efficiency_score,
979                cache_efficiency_score: old.performance_impact.cache_efficiency_score,
980                optimization_recommendations: old
981                    .performance_impact
982                    .optimization_recommendations
983                    .into_iter()
984                    .map(|r| OptimizationRecommendation {
985                        recommendation_type: match r.recommendation_type {
986                            crate::core::types::RecommendationType::MemoryLayout => {
987                                RecommendationType::MemoryLayout
988                            }
989                            crate::core::types::RecommendationType::AlgorithmChange => {
990                                RecommendationType::AlgorithmChange
991                            }
992                            crate::core::types::RecommendationType::DataStructureChange => {
993                                RecommendationType::DataStructureChange
994                            }
995                            crate::core::types::RecommendationType::CachingStrategy => {
996                                RecommendationType::CachingStrategy
997                            }
998                            crate::core::types::RecommendationType::MemoryPooling => {
999                                RecommendationType::MemoryPooling
1000                            }
1001                            crate::core::types::RecommendationType::LazyInitialization => {
1002                                RecommendationType::LazyInitialization
1003                            }
1004                            crate::core::types::RecommendationType::Inlining => {
1005                                RecommendationType::Inlining
1006                            }
1007                            crate::core::types::RecommendationType::Vectorization => {
1008                                RecommendationType::Vectorization
1009                            }
1010                            crate::core::types::RecommendationType::Parallelization => {
1011                                RecommendationType::Parallelization
1012                            }
1013                        },
1014                        priority: match r.priority {
1015                            crate::core::types::Priority::Low => Priority::Low,
1016                            crate::core::types::Priority::Medium => Priority::Medium,
1017                            crate::core::types::Priority::High => Priority::High,
1018                            crate::core::types::Priority::Critical => Priority::Critical,
1019                        },
1020                        description: r.description,
1021                        expected_improvement: r.expected_improvement,
1022                        implementation_difficulty: match r.implementation_difficulty {
1023                            crate::core::types::ImplementationDifficulty::Easy => {
1024                                ImplementationDifficulty::Easy
1025                            }
1026                            crate::core::types::ImplementationDifficulty::Medium => {
1027                                ImplementationDifficulty::Medium
1028                            }
1029                            crate::core::types::ImplementationDifficulty::Hard => {
1030                                ImplementationDifficulty::Hard
1031                            }
1032                            crate::core::types::ImplementationDifficulty::VeryHard => {
1033                                ImplementationDifficulty::VeryHard
1034                            }
1035                        },
1036                    })
1037                    .collect(),
1038            },
1039        }
1040    }
1041}
1042
1043#[cfg(test)]
1044mod tests {
1045    use super::*;
1046
1047    #[test]
1048    fn test_allocation_info_creation() {
1049        let info = AllocationInfo::new(0x12345678, 1024);
1050
1051        assert_eq!(info.ptr, 0x12345678);
1052        assert_eq!(info.size, 1024);
1053        assert!(info.is_active());
1054        assert!(info.borrow_info.is_none());
1055        assert!(info.clone_info.is_some());
1056        assert!(!info.ownership_history_available);
1057    }
1058
1059    #[test]
1060    fn test_allocation_info_mark_deallocated() {
1061        let mut info = AllocationInfo::new(0x1000, 512);
1062        assert!(info.is_active());
1063
1064        info.mark_deallocated();
1065        assert!(!info.is_active());
1066        assert!(info.timestamp_dealloc.is_some());
1067    }
1068
1069    #[test]
1070    fn test_allocation_info_enhance_with_type_info() {
1071        let mut info = AllocationInfo::new(0x1000, 512);
1072
1073        // Test with Rc type
1074        info.enhance_with_type_info("std::rc::Rc<String>");
1075        if let Some(clone_info) = &info.clone_info {
1076            assert_eq!(clone_info.clone_count, 2);
1077        }
1078
1079        // Test with Vec type
1080        info.enhance_with_type_info("Vec<i32>");
1081        if let Some(borrow_info) = &info.borrow_info {
1082            assert_eq!(borrow_info.immutable_borrows, 4);
1083            assert_eq!(borrow_info.mutable_borrows, 2);
1084        }
1085    }
1086
1087    #[test]
1088    fn test_borrow_info_default() {
1089        let borrow_info = BorrowInfo::default();
1090
1091        assert_eq!(borrow_info.immutable_borrows, 0);
1092        assert_eq!(borrow_info.mutable_borrows, 0);
1093        assert_eq!(borrow_info.max_concurrent_borrows, 0);
1094        assert_eq!(borrow_info.last_borrow_timestamp, None);
1095    }
1096
1097    #[test]
1098    fn test_clone_info_default() {
1099        let clone_info = CloneInfo::default();
1100
1101        assert_eq!(clone_info.clone_count, 0);
1102        assert!(!clone_info.is_clone);
1103        assert_eq!(clone_info.original_ptr, None);
1104    }
1105
1106    #[test]
1107    fn test_allocation_info_serialization() {
1108        let info = AllocationInfo::new(0x1000, 512);
1109
1110        // Test that it can be serialized
1111        let serialized = serde_json::to_string(&info);
1112        assert!(serialized.is_ok());
1113
1114        // Test that serialized data contains expected fields
1115        let json_str = serialized.expect("Failed to serialize AllocationInfo to JSON");
1116        assert!(json_str.contains("ptr"));
1117        assert!(json_str.contains("size"));
1118    }
1119}