Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

qubed — Core Library

The qubed crate provides the core Qube data structure, Coordinates types, compression, selection, serialization, and datacube conversion.

Cargo.toml:

[dependencies]
qubed = { path = "qubed" }

Qube

The central type. A Qube is a slot-map-backed tree where each node has a dimension name, a set of coordinate values, and children grouped by dimension.

Construction

MethodSignatureDescription
newfn new() -> QubeCreate an empty Qube with just a root node
from_asciifn from_ascii(input: &str) -> Result<Qube, String>Parse an ASCII tree representation
from_jsonfn from_json(value: Value) -> Result<Qube, String>Parse a nested JSON object
from_arena_jsonfn from_arena_json(value: Value) -> Result<Qube, String>Parse a BFS flat-array JSON layout
from_datacubefn from_datacube(dc: &Datacube, order: Option<&[String]>) -> QubeBuild from a flat datacube with optional dimension ordering

Example — from ASCII:

#![allow(unused)]
fn main() {
use qubed::Qube;

let q = Qube::from_ascii(r#"root
├── class=od
│   ├── expver=0001, param=1/2
│   └── expver=0002, param=1/2
└── class=rd
    ├── expver=0001, param=1/2/3
    └── expver=0002, param=1/2"#).unwrap();
}

Example — from nested JSON:

#![allow(unused)]
fn main() {
use qubed::Qube;
use serde_json::json;

let q = Qube::from_json(json!({
    "class=od": {
        "expver=0001/0002": { "param=1/2": {} }
    },
    "class=rd": {
        "expver=0001": { "param=1/2/3": {} },
        "expver=0002": { "param=1/2": {} }
    }
})).unwrap();
}

Tree Modification

MethodSignatureDescription
create_childfn create_child(&mut self, key: &str, parent: NodeIdx, coords: Option<Coordinates>) -> Result<NodeIdx, String>Create a child node. Returns existing node if an identical child already exists.
get_or_create_childfn get_or_create_child(&mut self, key: &str, parent_id: NodeIdx, coordinates: Option<Coordinates>) -> Result<NodeIdx, String>Return the existing child with the given dimension+coordinates, or create a new one.
check_if_new_childfn check_if_new_child(&mut self, key: &str, parent_id: NodeIdx, coordinates: Option<Coordinates>) -> Result<bool, String>Return true if no child with the given dimension+coordinates exists yet.
remove_nodefn remove_node(&mut self, id: NodeIdx) -> Result<(), String>Remove a node and all its descendants
appendfn append(&mut self, other: &mut Qube)Union: merge other into self, compress, then clear other
append_manyfn append_many(&mut self, others: &mut Vec<Qube>)Merge many Qubes with periodic compression (every 500)
append_datacubefn append_datacube(&mut self, dc: Datacube, order: Option<&[String]>, accept_existing_order: bool)Append a single Datacube
dropfn drop<I>(&mut self, to_drop: I) -> Result<(), String>Remove one or more dimensions, re-parenting their children, then compress
squeezefn squeeze(&mut self) -> Result<(), String>Drop every dimension whose union of values has length 1

Example — building programmatically:

#![allow(unused)]
fn main() {
use qubed::{Qube, Coordinates};

let mut q = Qube::new();
let root = q.root();

let class = q.create_child("class", root,
    Some(Coordinates::from_string("od"))).unwrap();
let expver = q.create_child("expver", class,
    Some(Coordinates::from_string("0001/0002"))).unwrap();
q.create_child("param", expver,
    Some(Coordinates::from_string("1/2"))).unwrap();
}

Example — union:

#![allow(unused)]
fn main() {
let mut a = Qube::from_ascii("root\n└── class=od, param=1").unwrap();
let mut b = Qube::from_ascii("root\n└── class=rd, param=2").unwrap();
a.append(&mut b);
// a now contains both branches, compressed; b is empty
}

Example — drop:

#![allow(unused)]
fn main() {
let mut q = Qube::from_ascii(r#"root
└── class=1
    ├── expver=0001
    │   └── param=1/2
    └── expver=0002
        └── param=1/2"#).unwrap();

q.drop(vec!["expver"]).unwrap();
// expver is removed; param nodes are re-parented under class
}

Example — squeeze:

#![allow(unused)]
fn main() {
let mut q = Qube::from_ascii(r#"root
└── class=1
    ├── expver=0001
    │   └── param=1/2
    └── expver=0002
        └── param=1/2"#).unwrap();

q.squeeze().unwrap();
// class=1 is the only value for that dimension, so it is dropped
}

Compression

#![allow(unused)]
fn main() {
fn compress(&mut self)
}

Compress the tree in-place. Three phases:

  1. Recursive merge — bottom-up, siblings with the same structural hash have their coordinates merged.
  2. Prune — nodes with Coordinates::Empty are removed.
  3. Dedup — structurally identical siblings are collapsed.

Called automatically by append and append_many.

Selection

#![allow(unused)]
fn main() {
fn select<C>(&self, selection: &[(&str, C)], mode: SelectMode) -> Result<Qube, String>
where C: Into<Coordinates> + Clone
}

Returns a new Qube containing only identifiers matching the constraints. C can be &[i32], Coordinates, or other Into<Coordinates> types.

#![allow(unused)]
fn main() {
fn prune(&mut self, node_id: NodeIdx, has_none_of: HashSet<&str>)
}

Remove branches that don’t contain all of the specified dimensions.

SelectMode:

  • Default — keep branches with at least one matching value per constrained dimension.
  • Prune — additionally remove branches missing any selected dimension entirely.

Serialization

MethodReturnsFormat
to_ascii()StringHuman-readable tree with ├──/└── connectors
to_json()ValueNested JSON: { "key=values": { children } }
to_arena_json()ValueBFS flat array: [{ dim, coords, parent, children }]

Arena JSON node record:

{ "dim": "class", "coords": "od/rd", "parent": null, "children": [1, 2] }

Iteration & Inspection

MethodSignatureDescription
to_datacubesfn to_datacubes(&self) -> Vec<Datacube>Decompose into leaf-path datacubes
datacube_countfn datacube_count(&self) -> usizeCount leaf identifiers without expansion
is_emptyfn is_empty(&self) -> boolTrue if root has no children and no coordinates
all_unique_dim_coordsfn all_unique_dim_coords(&mut self) -> BTreeMap<String, Coordinates>Union of all coordinates per dimension
rootfn root(&self) -> NodeIdxRoot node index
nodefn node(&self, id: NodeIdx) -> Option<NodeRef>Read-only reference to a node
dimensionfn dimension(&self, s: &str) -> Option<Dimension>Look up dimension by name
dimension_strfn dimension_str(&self, d: &Dimension) -> Option<&str>Get dimension name string

NodeRef

Read-only reference to a node in the Qube tree.

MethodReturnsDescription
id()NodeIdxSlot-map key
dimension()Option<&str>Dimension name (e.g. "class")
coordinates()&CoordinatesCoordinate values
child_dimensions()impl Iterator<Item = &Dimension>Distinct child dimension keys
children(key)Option<impl Iterator<Item = NodeIdx>>Children under a specific dimension
all_children()impl Iterator<Item = NodeIdx>All children across all dimensions
children_count()usizeTotal direct children
coordinates_count()usizeNumber of coordinate values
parent()Option<NodeIdx>Parent index
parent_node()Option<NodeRef>Parent as NodeRef
ancestors()impl Iterator<Item = NodeIdx>Walk up to root
span()HashSet<Dimension>All unique dimensions in subtree
structural_hash()Option<u64>Cached structural hash

Coordinates

A typed, ordered set of coordinate values.

Variants

VariantStorageExample
EmptyDefault for root
IntegersSorted i321/2/3
FloatsSorted f640.1/0.5
StringsSorted Stringod/rd
MixedAll three1/od/0.5

Construction

MethodDescription
Coordinates::new()Empty coordinates
Coordinates::from_string(s)Parse |-separated string (also handles / in ASCII context)
From<i32>, From<f64>, From<String>Single-value construction
FromIterator<i32>, FromIterator<f64>, FromIterator<String>Build from iterators

Leading zero preservation: tokens with length > 1 that start with '0' followed by a digit are stored as String to preserve formatting (e.g. "0001" stays "0001", not 1).

Modification

MethodDescription
append(value)Add a single value; auto-promotes to Mixed if types differ
extend(&other)Merge values from another Coordinates
extend_from_iter(iter)Extend from an iterator

Query

MethodDescription
to_string()/-separated string
len()Value count
is_empty()True if no values
contains(value)Membership check (integers only currently)

Set Operations

MethodDescription
intersect(&other)Returns IntersectionResult { intersection, only_a, only_b }
merge_coords(&other)Union (intersection + only_a + only_b combined)

Datacube

A flat HashMap<String, Coordinates> representing one dense datacube.

MethodDescription
new()Create empty
add_coordinate(dim, coords)Add a dimension
coordinates()Access the map
is_empty() / len()Check dimensions

Key Types Summary

TypeDescription
NodeIdxSlotMap key for node identity
DimensionInterned string key (MiniSpur from lasso)
IntersectionResult<T>{ intersection, only_a, only_b }
SelectModeDefault or Prune
CoordinateTypesInteger(i32), Float(f64), String(String)