1use std::path::Path;
7use std::path::PathBuf;
8use std::sync::Arc;
9
10use serde::Serialize;
11use vortex::array::stream::ArrayStreamExt;
12use vortex::error::VortexResult;
13use vortex::file::OpenOptionsSessionExt;
14use vortex::layout::LayoutRef;
15use vortex::session::VortexSession;
16
17#[derive(Debug, clap::Parser)]
19pub struct TreeArgs {
20 #[clap(subcommand)]
22 pub mode: TreeMode,
23}
24
25#[derive(Debug, clap::Subcommand)]
27pub enum TreeMode {
28 Array {
30 file: PathBuf,
32 #[arg(long)]
34 json: bool,
35 },
36 Layout {
38 file: PathBuf,
40 #[arg(short, long)]
42 verbose: bool,
43 #[arg(long)]
45 json: bool,
46 },
47}
48
49#[derive(Serialize)]
51pub struct LayoutTreeNode {
52 pub encoding: String,
54 pub dtype: String,
56 pub row_count: u64,
58 pub metadata_bytes: usize,
60 pub segment_ids: Vec<u32>,
62 pub children: Vec<LayoutTreeNodeWithName>,
64}
65
66#[derive(Serialize)]
68pub struct LayoutTreeNodeWithName {
69 pub name: String,
71 #[serde(flatten)]
73 pub node: LayoutTreeNode,
74}
75
76pub async fn exec_tree(session: &VortexSession, args: TreeArgs) -> VortexResult<()> {
82 match args.mode {
83 TreeMode::Array { file, json } => exec_array_tree(session, &file, json).await?,
84 TreeMode::Layout {
85 file,
86 verbose,
87 json,
88 } => exec_layout_tree(session, &file, verbose, json).await?,
89 }
90
91 Ok(())
92}
93
94async fn exec_array_tree(session: &VortexSession, file: &Path, _json: bool) -> VortexResult<()> {
95 let full = session
96 .open_options()
97 .open_path(file)
98 .await?
99 .scan()?
100 .into_array_stream()?
101 .read_all()
102 .await?;
103
104 println!("{}", full.display_tree());
105
106 Ok(())
107}
108
109async fn exec_layout_tree(
110 session: &VortexSession,
111 file: &Path,
112 verbose: bool,
113 json: bool,
114) -> VortexResult<()> {
115 let vxf = session.open_options().open_path(file).await?;
116 let footer = vxf.footer();
117
118 if json {
119 let tree = layout_to_json(Arc::clone(footer.layout()))?;
120 let json_output = serde_json::to_string_pretty(&tree)
121 .map_err(|e| vortex::error::vortex_err!("Failed to serialize JSON: {e}"))?;
122 println!("{json_output}");
123 } else if verbose {
124 let output = footer
126 .layout()
127 .display_tree_with_segments(vxf.segment_source())
128 .await?;
129 println!("{output}");
130 } else {
131 println!("{}", footer.layout().display_tree());
133 }
134
135 Ok(())
136}
137
138fn layout_to_json(layout: LayoutRef) -> VortexResult<LayoutTreeNode> {
139 let children = layout.children()?;
140 let child_names: Vec<_> = layout.child_names().collect();
141
142 let children_json: Vec<LayoutTreeNodeWithName> = children
143 .into_iter()
144 .zip(child_names.into_iter())
145 .map(|(child, name)| {
146 let node = layout_to_json(child)?;
147 Ok(LayoutTreeNodeWithName {
148 name: name.to_string(),
149 node,
150 })
151 })
152 .collect::<VortexResult<Vec<_>>>()?;
153
154 Ok(LayoutTreeNode {
155 encoding: layout.encoding().to_string(),
156 dtype: layout.dtype().to_string(),
157 row_count: layout.row_count(),
158 metadata_bytes: layout.metadata().len(),
159 segment_ids: layout.segment_ids().iter().map(|s| **s).collect(),
160 children: children_json,
161 })
162}