acadrust 0.6.6

A pure Rust library for reading and writing CAD files in DXF format (ASCII and Binary) and DWG format (Binary).
Documentation
use std::io::Cursor;

use acadrust::entities::Mesh;
use acadrust::{CadDocument, DwgReadOptions, DwgReader, DwgWriter, EntityType, Vector3};

fn dense_mesh() -> Mesh {
    let mut mesh = Mesh::new();
    for i in 0..6 {
        mesh.add_vertex(Vector3::new(i as f64, (i % 2) as f64, 0.0));
    }
    mesh.add_triangle(0, 1, 2);
    mesh.add_triangle(1, 2, 3);
    mesh.add_triangle(2, 3, 4);
    mesh.add_triangle(3, 4, 5);
    mesh.add_triangle(0, 2, 5);
    mesh
}

fn write_mesh() -> Vec<u8> {
    let mut doc = CadDocument::new();
    doc.add_entity(EntityType::Mesh(dense_mesh())).unwrap();
    DwgWriter::write_to_vec(&doc).unwrap()
}

fn faces(doc: &CadDocument) -> Vec<Vec<usize>> {
    doc.entities()
        .find_map(|entity| match entity {
            EntityType::Mesh(mesh) => Some(
                mesh.faces
                    .iter()
                    .map(|face| face.vertices.clone())
                    .collect(),
            ),
            _ => None,
        })
        .expect("MESH entity")
}

#[test]
fn default_read_keeps_every_face_of_a_small_mesh() {
    let mut reader = DwgReader::from_stream(Cursor::new(write_mesh()));
    let doc = reader.read().unwrap();
    assert_eq!(faces(&doc).len(), 5);
    assert!(doc
        .notifications
        .iter()
        .all(|note| !note.message.contains("face budget")));
}

#[test]
fn explicit_caps_truncate_whole_faces_and_report_the_budget() {
    let bytes = write_mesh();
    let mut reader = DwgReader::from_stream_with_options(
        Cursor::new(bytes.clone()),
        DwgReadOptions::default().with_mesh_limits(2, usize::MAX),
    );
    let outcome = reader.read_with_stats().unwrap();
    assert_eq!(faces(&outcome.document), vec![vec![0, 1, 2], vec![1, 2, 3]]);
    assert!(outcome
        .stats
        .diagnostics
        .iter()
        .any(|diagnostic| diagnostic.code == "mesh-face-budget"));

    let mut reader = DwgReader::from_stream_with_options(
        Cursor::new(bytes),
        DwgReadOptions::default().with_mesh_limits(usize::MAX, 7),
    );
    let doc = reader.read().unwrap();
    let stored = faces(&doc);
    assert_eq!(stored, vec![vec![0, 1, 2], vec![1, 2, 3]]);
    assert!(doc
        .notifications
        .iter()
        .any(|note| note.message.contains("face budget")));
}

#[test]
fn unlimited_option_stores_every_face() {
    let mut reader = DwgReader::from_stream_with_options(
        Cursor::new(write_mesh()),
        DwgReadOptions::default().with_unlimited_mesh(),
    );
    let doc = reader.read().unwrap();
    assert_eq!(faces(&doc).len(), 5);
    assert!(doc
        .notifications
        .iter()
        .all(|note| !note.message.contains("face budget")));
}