Rust
The cadboss crates
One Rust core in five published crates, MIT OR Apache-2.0. The CLI and the Python package call the same reader, so all three return the same document.
crates.io
Five crates, one reader.
cadboss-corecrates.io
Source (mmap or owned bytes), budgets, report, errors, geometry.
cadboss-modelcrates.io
The format-independent document: metadata, layers, blocks, layouts, text groups, entities.
cadboss-dxfcrates.io
The DXF reader: tape lexer, binary and ASCII, header, tables, blocks, layouts, in-place entity decoder, text groups.
cadboss-outputcrates.io
Markdown and JSON writers.
cadboss-clicrates.io
The cadboss binary and its Claude Code skill.
Layering
Each crate depends only on the ones above it.
| Crate | Owns | Depends on |
|---|---|---|
| cadboss-core | Source (mmap or owned bytes), budgets, report, errors, geometry | none |
| cadboss-model | The format-independent document: metadata, layers, blocks, layouts, text groups, entities | core |
| cadboss-dxf | The DXF reader: tape lexer, binary and ASCII, header, tables, blocks, layouts, in-place entity decoder, text groups | core, model |
| cadboss-output | Markdown and JSON writers | core, model |
| cadboss-cli | The cadboss binary and its Claude Code skill | core, model, dxf, output |
The Python package (crates/cadboss-py with python/cadboss, built with pyo3 and maturin) wraps the same reader and is published to PyPI.
Reading a drawing
Read a drawing with its report.
The README example: read the unified document with its report, then walk the decoded entities of the Model layout.
use std::path::Path;
use cadboss_dxf::{open_reporting, DxfDocument};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let (doc, report) = open_reporting(Path::new("plan.dxf"))?;
println!("{} {:?}", doc.metadata.version, doc.metadata.units);
for item in &doc.text.title_block {
println!("{} on layer {}", item.text, item.layer);
}
for skipped in &report.skipped {
println!("{:?} {:?} x{}", skipped.kind, skipped.reason, skipped.count);
}
let dxf = DxfDocument::open(Path::new("plan.dxf"))?;
for entity in dxf.entities("Model") {
println!("{entity:?}");
}
Ok(())
}cadboss_dxf::open maps the file, read loads it into one buffer, load takes bytes; each has a _reporting twin that returns the Report beside the Document, and a _with_options variant that takes &Options. DxfDocument is the layer underneath: the tape, the header, the tables, and an in-place entity decoder per layout or block.
Budget, Report, Skipped
Budgets in, a report out.
A Budget caps bytes, tokens, entities, layouts, nesting depth and string length; Budget::default() holds the defaults and Budget::set(key, value) sets one by the same names the CLI and Python accept. The reader stops at a cap and records it in the Report.
The report keeps one entry per kind and reason, with a count. It keeps up to 64 distinct entries and counts the rest in unlisted; summary() renders lines such as 4 entities skipped (entity_limit), the same text the CLI prints.
// cadboss_core
pub struct Budget {
pub max_bytes: u64,
pub max_entities: u64,
pub max_layouts: u32,
pub max_nesting: u32,
pub max_string_bytes: u32,
pub max_tokens: u64,
}
pub struct Report {
pub skipped: Vec<Skipped>,
pub unlisted: u64,
}
pub struct Skipped {
pub kind: SkipKind,
pub reason: SkipReason,
pub count: u64,
}
pub enum SkipKind { Token, Section, Table, Entity, Text, Object }
pub enum SkipReason {
Malformed, Truncated, Unknown, NestingLimit, EntityLimit,
StringLimit, UnsupportedCodepage, Unsupported, TokenLimit,
}
// cadboss_dxf
pub struct Options {
pub budget: Budget,
pub threads: usize,
}FAQ
Questions developers ask.
- Which crate do I depend on?
- cadboss-dxf to read a drawing; it returns the format-independent Document from cadboss-model. Add cadboss-output for the Markdown and JSON writers that the CLI and the Python package use.
- What is the difference between open, read and load?
- cadboss_dxf::open maps the file, read loads it into one buffer, and load takes bytes. Each has a _reporting twin that returns the Report beside the Document, and a _with_options variant that takes Options with a Budget.
- When do I need DxfDocument?
- When you want the layer underneath the unified Document: the tape, the header, the tables, and an in-place entity decoder per layout or block. DxfDocument::open(path) and dxf.entities("Model") walk the entities of one layout.
- Can the reader panic on a broken file?
- Panics are denied by the workspace lints. Malformed records, truncated sections and exceeded budgets become Skipped notes in the Report, and a cargo-fuzz target seeded from the fixtures runs on each push.