Vendor qroissant 0.3.0 baseline
This commit is contained in:
commit
53ac90fe84
56 changed files with 18309 additions and 0 deletions
278
crates/qroissant-python/src/repr/format.rs
Normal file
278
crates/qroissant-python/src/repr/format.rs
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
//! High-level format functions for each q value shape.
|
||||
//!
|
||||
//! Each function produces a multi-line ASCII repr string. Rendering is driven
|
||||
//! by the active [`FormattingOptions`] (read from the process-wide global).
|
||||
|
||||
use qroissant_core::Atom as CoreAtom;
|
||||
use qroissant_core::Dictionary as CoreDictionary;
|
||||
use qroissant_core::List as CoreList;
|
||||
use qroissant_core::Table as CoreTable;
|
||||
use qroissant_core::Value as CoreValue;
|
||||
use qroissant_core::Vector as CoreVector;
|
||||
use qroissant_core::VectorData;
|
||||
|
||||
use super::cell::atom_primitive_label;
|
||||
use super::cell::format_atom_cell;
|
||||
use super::cell::format_atom_raw;
|
||||
use super::cell::format_char_vector;
|
||||
use super::cell::format_vector_item;
|
||||
use super::cell::primitive_label;
|
||||
use super::cell::truncate;
|
||||
use super::options::active_options;
|
||||
use super::render::PreviewSlot;
|
||||
use super::render::preview_slots;
|
||||
use super::render::render_preview;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Attribute helper
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
fn attribute_label(attribute: qroissant_core::Attribute) -> &'static str {
|
||||
match attribute {
|
||||
qroissant_core::Attribute::None => "none",
|
||||
qroissant_core::Attribute::Sorted => "sorted",
|
||||
qroissant_core::Attribute::Unique => "unique",
|
||||
qroissant_core::Attribute::Parted => "parted",
|
||||
qroissant_core::Attribute::Grouped => "grouped",
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Atom
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
pub fn format_atom(atom: &CoreAtom) -> String {
|
||||
let label = atom_primitive_label(atom);
|
||||
render_preview(
|
||||
vec![format!("Atom [{label}]")],
|
||||
vec!["value".to_string()],
|
||||
vec![vec![format_atom_cell(atom)]],
|
||||
vec!["shape: (1,)".to_string()],
|
||||
)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Vector
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
pub fn format_vector(vector: &CoreVector) -> String {
|
||||
let len = vector.len();
|
||||
let data = vector.data();
|
||||
let label = primitive_label(data);
|
||||
let attr = vector.attribute();
|
||||
|
||||
let rows = match data {
|
||||
VectorData::Char(chars) => {
|
||||
vec![vec![format_char_vector(chars)]]
|
||||
}
|
||||
_ => {
|
||||
let opts = active_options();
|
||||
preview_slots(len, opts.max_rows, opts.row_display)
|
||||
.into_iter()
|
||||
.map(|slot| match slot {
|
||||
PreviewSlot::Index(i) => vec![format_vector_item(data, i)],
|
||||
PreviewSlot::Ellipsis => vec!["...".to_string()],
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
};
|
||||
|
||||
render_preview(
|
||||
vec![format!("Vector [{label}, attr={}]", attribute_label(attr))],
|
||||
vec!["value".to_string()],
|
||||
rows,
|
||||
vec![format!("shape: ({len},)")],
|
||||
)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// List
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Compact single-line summary of any `CoreValue` (used for list/dict cells).
|
||||
fn inline_value_summary(value: &CoreValue) -> String {
|
||||
match value {
|
||||
CoreValue::Atom(atom) => truncate(format!(
|
||||
"{} [{}]",
|
||||
format_atom_raw(atom),
|
||||
atom_primitive_label(atom)
|
||||
)),
|
||||
CoreValue::Vector(vector) => {
|
||||
let label = primitive_label(vector.data());
|
||||
let len = vector.len();
|
||||
match vector.data() {
|
||||
VectorData::Char(chars) => truncate(format_char_vector(chars)),
|
||||
_ => truncate(format!("vector<{label}>[{len}]")),
|
||||
}
|
||||
}
|
||||
CoreValue::List(list) => truncate(format!("list[{}]", list.len())),
|
||||
CoreValue::Dictionary(dict) => truncate(format!("dict[{}]", dict.len())),
|
||||
CoreValue::Table(table) => {
|
||||
truncate(format!("table[{}x{}]", table.len(), table.num_columns()))
|
||||
}
|
||||
CoreValue::UnaryPrimitive { opcode } => truncate(format!("unary(0x{opcode:02x})")),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn format_list(list: &CoreList) -> String {
|
||||
let len = list.len();
|
||||
let opts = active_options();
|
||||
let attr = list.attribute();
|
||||
|
||||
let rows = preview_slots(len, opts.max_rows, opts.row_display)
|
||||
.into_iter()
|
||||
.map(|slot| match slot {
|
||||
PreviewSlot::Index(i) => vec![inline_value_summary(&list.values()[i])],
|
||||
PreviewSlot::Ellipsis => vec!["...".to_string()],
|
||||
})
|
||||
.collect();
|
||||
|
||||
render_preview(
|
||||
vec![format!("List [list, attr={}]", attribute_label(attr))],
|
||||
vec!["value".to_string()],
|
||||
rows,
|
||||
vec![format!("shape: ({len},)")],
|
||||
)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Dictionary
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
pub fn format_dictionary(dict: &CoreDictionary) -> String {
|
||||
let size = dict.len();
|
||||
let sorted = dict.sorted();
|
||||
|
||||
let all_rows = vec![
|
||||
vec!["keys".to_string(), inline_value_summary(dict.keys())],
|
||||
vec!["values".to_string(), inline_value_summary(dict.values())],
|
||||
];
|
||||
|
||||
let opts = active_options();
|
||||
let rows = preview_slots(all_rows.len(), opts.max_rows, opts.row_display)
|
||||
.into_iter()
|
||||
.map(|slot| match slot {
|
||||
PreviewSlot::Index(i) => all_rows[i].clone(),
|
||||
PreviewSlot::Ellipsis => vec!["...".to_string(), "...".to_string()],
|
||||
})
|
||||
.collect();
|
||||
|
||||
render_preview(
|
||||
vec![format!("Dictionary [dict, sorted={sorted}]")],
|
||||
vec!["part".to_string(), "value".to_string()],
|
||||
rows,
|
||||
vec![format!("shape: ({size},)")],
|
||||
)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Table
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
fn column_primitive_label(col: &CoreValue) -> &'static str {
|
||||
match col {
|
||||
CoreValue::Vector(v) => primitive_label(v.data()),
|
||||
CoreValue::List(_) => "list",
|
||||
CoreValue::Atom(_) => "atom",
|
||||
_ => "?",
|
||||
}
|
||||
}
|
||||
|
||||
fn table_cell(col: &CoreValue, row_index: usize) -> String {
|
||||
match col {
|
||||
CoreValue::Vector(v) => match v.data() {
|
||||
VectorData::Char(chars) => {
|
||||
// Show a single char per cell
|
||||
if row_index < chars.len() {
|
||||
(chars[row_index] as char).to_string()
|
||||
} else {
|
||||
"?".to_string()
|
||||
}
|
||||
}
|
||||
data => format_vector_item(data, row_index),
|
||||
},
|
||||
CoreValue::Atom(atom) => format_atom_cell(atom),
|
||||
CoreValue::List(list) => {
|
||||
if row_index < list.len() {
|
||||
inline_value_summary(&list.values()[row_index])
|
||||
} else {
|
||||
"?".to_string()
|
||||
}
|
||||
}
|
||||
_ => inline_value_summary(col),
|
||||
}
|
||||
}
|
||||
|
||||
fn column_name(raw: &[u8]) -> String {
|
||||
String::from_utf8_lossy(raw).into_owned()
|
||||
}
|
||||
|
||||
pub fn format_table(table: &CoreTable) -> String {
|
||||
let num_rows = table.len();
|
||||
let num_cols = table.num_columns();
|
||||
let opts = active_options();
|
||||
let visible_cols = num_cols.min(opts.max_columns);
|
||||
|
||||
// Build headers: "name\ntype" for each visible column
|
||||
let mut headers: Vec<String> = table
|
||||
.column_names()
|
||||
.iter()
|
||||
.zip(table.columns().iter())
|
||||
.take(visible_cols)
|
||||
.map(|(name, col)| {
|
||||
let col_name = truncate(column_name(name));
|
||||
let type_label = column_primitive_label(col);
|
||||
format!("{col_name}\n{type_label}")
|
||||
})
|
||||
.collect();
|
||||
|
||||
if num_cols > visible_cols {
|
||||
headers.push("...\n...".to_string());
|
||||
} else if headers.is_empty() {
|
||||
headers.push("value".to_string());
|
||||
}
|
||||
|
||||
// Build rows
|
||||
let row_slots = preview_slots(num_rows, opts.max_rows, opts.row_display);
|
||||
let columns = table.columns();
|
||||
|
||||
let body_rows: Vec<Vec<String>> = row_slots
|
||||
.into_iter()
|
||||
.map(|slot| {
|
||||
let mut row: Vec<String> = match slot {
|
||||
PreviewSlot::Index(row_i) => (0..visible_cols)
|
||||
.map(|col_i| table_cell(&columns[col_i], row_i))
|
||||
.collect(),
|
||||
PreviewSlot::Ellipsis => vec!["...".to_string(); visible_cols.max(1)],
|
||||
};
|
||||
if num_cols > visible_cols {
|
||||
row.push("...".to_string());
|
||||
}
|
||||
row
|
||||
})
|
||||
.collect();
|
||||
|
||||
render_preview(
|
||||
vec![format!(
|
||||
"Table [table, attr={}]",
|
||||
attribute_label(table.attribute())
|
||||
)],
|
||||
headers,
|
||||
body_rows,
|
||||
vec![format!("shape: ({num_rows}, {num_cols})")],
|
||||
)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// UnaryPrimitive
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn format_unary_primitive(opcode: i8) -> String {
|
||||
render_preview(
|
||||
vec!["UnaryPrimitive [unary_primitive]".to_string()],
|
||||
vec!["opcode".to_string()],
|
||||
vec![vec![format!("0x{opcode:02x}")]],
|
||||
vec!["shape: (1,)".to_string()],
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue