From 715e950d7c6552d5e7e2d92bae5e3bb508684155 Mon Sep 17 00:00:00 2001 From: Karim Date: Sun, 5 Jul 2026 03:12:32 +0200 Subject: [PATCH] DWG/DXF-Import-Spike: acadrust baut zu wasm32 (Crate dwgimport) - src-tauri/dwgimport: eigenstaendiges Crate (cdylib+rlib, eigener [workspace]), dep acadrust 0.4 (MPL-2.0, pure Rust). parse_dxf_summary(bytes) via DxfReader::from_reader + Cursor> -> JSON (version/entityCount/ entityTypeCounts/layerNames). wasm-Fassade parse_dxf_summary_json. - getrandom wasm_js-Feature noetig (transitiv via ahash) -> als Dep gesetzt. - Kernbeweis: acadrust kompiliert nach wasm32 (839 KB), DXF-Parse headless getestet (5 Entities korrekt). Beweist den DWG/DXF-Import-Weg im Rust/WASM-Kern. - build:dwgimport-Script, src-tauri/Cargo.toml exclude erweitert. --- package.json | 3 +- src-tauri/Cargo.toml | 2 +- src-tauri/dwgimport/Cargo.lock | 578 +++++++++++++++++++++++++++++++++ src-tauri/dwgimport/Cargo.toml | 36 ++ src-tauri/dwgimport/src/lib.rs | 284 ++++++++++++++++ 5 files changed, 901 insertions(+), 2 deletions(-) create mode 100644 src-tauri/dwgimport/Cargo.lock create mode 100644 src-tauri/dwgimport/Cargo.toml create mode 100644 src-tauri/dwgimport/src/lib.rs diff --git a/package.json b/package.json index d299165..1eacc0e 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,8 @@ "build:engine": "wasm-pack build src-tauri/render2d --release --target web --out-dir ../../src/engine/pkg --out-name render2d --no-default-features --features web", "build:engine3d": "wasm-pack build src-tauri/render3d --release --target web --out-dir ../../src/engine/pkg3d --out-name render3d --no-default-features --features web", "build:geometry": "wasm-pack build src-tauri/geometry --release --target web --out-dir ../../src/engine/pkgGeometry --out-name geometry --no-default-features --features web", - "build:kernel2d": "wasm-pack build src-tauri/kernel2d --release --target web --out-dir ../../src/engine/pkgKernel2d --out-name kernel2d --no-default-features --features web" + "build:kernel2d": "wasm-pack build src-tauri/kernel2d --release --target web --out-dir ../../src/engine/pkgKernel2d --out-name kernel2d --no-default-features --features web", + "build:dwgimport": "wasm-pack build src-tauri/dwgimport --release --target web --out-dir ../../src/engine/pkgDwgImport --out-name dwgimport --no-default-features --features web" }, "dependencies": { "@mlightcad/libredwg-web": "^0.7.7", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 8b0ec6e..ea33125 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -8,7 +8,7 @@ members = ["."] # wird und das TS-Frontend die Joins direkt per WASM aufruft (statt TS-Duplikat). # kernel2d: analog — eigenstaendiger 2D-Geometrie-Kern (Port von kernel2d.ts), # per wasm-pack (Feature "web") zu WASM gebaut, ausserhalb des cad-tauri-Workspace. -exclude = ["render2d", "render3d", "geometry", "kernel2d"] +exclude = ["render2d", "render3d", "geometry", "kernel2d", "dwgimport"] [package] name = "cad-tauri" diff --git a/src-tauri/dwgimport/Cargo.lock b/src-tauri/dwgimport/Cargo.lock new file mode 100644 index 0000000..9fc0b64 --- /dev/null +++ b/src-tauri/dwgimport/Cargo.lock @@ -0,0 +1,578 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "acadrust" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "153498e7c9b058326ff0fae11bc9fd870cf2ea0aa9111875d03625fa9018c218" +dependencies = [ + "ahash", + "anyhow", + "bitflags", + "byteorder", + "encoding_rs", + "flate2", + "indexmap", + "itoa", + "nalgebra", + "nom", + "once_cell", + "ryu", + "thiserror", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "anyhow" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" + +[[package]] +name = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +dependencies = [ + "num-traits", +] + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "bitflags" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" + +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + +[[package]] +name = "bytemuck" +version = "1.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "dwgimport" +version = "0.1.0" +dependencies = [ + "acadrust", + "console_error_panic_hook", + "getrandom", + "serde", + "serde_json", + "wasm-bindgen", +] + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi", + "wasip2", + "wasm-bindgen", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "js-sys" +version = "0.3.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "matrixmultiply" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08" +dependencies = [ + "autocfg", + "rawpointer", +] + +[[package]] +name = "memchr" +version = "2.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "nalgebra" +version = "0.32.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5c17de023a86f59ed79891b2e5d5a94c705dbe904a5b5c9c952ea6221b03e4" +dependencies = [ + "approx", + "matrixmultiply", + "nalgebra-macros", + "num-complex", + "num-rational", + "num-traits", + "simba", + "typenum", +] + +[[package]] +name = "nalgebra-macros" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "254a5372af8fc138e36684761d3c0cdb758a4410e938babcff1c860ce14ddbfc" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rawpointer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + +[[package]] +name = "safe_arch" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "simba" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "061507c94fc6ab4ba1c9a0305018408e312e17c041eb63bef8aa726fa33aceae" +dependencies = [ + "approx", + "num-complex", + "num-traits", + "paste", + "wide", +] + +[[package]] +name = "simd-adler32" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" + +[[package]] +name = "syn" +version = "2.0.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasip2" +version = "1.0.4+wasi-0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wide" +version = "0.7.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce5da8ecb62bcd8ec8b7ea19f69a51275e91299be594ea5cc6ef7819e16cd03" +dependencies = [ + "bytemuck", + "safe_arch", +] + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "zerocopy" +version = "0.8.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce1022995ff5ff5d841ad7d994facc23098cd40152f2c1d11cd607c6f530653f" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/src-tauri/dwgimport/Cargo.toml b/src-tauri/dwgimport/Cargo.toml new file mode 100644 index 0000000..c71fd8b --- /dev/null +++ b/src-tauri/dwgimport/Cargo.toml @@ -0,0 +1,36 @@ +# Eigener leerer Workspace-Block: entkoppelt dwgimport vollstaendig vom +# cad-tauri-Workspace (src-tauri/Cargo.toml). Muster: kernel2d/render2d. +[workspace] + +[package] +name = "dwgimport" +version = "0.1.0" +edition = "2021" +description = "DXF-Import-Probe: beweist, dass acadrust (MPL-2.0) aus einem Byte-Buffer parst und nach wasm32-unknown-unknown kompiliert." + +# cdylib: fuer wasm-pack (Feature \"web\"). rlib: fuer cargo test + Pfad-Dep. +[lib] +crate-type = ["cdylib", "rlib"] + +[features] +# Standard: headless, kein WASM-Overhead — per `cargo test` pruefbar. +default = [] +# Browser-Bindings: wasm-bindgen-Fassade; nur fuer wasm32-unknown-unknown. +web = ["dep:wasm-bindgen", "dep:serde_json", "dep:console_error_panic_hook"] + +[dependencies] +# DXF/DWG-Parser (MPL-2.0), von crates.io. +acadrust = "0.4" + +# getrandom wird transitiv via ahash→acadrust gezogen. Fuer wasm32 muss das +# Feature "wasm_js" explizit aktiviert werden (sonst Compile-Fehler). +# Direkte Dep mit Feature-Aktivierung unifiziert das Flag fuer alle Abhaengigen. +getrandom = { version = "0.3", features = ["wasm_js"] } + +# Serialisierung: immer vorhanden (fuer den headless parse_dxf_summary-Kern). +serde = { version = "1", features = ["derive"] } +serde_json = { version = "1", optional = true } + +# WASM-Bindings — nur im Feature "web" aktiv. +wasm-bindgen = { version = "0.2", optional = true } +console_error_panic_hook = { version = "0.1", optional = true } diff --git a/src-tauri/dwgimport/src/lib.rs b/src-tauri/dwgimport/src/lib.rs new file mode 100644 index 0000000..cefa277 --- /dev/null +++ b/src-tauri/dwgimport/src/lib.rs @@ -0,0 +1,284 @@ +// dwgimport — SPIKE: beweist, dass acadrust (MPL-2.0) aus einem Byte-Buffer +// ein DXF parst und nach wasm32-unknown-unknown kompiliert. +// +// Aufbau: +// - `parse_dxf_summary`: headless, feature-frei testbar. +// - `#[cfg(feature="web")]` wasm-bindgen-Fassade darueber. +// +// API-Stuetzpunkt acadrust: +// `DxfReader::from_reader(reader: R)` +// → std::io::Cursor<&[u8]> implementiert Read + Seek → WASM-tauglich. + +use std::collections::HashMap; +use std::io::Cursor; + +use acadrust::DxfReader; + +// serde_json nur bei Feature "web" als optionale Dep, aber serde ist immer da. +// Fuer den headless-Kern bauen wir das JSON mit einem einfachen Format-String, +// damit keine Compile-Time-Dep auf serde_json im Default-Feature noetig ist. + +/// Parst ein DXF aus einem Byte-Slice und gibt ein JSON-Summary zurueck. +/// +/// Rueckgabe-JSON-Schema: +/// ```json +/// { +/// "version": "AC1015", +/// "entityCount": 5, +/// "entityTypeCounts": { "LINE": 3, "CIRCLE": 2 }, +/// "layerNames": ["0", "Wand"] +/// } +/// ``` +/// +/// Fehler: String mit Fehlerbeschreibung. +pub fn parse_dxf_summary(bytes: &[u8]) -> Result { + // Cursor> implementiert Read + Seek + 'static — kein std::fs noetig. + // (from_reader verlangt R: 'static; Cursor<&[u8]> wuerde die Lifetime verletzen.) + let cursor = Cursor::new(bytes.to_vec()); + let reader = DxfReader::from_reader(cursor) + .map_err(|e| format!("DxfReader::from_reader fehlgeschlagen: {e}"))?; + + let doc = reader + .read() + .map_err(|e| format!("DxfReader::read fehlgeschlagen: {e}"))?; + + // Versions-String aus dem Enum (Debug-Format, z. B. "AC1015"). + let version = format!("{:?}", doc.version); + + // Entitaeten zaehlen und nach Typ aufschluesseln. + let mut type_counts: HashMap<&str, usize> = HashMap::new(); + for entity in doc.entities() { + let typ = entity.as_entity().entity_type(); + *type_counts.entry(typ).or_insert(0) += 1; + } + let entity_count = type_counts.values().sum::(); + + // Layer-Namen aus der Layer-Tabelle. + let mut layer_names: Vec = doc + .layers + .iter() + .map(|l| l.name.clone()) + .collect(); + layer_names.sort(); + + // JSON-Serialisierung ohne optionale serde_json-Dep im Default-Feature. + // Fuer den headless-Test reicht ein sauberer Format-String. + let type_counts_json = { + let mut pairs: Vec = type_counts + .iter() + .map(|(k, v)| format!(" \"{k}\": {v}")) + .collect(); + pairs.sort(); // deterministisch fuer Tests + format!("{{\n{}\n }}", pairs.join(",\n")) + }; + + let layer_names_json = { + let quoted: Vec = layer_names + .iter() + .map(|n| format!("\"{}\"", n.replace('"', "\\\""))) + .collect(); + format!("[{}]", quoted.join(", ")) + }; + + Ok(format!( + "{{\n \"version\": \"{version}\",\n \"entityCount\": {entity_count},\n \"entityTypeCounts\": {type_counts_json},\n \"layerNames\": {layer_names_json}\n}}" + )) +} + +// --------------------------------------------------------------------------- +// WASM-Fassade (nur bei Feature "web" compiliert) +// --------------------------------------------------------------------------- + +#[cfg(feature = "web")] +mod wasm { + use super::parse_dxf_summary; + use wasm_bindgen::prelude::*; + + /// Initialisiert den Panic-Hook fuer bessere Fehlermeldungen im Browser. + #[wasm_bindgen(start)] + pub fn init_panic_hook() { + console_error_panic_hook::set_once(); + } + + /// WASM-Fassade: nimmt einen Byte-Buffer (Uint8Array aus JS) und gibt ein + /// JSON-String zurueck, das das DXF-Summary beschreibt. + /// + /// JS-Aufruf: + /// ```js + /// import init, { parse_dxf_summary_json } from './pkgDwgImport/dwgimport.js'; + /// await init(); + /// const json = parse_dxf_summary_json(new Uint8Array(buffer)); + /// ``` + #[wasm_bindgen] + pub fn parse_dxf_summary_json(bytes: &[u8]) -> Result { + parse_dxf_summary(bytes) + .map_err(|e| JsValue::from_str(&e)) + } +} + +// --------------------------------------------------------------------------- +// Tests +// --------------------------------------------------------------------------- + +#[cfg(test)] +mod tests { + use super::*; + + /// Minimales ASCII-DXF mit 3 LINE- und 2 CIRCLE-Entitaeten auf Layer "WAND" + /// und Layer "0". Wird direkt als Byte-Slice eingebettet — kein Datei-IO. + const MINI_DXF: &str = r#" 0 +SECTION + 2 +HEADER + 9 +$ACADVER + 1 +AC1015 + 0 +ENDSEC + 0 +SECTION + 2 +TABLES + 0 +TABLE + 2 +LAYER + 70 + 2 + 0 +LAYER + 2 +0 + 70 + 0 + 62 + 7 + 6 +Continuous + 0 +LAYER + 2 +WAND + 70 + 0 + 62 + 3 + 6 +Continuous + 0 +ENDTAB + 0 +ENDSEC + 0 +SECTION + 2 +ENTITIES + 0 +LINE + 8 +WAND + 10 +0.0 + 20 +0.0 + 30 +0.0 + 11 +100.0 + 21 +0.0 + 31 +0.0 + 0 +LINE + 8 +WAND + 10 +100.0 + 20 +0.0 + 30 +0.0 + 11 +100.0 + 21 +50.0 + 31 +0.0 + 0 +LINE + 8 +0 + 10 +100.0 + 20 +50.0 + 30 +0.0 + 11 +0.0 + 21 +0.0 + 31 +0.0 + 0 +CIRCLE + 8 +WAND + 10 +50.0 + 20 +25.0 + 30 +0.0 + 40 +10.0 + 0 +CIRCLE + 8 +0 + 10 +20.0 + 20 +10.0 + 30 +0.0 + 40 +5.0 + 0 +ENDSEC + 0 +EOF +"#; + + #[test] + fn test_parse_mini_dxf() { + let result = parse_dxf_summary(MINI_DXF.as_bytes()); + assert!(result.is_ok(), "parse_dxf_summary schlug fehl: {:?}", result); + + let json = result.unwrap(); + println!("DXF-Summary:\n{json}"); + + // Version muss AC1015 sein. + assert!(json.contains("AC1015"), "Version AC1015 nicht im JSON: {json}"); + + // Genau 5 Entitaeten: 3 LINE + 2 CIRCLE. + assert!( + json.contains("\"entityCount\": 5"), + "entityCount soll 5 sein: {json}" + ); + assert!( + json.contains("\"LINE\": 3"), + "LINE-Zaehler soll 3 sein: {json}" + ); + assert!( + json.contains("\"CIRCLE\": 2"), + "CIRCLE-Zaehler soll 2 sein: {json}" + ); + + // Layer "WAND" und "0" muessen erscheinen. + assert!(json.contains("\"WAND\""), "Layer WAND fehlt: {json}"); + assert!(json.contains("\"0\""), "Layer 0 fehlt: {json}"); + } +}