use serde::{Deserialize, Serialize};
use super::generic::MemoryImpact;
use super::leak_detection::LeakRiskLevel;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct OwnershipHierarchy {
pub root_owners: Vec<OwnershipNode>,
pub max_depth: usize,
pub total_objects: usize,
pub transfer_events: Vec<OwnershipTransferEvent>,
pub weak_references: Vec<WeakReferenceInfo>,
pub circular_references: Vec<CircularReferenceInfo>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct OwnershipNode {
pub object_id: usize,
pub type_name: String,
pub ownership_type: OwnershipType,
pub owned_objects: Vec<OwnershipNode>,
pub reference_count: Option<usize>,
pub weak_reference_count: Option<usize>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum OwnershipType {
Unique,
SharedSingleThreaded,
SharedMultiThreaded,
Borrowed,
Weak,
Raw,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct OwnershipTransferEvent {
pub source_object: usize,
pub target_object: usize,
pub transfer_type: OwnershipTransferType,
pub timestamp: u64,
pub mechanism: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum OwnershipTransferType {
Move,
Clone,
Borrow,
ReferenceIncrement,
ReferenceDecrement,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct WeakReferenceInfo {
pub weak_ref_id: usize,
pub target_object_id: usize,
pub weak_ref_type: WeakReferenceType,
pub target_alive: bool,
pub upgrade_attempts: u32,
pub successful_upgrades: u32,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum WeakReferenceType {
RcWeak,
ArcWeak,
Custom,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CircularReferenceInfo {
pub cycle_objects: Vec<usize>,
pub detection_timestamp: u64,
pub cycle_type: CircularReferenceType,
pub leak_risk: LeakRiskLevel,
pub resolution_suggestion: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum CircularReferenceType {
Direct,
Indirect,
SelfReferential,
Complex,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct TypeRelationshipInfo {
pub type_name: String,
pub parent_types: Vec<ParentTypeInfo>,
pub child_types: Vec<ChildTypeInfo>,
pub composed_types: Vec<ComposedTypeInfo>,
pub complexity_score: u32,
pub inheritance_depth: u32,
pub composition_breadth: u32,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ParentTypeInfo {
pub type_name: String,
pub relationship_type: RelationshipType,
pub inheritance_level: u32,
pub memory_impact: MemoryImpact,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ChildTypeInfo {
pub type_name: String,
pub relationship_type: RelationshipType,
pub specialization_level: u32,
pub usage_frequency: u32,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ComposedTypeInfo {
pub type_name: String,
pub field_name: String,
pub composition_type: CompositionType,
pub memory_offset: Option<usize>,
pub access_frequency: u32,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum RelationshipType {
TraitImplementation,
TraitBound,
Inheritance,
Association,
Composition,
Dependency,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum CompositionType {
Field,
AssociatedType,
GenericParameter,
NestedType,
Reference,
SmartPointer,
}
impl From<crate::core::types::TypeRelationshipInfo> for TypeRelationshipInfo {
fn from(old: crate::core::types::TypeRelationshipInfo) -> Self {
Self {
type_name: old.type_name,
parent_types: old
.parent_types
.into_iter()
.map(|p| ParentTypeInfo {
type_name: p.type_name,
relationship_type: match p.relationship_type {
crate::core::types::RelationshipType::TraitImplementation => {
RelationshipType::TraitImplementation
}
crate::core::types::RelationshipType::TraitBound => {
RelationshipType::TraitBound
}
crate::core::types::RelationshipType::Inheritance => {
RelationshipType::Inheritance
}
crate::core::types::RelationshipType::Association => {
RelationshipType::Association
}
crate::core::types::RelationshipType::Composition => {
RelationshipType::Composition
}
crate::core::types::RelationshipType::Dependency => {
RelationshipType::Dependency
}
},
inheritance_level: p.inheritance_level,
memory_impact: match p.memory_impact {
crate::core::types::MemoryImpact::None => MemoryImpact::None,
crate::core::types::MemoryImpact::SizeIncrease(s) => {
MemoryImpact::SizeIncrease(s)
}
crate::core::types::MemoryImpact::AlignmentChange(s) => {
MemoryImpact::AlignmentChange(s)
}
crate::core::types::MemoryImpact::LayoutChange(s) => {
MemoryImpact::LayoutChange(s)
}
},
})
.collect(),
child_types: old
.child_types
.into_iter()
.map(|c| ChildTypeInfo {
type_name: c.type_name,
relationship_type: match c.relationship_type {
crate::core::types::RelationshipType::TraitImplementation => {
RelationshipType::TraitImplementation
}
crate::core::types::RelationshipType::TraitBound => {
RelationshipType::TraitBound
}
crate::core::types::RelationshipType::Inheritance => {
RelationshipType::Inheritance
}
crate::core::types::RelationshipType::Association => {
RelationshipType::Association
}
crate::core::types::RelationshipType::Composition => {
RelationshipType::Composition
}
crate::core::types::RelationshipType::Dependency => {
RelationshipType::Dependency
}
},
specialization_level: c.specialization_level,
usage_frequency: c.usage_frequency,
})
.collect(),
composed_types: old
.composed_types
.into_iter()
.map(|c| ComposedTypeInfo {
type_name: c.type_name,
field_name: c.field_name,
composition_type: match c.composition_type {
crate::core::types::CompositionType::Field => CompositionType::Field,
crate::core::types::CompositionType::AssociatedType => {
CompositionType::AssociatedType
}
crate::core::types::CompositionType::GenericParameter => {
CompositionType::GenericParameter
}
crate::core::types::CompositionType::NestedType => {
CompositionType::NestedType
}
crate::core::types::CompositionType::Reference => {
CompositionType::Reference
}
crate::core::types::CompositionType::SmartPointer => {
CompositionType::SmartPointer
}
},
memory_offset: c.memory_offset,
access_frequency: c.access_frequency,
})
.collect(),
complexity_score: old.complexity_score,
inheritance_depth: old.inheritance_depth,
composition_breadth: old.composition_breadth,
}
}
}
impl From<crate::core::types::OwnershipNode> for OwnershipNode {
fn from(old: crate::core::types::OwnershipNode) -> Self {
Self {
object_id: old.object_id,
type_name: old.type_name,
ownership_type: match old.ownership_type {
crate::core::types::OwnershipType::Unique => OwnershipType::Unique,
crate::core::types::OwnershipType::SharedSingleThreaded => {
OwnershipType::SharedSingleThreaded
}
crate::core::types::OwnershipType::SharedMultiThreaded => {
OwnershipType::SharedMultiThreaded
}
crate::core::types::OwnershipType::Borrowed => OwnershipType::Borrowed,
crate::core::types::OwnershipType::Weak => OwnershipType::Weak,
crate::core::types::OwnershipType::Raw => OwnershipType::Raw,
},
owned_objects: old.owned_objects.into_iter().map(Into::into).collect(),
reference_count: old.reference_count,
weak_reference_count: old.weak_reference_count,
}
}
}
impl From<crate::core::types::OwnershipTransferEvent> for OwnershipTransferEvent {
fn from(old: crate::core::types::OwnershipTransferEvent) -> Self {
Self {
source_object: old.source_object,
target_object: old.target_object,
transfer_type: match old.transfer_type {
crate::core::types::OwnershipTransferType::Move => OwnershipTransferType::Move,
crate::core::types::OwnershipTransferType::Clone => OwnershipTransferType::Clone,
crate::core::types::OwnershipTransferType::Borrow => OwnershipTransferType::Borrow,
crate::core::types::OwnershipTransferType::ReferenceIncrement => {
OwnershipTransferType::ReferenceIncrement
}
crate::core::types::OwnershipTransferType::ReferenceDecrement => {
OwnershipTransferType::ReferenceDecrement
}
},
timestamp: old.timestamp,
mechanism: old.mechanism,
}
}
}
impl From<crate::core::types::WeakReferenceInfo> for WeakReferenceInfo {
fn from(old: crate::core::types::WeakReferenceInfo) -> Self {
Self {
weak_ref_id: old.weak_ref_id,
target_object_id: old.target_object_id,
weak_ref_type: match old.weak_ref_type {
crate::core::types::WeakReferenceType::RcWeak => WeakReferenceType::RcWeak,
crate::core::types::WeakReferenceType::ArcWeak => WeakReferenceType::ArcWeak,
crate::core::types::WeakReferenceType::Custom => WeakReferenceType::Custom,
},
target_alive: old.target_alive,
upgrade_attempts: old.upgrade_attempts,
successful_upgrades: old.successful_upgrades,
}
}
}
impl From<crate::core::types::CircularReferenceInfo> for CircularReferenceInfo {
fn from(old: crate::core::types::CircularReferenceInfo) -> Self {
Self {
cycle_objects: old.cycle_objects,
detection_timestamp: old.detection_timestamp,
cycle_type: match old.cycle_type {
crate::core::types::CircularReferenceType::Direct => CircularReferenceType::Direct,
crate::core::types::CircularReferenceType::Indirect => {
CircularReferenceType::Indirect
}
crate::core::types::CircularReferenceType::SelfReferential => {
CircularReferenceType::SelfReferential
}
crate::core::types::CircularReferenceType::Complex => {
CircularReferenceType::Complex
}
},
leak_risk: match old.leak_risk {
crate::core::types::LeakRiskLevel::Low => LeakRiskLevel::Low,
crate::core::types::LeakRiskLevel::Medium => LeakRiskLevel::Medium,
crate::core::types::LeakRiskLevel::High => LeakRiskLevel::High,
crate::core::types::LeakRiskLevel::Critical => LeakRiskLevel::Critical,
},
resolution_suggestion: old.resolution_suggestion,
}
}
}
impl From<crate::core::types::OwnershipHierarchy> for OwnershipHierarchy {
fn from(old: crate::core::types::OwnershipHierarchy) -> Self {
Self {
root_owners: old.root_owners.into_iter().map(Into::into).collect(),
max_depth: old.max_depth,
total_objects: old.total_objects,
transfer_events: old.transfer_events.into_iter().map(Into::into).collect(),
weak_references: old.weak_references.into_iter().map(Into::into).collect(),
circular_references: old
.circular_references
.into_iter()
.map(Into::into)
.collect(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ownership_hierarchy() {
let hierarchy = OwnershipHierarchy {
root_owners: vec![],
max_depth: 3,
total_objects: 10,
transfer_events: vec![],
weak_references: vec![],
circular_references: vec![],
};
assert_eq!(hierarchy.max_depth, 3);
assert_eq!(hierarchy.total_objects, 10);
}
#[test]
fn test_ownership_type() {
let ownership = OwnershipType::SharedMultiThreaded;
assert!(matches!(ownership, OwnershipType::SharedMultiThreaded));
}
#[test]
fn test_weak_reference_info() {
let weak_ref = WeakReferenceInfo {
weak_ref_id: 1,
target_object_id: 100,
weak_ref_type: WeakReferenceType::ArcWeak,
target_alive: true,
upgrade_attempts: 5,
successful_upgrades: 4,
};
assert_eq!(weak_ref.upgrade_attempts, 5);
assert!(weak_ref.target_alive);
}
#[test]
fn test_ownership_node_nested() {
let child = OwnershipNode {
object_id: 2,
type_name: "Child".to_string(),
ownership_type: OwnershipType::Unique,
owned_objects: vec![],
reference_count: None,
weak_reference_count: None,
};
let parent = OwnershipNode {
object_id: 1,
type_name: "Parent".to_string(),
ownership_type: OwnershipType::SharedMultiThreaded,
owned_objects: vec![child],
reference_count: Some(3),
weak_reference_count: Some(1),
};
assert_eq!(
parent.owned_objects.len(),
1,
"Parent should have one child"
);
assert_eq!(
parent.reference_count,
Some(3),
"Reference count should be 3"
);
}
#[test]
fn test_ownership_transfer_event() {
let event = OwnershipTransferEvent {
source_object: 1,
target_object: 2,
transfer_type: OwnershipTransferType::Move,
timestamp: 1000,
mechanism: "std::move".to_string(),
};
assert_eq!(event.source_object, 1, "Source should match");
assert_eq!(event.target_object, 2, "Target should match");
assert_eq!(
event.transfer_type,
OwnershipTransferType::Move,
"Transfer type should be Move"
);
}
#[test]
fn test_ownership_transfer_type_variants() {
let variants = vec![
OwnershipTransferType::Move,
OwnershipTransferType::Clone,
OwnershipTransferType::Borrow,
OwnershipTransferType::ReferenceIncrement,
OwnershipTransferType::ReferenceDecrement,
];
for variant in &variants {
let debug_str = format!("{variant:?}");
assert!(
!debug_str.is_empty(),
"Variant should have debug representation"
);
}
}
#[test]
fn test_circular_reference_info() {
let circular = CircularReferenceInfo {
cycle_objects: vec![1, 2, 3],
detection_timestamp: 1000,
cycle_type: CircularReferenceType::Indirect,
leak_risk: LeakRiskLevel::High,
resolution_suggestion: "Use Weak references".to_string(),
};
assert_eq!(
circular.cycle_objects.len(),
3,
"Should have 3 objects in cycle"
);
assert_eq!(
circular.cycle_type,
CircularReferenceType::Indirect,
"Cycle type should be Indirect"
);
}
#[test]
fn test_circular_reference_type_variants() {
assert_eq!(CircularReferenceType::Direct, CircularReferenceType::Direct);
assert_eq!(
CircularReferenceType::Indirect,
CircularReferenceType::Indirect
);
assert_eq!(
CircularReferenceType::SelfReferential,
CircularReferenceType::SelfReferential
);
assert_eq!(
CircularReferenceType::Complex,
CircularReferenceType::Complex
);
assert_ne!(
CircularReferenceType::Direct,
CircularReferenceType::Indirect
);
}
#[test]
fn test_type_relationship_info() {
let info = TypeRelationshipInfo {
type_name: "MyStruct".to_string(),
parent_types: vec![],
child_types: vec![],
composed_types: vec![],
complexity_score: 10,
inheritance_depth: 2,
composition_breadth: 5,
};
assert_eq!(info.type_name, "MyStruct", "Type name should match");
assert_eq!(info.complexity_score, 10, "Complexity score should match");
}
#[test]
fn test_parent_type_info() {
let parent = ParentTypeInfo {
type_name: "ParentTrait".to_string(),
relationship_type: RelationshipType::TraitImplementation,
inheritance_level: 1,
memory_impact: MemoryImpact::None,
};
assert_eq!(
parent.type_name, "ParentTrait",
"Parent type name should match"
);
assert_eq!(parent.inheritance_level, 1, "Inheritance level should be 1");
}
#[test]
fn test_relationship_type_variants() {
let variants = vec![
RelationshipType::TraitImplementation,
RelationshipType::TraitBound,
RelationshipType::Inheritance,
RelationshipType::Association,
RelationshipType::Composition,
RelationshipType::Dependency,
];
for variant in &variants {
let debug_str = format!("{variant:?}");
assert!(
!debug_str.is_empty(),
"Variant should have debug representation"
);
}
}
#[test]
fn test_composition_type_variants() {
let variants = vec![
CompositionType::Field,
CompositionType::AssociatedType,
CompositionType::GenericParameter,
CompositionType::NestedType,
CompositionType::Reference,
CompositionType::SmartPointer,
];
for variant in &variants {
let debug_str = format!("{variant:?}");
assert!(
!debug_str.is_empty(),
"Variant should have debug representation"
);
}
}
#[test]
fn test_composed_type_info() {
let composed = ComposedTypeInfo {
type_name: "InnerType".to_string(),
field_name: "inner".to_string(),
composition_type: CompositionType::Field,
memory_offset: Some(16),
access_frequency: 100,
};
assert_eq!(composed.field_name, "inner", "Field name should match");
assert_eq!(
composed.memory_offset,
Some(16),
"Memory offset should be 16"
);
}
#[test]
fn test_ownership_hierarchy_multiple_roots() {
let root1 = OwnershipNode {
object_id: 1,
type_name: "Root1".to_string(),
ownership_type: OwnershipType::Unique,
owned_objects: vec![],
reference_count: None,
weak_reference_count: None,
};
let root2 = OwnershipNode {
object_id: 2,
type_name: "Root2".to_string(),
ownership_type: OwnershipType::SharedSingleThreaded,
owned_objects: vec![],
reference_count: Some(2),
weak_reference_count: None,
};
let hierarchy = OwnershipHierarchy {
root_owners: vec![root1, root2],
max_depth: 5,
total_objects: 10,
transfer_events: vec![],
weak_references: vec![],
circular_references: vec![],
};
assert_eq!(
hierarchy.root_owners.len(),
2,
"Should have two root owners"
);
}
#[test]
fn test_ownership_type_serialization() {
let ownership = OwnershipType::SharedMultiThreaded;
let json = serde_json::to_string(&ownership);
assert!(json.is_ok(), "Should serialize to JSON");
let deserialized: Result<OwnershipType, _> = serde_json::from_str(&json.unwrap());
assert!(deserialized.is_ok(), "Should deserialize from JSON");
assert_eq!(
deserialized.unwrap(),
OwnershipType::SharedMultiThreaded,
"Should preserve value"
);
}
#[test]
fn test_weak_reference_type_variants() {
assert_eq!(WeakReferenceType::RcWeak, WeakReferenceType::RcWeak);
assert_eq!(WeakReferenceType::ArcWeak, WeakReferenceType::ArcWeak);
assert_eq!(WeakReferenceType::Custom, WeakReferenceType::Custom);
assert_ne!(WeakReferenceType::RcWeak, WeakReferenceType::ArcWeak);
}
#[test]
fn test_child_type_info() {
let child = ChildTypeInfo {
type_name: "ChildStruct".to_string(),
relationship_type: RelationshipType::Association,
specialization_level: 2,
usage_frequency: 50,
};
assert_eq!(
child.type_name, "ChildStruct",
"Child type name should match"
);
assert_eq!(child.usage_frequency, 50, "Usage frequency should match");
}
}