use std::path::Path;
use std::path::PathBuf;
use std::sync::Arc;
use serde::Serialize;
use vortex::array::stream::ArrayStreamExt;
use vortex::error::VortexResult;
use vortex::file::OpenOptionsSessionExt;
use vortex::layout::LayoutRef;
use vortex::session::VortexSession;
#[derive(Debug, clap::Parser)]
pub struct TreeArgs {
#[clap(subcommand)]
pub mode: TreeMode,
}
#[derive(Debug, clap::Subcommand)]
pub enum TreeMode {
Array {
file: PathBuf,
#[arg(long)]
json: bool,
},
Layout {
file: PathBuf,
#[arg(short, long)]
verbose: bool,
#[arg(long)]
json: bool,
},
}
#[derive(Serialize)]
pub struct LayoutTreeNode {
pub encoding: String,
pub dtype: String,
pub row_count: u64,
pub metadata_bytes: usize,
pub segment_ids: Vec<u32>,
pub children: Vec<LayoutTreeNodeWithName>,
}
#[derive(Serialize)]
pub struct LayoutTreeNodeWithName {
pub name: String,
#[serde(flatten)]
pub node: LayoutTreeNode,
}
pub async fn exec_tree(session: &VortexSession, args: TreeArgs) -> VortexResult<()> {
match args.mode {
TreeMode::Array { file, json } => exec_array_tree(session, &file, json).await?,
TreeMode::Layout {
file,
verbose,
json,
} => exec_layout_tree(session, &file, verbose, json).await?,
}
Ok(())
}
async fn exec_array_tree(session: &VortexSession, file: &Path, _json: bool) -> VortexResult<()> {
let full = session
.open_options()
.open_path(file)
.await?
.scan()?
.into_array_stream()?
.read_all()
.await?;
println!("{}", full.display_tree());
Ok(())
}
async fn exec_layout_tree(
session: &VortexSession,
file: &Path,
verbose: bool,
json: bool,
) -> VortexResult<()> {
let vxf = session.open_options().open_path(file).await?;
let footer = vxf.footer();
if json {
let tree = layout_to_json(Arc::clone(footer.layout()))?;
let json_output = serde_json::to_string_pretty(&tree)
.map_err(|e| vortex::error::vortex_err!("Failed to serialize JSON: {e}"))?;
println!("{json_output}");
} else if verbose {
let output = footer
.layout()
.display_tree_with_segments(vxf.segment_source())
.await?;
println!("{output}");
} else {
println!("{}", footer.layout().display_tree());
}
Ok(())
}
fn layout_to_json(layout: LayoutRef) -> VortexResult<LayoutTreeNode> {
let children = layout.children()?;
let child_names: Vec<_> = layout.child_names().collect();
let children_json: Vec<LayoutTreeNodeWithName> = children
.into_iter()
.zip(child_names.into_iter())
.map(|(child, name)| {
let node = layout_to_json(child)?;
Ok(LayoutTreeNodeWithName {
name: name.to_string(),
node,
})
})
.collect::<VortexResult<Vec<_>>>()?;
Ok(LayoutTreeNode {
encoding: layout.encoding().to_string(),
dtype: layout.dtype().to_string(),
row_count: layout.row_count(),
metadata_bytes: layout.metadata().len(),
segment_ids: layout.segment_ids().iter().map(|s| **s).collect(),
children: children_json,
})
}