use borrowscope_runtime::{
get_events, reset, track_ffi_call, track_static_access, track_static_init,
track_union_field_access,
};
use std::sync::atomic::{AtomicU32, Ordering};
mod ffi_simulation {
pub fn process_buffer(ptr: *const u8, len: usize) -> i32 {
let slice = unsafe { std::slice::from_raw_parts(ptr, len) };
slice.iter().map(|&b| b as i32).sum()
}
pub fn get_system_time() -> u64 {
1234567890
}
}
fn tracked_process_buffer(data: &[u8]) -> i32 {
track_ffi_call("process_buffer", "manual_tracking.rs:42");
ffi_simulation::process_buffer(data.as_ptr(), data.len())
}
fn tracked_get_system_time() -> u64 {
track_ffi_call("get_system_time", "manual_tracking.rs:48");
ffi_simulation::get_system_time()
}
#[repr(C)]
union NumberUnion {
int_val: i32,
float_val: f32,
bytes: [u8; 4],
}
fn read_as_int(data: &NumberUnion) -> i32 {
track_union_field_access("NumberUnion", "int_val", "manual_tracking.rs:64");
unsafe { data.int_val }
}
fn read_as_float(data: &NumberUnion) -> f32 {
track_union_field_access("NumberUnion", "float_val", "manual_tracking.rs:70");
unsafe { data.float_val }
}
fn read_as_bytes(data: &NumberUnion) -> [u8; 4] {
track_union_field_access("NumberUnion", "bytes", "manual_tracking.rs:76");
unsafe { data.bytes }
}
static REQUEST_COUNTER: AtomicU32 = AtomicU32::new(0);
static ERROR_COUNTER: AtomicU32 = AtomicU32::new(0);
const REQUEST_COUNTER_ID: usize = 1;
const ERROR_COUNTER_ID: usize = 2;
fn init_statics() {
track_static_init(
"REQUEST_COUNTER",
REQUEST_COUNTER_ID,
"AtomicU32",
false, (),
);
track_static_init(
"ERROR_COUNTER",
ERROR_COUNTER_ID,
"AtomicU32",
false,
(),
);
}
fn increment_requests() {
track_static_access(
REQUEST_COUNTER_ID,
"REQUEST_COUNTER",
true, "manual_tracking.rs:108",
);
REQUEST_COUNTER.fetch_add(1, Ordering::SeqCst);
}
fn get_request_count() -> u32 {
track_static_access(
REQUEST_COUNTER_ID,
"REQUEST_COUNTER",
false, "manual_tracking.rs:119",
);
REQUEST_COUNTER.load(Ordering::SeqCst)
}
fn increment_errors() {
track_static_access(
ERROR_COUNTER_ID,
"ERROR_COUNTER",
true,
"manual_tracking.rs:130",
);
ERROR_COUNTER.fetch_add(1, Ordering::SeqCst);
}
fn main() {
reset();
println!("=== Manual Tracking Example ===\n");
println!("Demonstrating manual instrumentation for patterns that");
println!("the #[trace_borrow] macro cannot auto-detect.\n");
println!("--- Static Variable Initialization ---");
init_statics();
println!("\n--- FFI Calls ---");
let data = vec![1u8, 2, 3, 4, 5];
let sum = tracked_process_buffer(&data);
println!("FFI process_buffer returned: {}", sum);
let time = tracked_get_system_time();
println!("FFI get_system_time returned: {}", time);
println!("\n--- Union Field Access ---");
let num = NumberUnion { int_val: 42 };
let as_int = read_as_int(&num);
println!("Union as int: {}", as_int);
let as_float = read_as_float(&num);
println!("Union as float: {}", as_float);
let as_bytes = read_as_bytes(&num);
println!("Union as bytes: {:?}", as_bytes);
println!("\n--- Static Variable Access ---");
increment_requests();
increment_requests();
increment_requests();
increment_errors();
let requests = get_request_count();
println!("Request count: {}", requests);
println!("\n--- Tracked Events ---");
let events = get_events();
for event in &events {
println!("{:?}", event);
}
println!("\n--- Summary ---");
println!("Total events tracked: {}", events.len());
println!(
" - StaticInit events: {}",
events
.iter()
.filter(|e| format!("{:?}", e).contains("StaticInit"))
.count()
);
println!(
" - StaticAccess events: {}",
events
.iter()
.filter(|e| format!("{:?}", e).contains("StaticAccess"))
.count()
);
println!(
" - FfiCall events: {}",
events
.iter()
.filter(|e| format!("{:?}", e).contains("FfiCall"))
.count()
);
println!(
" - UnionFieldAccess events: {}",
events
.iter()
.filter(|e| format!("{:?}", e).contains("UnionFieldAccess"))
.count()
);
}