use std::path::Path;
#[derive(Debug, Clone, Default)]
pub struct PdbCurFrame {
pub f_lineno: i32,
pub co_filename: String,
pub co_name: String,
}
#[derive(Debug, Clone, Default)]
pub struct PdbSegmentInfo {
pub curframe: PdbCurFrame,
pub stack_len: usize,
pub initial_stack_length: usize,
}
pub fn current_line(_pl: &(), segment_info: &PdbSegmentInfo) -> String {
segment_info.curframe.f_lineno.to_string()
}
pub fn current_file(_pl: &(), segment_info: &PdbSegmentInfo, basename: bool) -> String {
let filename = &segment_info.curframe.co_filename;
if basename {
Path::new(filename)
.file_name()
.map(|n| n.to_string_lossy().into_owned())
.unwrap_or_else(|| filename.clone())
} else {
filename.clone()
}
}
pub fn current_code_name(_pl: &(), segment_info: &PdbSegmentInfo) -> String {
segment_info.curframe.co_name.clone()
}
pub fn current_context(_pl: &(), segment_info: &PdbSegmentInfo) -> String {
let name = &segment_info.curframe.co_name;
if name == "<module>" {
Path::new(&segment_info.curframe.co_filename)
.file_name()
.map(|n| n.to_string_lossy().into_owned())
.unwrap_or_else(|| segment_info.curframe.co_filename.clone())
} else {
name.clone()
}
}
pub fn stack_depth(_pl: &(), segment_info: &PdbSegmentInfo, full_stack: bool) -> String {
let subtract = if full_stack {
0
} else {
segment_info.initial_stack_length
};
(segment_info.stack_len.saturating_sub(subtract)).to_string()
}
#[cfg(test)]
mod tests {
use super::*;
fn sample() -> PdbSegmentInfo {
PdbSegmentInfo {
curframe: PdbCurFrame {
f_lineno: 42,
co_filename: "/home/user/work/main.py".into(),
co_name: "frobnicate".into(),
},
stack_len: 5,
initial_stack_length: 2,
}
}
#[test]
fn current_line_returns_lineno_as_string() {
assert_eq!(current_line(&(), &sample()), "42");
}
#[test]
fn current_file_basename_true_returns_filename_only() {
assert_eq!(current_file(&(), &sample(), true), "main.py");
}
#[test]
fn current_file_basename_false_returns_full_path() {
assert_eq!(
current_file(&(), &sample(), false),
"/home/user/work/main.py"
);
}
#[test]
fn current_code_name_returns_co_name() {
assert_eq!(current_code_name(&(), &sample()), "frobnicate");
}
#[test]
fn current_context_returns_co_name_for_normal_function() {
assert_eq!(current_context(&(), &sample()), "frobnicate");
}
#[test]
fn current_context_substitutes_module_with_basename() {
let mut info = sample();
info.curframe.co_name = "<module>".into();
assert_eq!(current_context(&(), &info), "main.py");
}
#[test]
fn stack_depth_default_subtracts_initial() {
assert_eq!(stack_depth(&(), &sample(), false), "3");
}
#[test]
fn stack_depth_full_stack_returns_raw_len() {
assert_eq!(stack_depth(&(), &sample(), true), "5");
}
}