use std::path::PathBuf;
use serde::Serialize;
use vortex::error::VortexResult;
use vortex::file::OpenOptionsSessionExt;
use vortex::session::VortexSession;
use crate::segment_tree::collect_segment_tree;
#[derive(Debug, clap::Parser)]
pub struct SegmentsArgs {
pub file: PathBuf,
}
#[derive(Serialize)]
struct SegmentsOutput {
columns: Vec<ColumnInfo>,
}
#[derive(Serialize)]
struct ColumnInfo {
name: String,
segments: Vec<SegmentInfo>,
}
#[derive(Serialize)]
struct SegmentInfo {
name: String,
row_offset: u64,
row_count: u64,
byte_offset: u64,
byte_length: u32,
alignment: usize,
byte_gap: u64,
}
pub async fn exec_segments(session: &VortexSession, args: SegmentsArgs) -> VortexResult<()> {
let vxf = session.open_options().open_path(args.file).await?;
let footer = vxf.footer();
let mut segment_tree = collect_segment_tree(footer.layout().as_ref(), footer.segment_map());
let columns: Vec<ColumnInfo> = segment_tree
.segment_ordering
.iter()
.filter_map(|name| {
let mut segments = segment_tree.segments.remove(name)?;
segments.sort_by(|a, b| a.spec.offset.cmp(&b.spec.offset));
let mut current_offset = 0u64;
let segment_infos: Vec<SegmentInfo> = segments
.into_iter()
.map(|seg| {
let byte_gap = if current_offset == 0 {
0
} else {
seg.spec.offset.saturating_sub(current_offset)
};
current_offset = seg.spec.offset + seg.spec.length as u64;
SegmentInfo {
name: seg.name.to_string(),
row_offset: seg.row_offset,
row_count: seg.row_count,
byte_offset: seg.spec.offset,
byte_length: seg.spec.length,
alignment: *seg.spec.alignment,
byte_gap,
}
})
.collect();
Some(ColumnInfo {
name: name.to_string(),
segments: segment_infos,
})
})
.collect();
let output = SegmentsOutput { columns };
let json_output = serde_json::to_string_pretty(&output)
.map_err(|e| vortex::error::vortex_err!("Failed to serialize JSON: {e}"))?;
println!("{json_output}");
Ok(())
}