From 68b46b4e53dda6d4443916974a6b1273192708fd Mon Sep 17 00:00:00 2001 From: Myriad-Dreamin <35292584+Myriad-Dreamin@users.noreply.github.com> Date: Sun, 2 Feb 2025 16:38:22 +0800 Subject: [PATCH] feat: use world implementation from tinymist (#636) * fix: warnings in clippy 1.84 * feat: use world implementation from tinymist * build: update dep * fix: fmt * dev: delete reflexo-vfs * fix: default features * fix: compile error --- Cargo.lock | 286 +++++--- Cargo.toml | 24 +- benches/lowering/src/lowering.rs | 4 +- cli/src/compile.rs | 33 +- cli/src/lib.rs | 100 ++- cli/src/main.rs | 1 - cli/src/query_repl.rs | 2 +- crates/conversion/typst2vec/Cargo.toml | 3 + crates/conversion/typst2vec/src/font/glyph.rs | 17 +- .../conversion/typst2vec/src/font/ligature.rs | 4 +- crates/conversion/typst2vec/src/incr.rs | 8 +- .../typst2vec/src/pass/glyph2vec.rs | 2 +- .../conversion/typst2vec/src/pass/span2vec.rs | 4 +- crates/conversion/typst2vec/src/utils.rs | 4 +- crates/conversion/vec2bbox/Cargo.toml | 3 + crates/conversion/vec2bbox/src/lib.rs | 2 +- crates/conversion/vec2canvas/Cargo.toml | 3 + crates/conversion/vec2canvas/src/bounds.rs | 2 +- crates/conversion/vec2canvas/src/incr.rs | 2 +- crates/conversion/vec2canvas/src/lib.rs | 2 + crates/conversion/vec2canvas/src/utils.rs | 2 +- crates/conversion/vec2dom/Cargo.toml | 3 + .../conversion/vec2dom/src/canvas_backend.rs | 2 +- crates/conversion/vec2dom/src/dom.rs | 35 +- crates/conversion/vec2dom/src/incr.rs | 12 +- crates/conversion/vec2dom/src/svg_backend.rs | 6 +- crates/conversion/vec2sema/Cargo.toml | 3 + crates/conversion/vec2svg/Cargo.toml | 3 + .../conversion/vec2svg/src/backend/glyph.rs | 7 +- crates/conversion/vec2svg/src/backend/mod.rs | 16 +- .../vec2svg/src/frontend/context.rs | 7 +- .../conversion/vec2svg/src/frontend/flat.rs | 2 +- .../vec2svg/src/frontend/incremental.rs | 16 +- crates/conversion/vec2svg/src/frontend/mod.rs | 7 +- .../vec2svg/src/transform/minify.rs | 8 +- crates/reflexo-typst-shim/Cargo.toml | 22 - crates/reflexo-typst-shim/src/lib.rs | 13 - crates/reflexo-typst-shim/src/nightly/mod.rs | 1 - .../reflexo-typst-shim/src/nightly/syntax.rs | 16 - crates/reflexo-typst-shim/src/stable/mod.rs | 1 - .../reflexo-typst-shim/src/stable/syntax.rs | 16 - crates/reflexo-typst/Cargo.toml | 18 +- crates/reflexo-typst/src/compile.rs | 60 +- crates/reflexo-typst/src/config/mod.rs | 4 +- crates/reflexo-typst/src/diag/console.rs | 7 +- crates/reflexo-typst/src/driver.rs | 50 +- crates/reflexo-typst/src/error.rs | 60 +- crates/reflexo-typst/src/export.rs | 8 +- .../src/export/dynamic_layout.rs | 6 +- crates/reflexo-typst/src/exporter/ast.rs | 20 +- crates/reflexo-typst/src/lib.rs | 36 +- crates/reflexo-typst/src/task.rs | 2 +- crates/reflexo-typst/src/utils.rs | 2 +- crates/reflexo-typst/src/watch.rs | 198 ++---- crates/reflexo-vfs/Cargo.toml | 29 - crates/reflexo-vfs/README.md | 5 - crates/reflexo-vfs/src/browser.rs | 97 --- crates/reflexo-vfs/src/dummy.rs | 33 - crates/reflexo-vfs/src/lib.rs | 355 ---------- crates/reflexo-vfs/src/notify.rs | 279 -------- crates/reflexo-vfs/src/overlay.rs | 121 ---- crates/reflexo-vfs/src/path_interner.rs | 71 -- crates/reflexo-vfs/src/system.rs | 83 --- crates/reflexo-vfs/src/trace.rs | 81 --- crates/reflexo-vfs/src/utils.rs | 23 - crates/reflexo-world/Cargo.toml | 53 -- crates/reflexo-world/README.md | 5 - crates/reflexo-world/src/browser.rs | 48 -- crates/reflexo-world/src/config.rs | 68 -- crates/reflexo-world/src/entry.rs | 219 ------ crates/reflexo-world/src/font/cache.rs | 26 - crates/reflexo-world/src/font/info.rs | 83 --- crates/reflexo-world/src/font/loader.rs | 43 -- crates/reflexo-world/src/font/mod.rs | 25 - crates/reflexo-world/src/font/partial_book.rs | 52 -- crates/reflexo-world/src/font/profile.rs | 138 ---- crates/reflexo-world/src/font/pure.rs | 56 -- crates/reflexo-world/src/font/resolver.rs | 201 ------ crates/reflexo-world/src/font/slot.rs | 68 -- crates/reflexo-world/src/font/system.rs | 389 ----------- crates/reflexo-world/src/font/web/mod.rs | 496 -------------- crates/reflexo-world/src/lib.rs | 155 ----- crates/reflexo-world/src/package/browser.rs | 113 --- crates/reflexo-world/src/package/dummy.rs | 12 - crates/reflexo-world/src/package/http.rs | 337 --------- crates/reflexo-world/src/package/mod.rs | 37 - crates/reflexo-world/src/parser/mod.rs | 8 - .../reflexo-world/src/parser/modifier_set.rs | 33 - .../src/parser/semantic_tokens.rs | 237 ------- .../reflexo-world/src/parser/typst_tokens.rs | 113 --- crates/reflexo-world/src/source.rs | 256 ------- crates/reflexo-world/src/system.rs | 52 -- crates/reflexo-world/src/world.rs | 646 ------------------ crates/reflexo/Cargo.toml | 17 +- crates/reflexo/src/adt/fmap.rs | 111 --- crates/reflexo/src/adt/mod.rs | 5 - crates/reflexo/src/concepts/cow_mut.rs | 30 - crates/reflexo/src/concepts/hash.rs | 61 -- crates/reflexo/src/concepts/marker.rs | 45 -- crates/reflexo/src/concepts/mod.rs | 22 - crates/reflexo/src/concepts/query.rs | 83 --- crates/reflexo/src/concepts/read.rs | 3 - crates/reflexo/src/concepts/takable.rs | 17 - crates/reflexo/src/debug_loc.rs | 174 ----- crates/reflexo/src/error.rs | 327 --------- crates/reflexo/src/hash.rs | 313 --------- crates/reflexo/src/lib.rs | 16 +- crates/reflexo/src/path.rs | 229 ------- crates/reflexo/src/time.rs | 23 - crates/reflexo/src/vector/incr.rs | 4 +- crates/reflexo/src/vector/ir/layout.rs | 22 +- crates/reflexo/src/vector/ir/module.rs | 1 + crates/reflexo/src/vector/ir/visualize.rs | 2 +- crates/reflexo/src/vector/vm.rs | 4 +- fuzzers/incremental/src/main.rs | 2 +- packages/compiler/Cargo.toml | 3 + packages/compiler/src/builder.rs | 14 +- packages/compiler/src/lib.rs | 18 +- packages/compiler/src/utils.rs | 2 +- packages/parser/Cargo.toml | 3 + packages/parser/src/lib.rs | 4 +- packages/renderer/Cargo.toml | 3 + packages/renderer/src/builder/glyph_pack.rs | 4 +- packages/renderer/src/builder/mod.rs | 12 +- packages/renderer/src/builder/raw_font.rs | 2 +- packages/renderer/src/builder/web_font.rs | 2 +- packages/renderer/src/lib.rs | 18 +- packages/renderer/src/render/canvas.rs | 4 +- packages/renderer/src/render/mod.rs | 2 +- packages/renderer/src/render/pdf.rs | 6 +- packages/renderer/src/render/svg.rs | 4 +- packages/renderer/src/session.rs | 8 +- packages/renderer/src/utils.rs | 2 +- packages/renderer/src/worker.rs | 14 +- packages/typst.node/Cargo.toml | 3 + packages/typst.node/src/compiler/boxed.rs | 16 +- packages/typst.node/src/compiler/mod.rs | 9 +- packages/typst.node/src/lib.rs | 12 +- scripts/publish.py | 3 - server/dev/src/main.rs | 6 +- tests/common/Cargo.toml | 3 + tests/common/src/web_artifact.rs | 2 +- tests/heap-profile/src/lib.rs | 2 +- tests/incremental/src/main.rs | 6 +- tests/integration/src/tests.rs | 8 +- tests/integration/src/wasm.rs | 2 +- tests/std/src/main.rs | 4 +- tools/rkyv-assertions/src/main.rs | 4 +- 148 files changed, 779 insertions(+), 7258 deletions(-) delete mode 100644 crates/reflexo-typst-shim/Cargo.toml delete mode 100644 crates/reflexo-typst-shim/src/lib.rs delete mode 100644 crates/reflexo-typst-shim/src/nightly/mod.rs delete mode 100644 crates/reflexo-typst-shim/src/nightly/syntax.rs delete mode 100644 crates/reflexo-typst-shim/src/stable/mod.rs delete mode 100644 crates/reflexo-typst-shim/src/stable/syntax.rs delete mode 100644 crates/reflexo-vfs/Cargo.toml delete mode 100644 crates/reflexo-vfs/README.md delete mode 100644 crates/reflexo-vfs/src/browser.rs delete mode 100644 crates/reflexo-vfs/src/dummy.rs delete mode 100644 crates/reflexo-vfs/src/lib.rs delete mode 100644 crates/reflexo-vfs/src/notify.rs delete mode 100644 crates/reflexo-vfs/src/overlay.rs delete mode 100644 crates/reflexo-vfs/src/path_interner.rs delete mode 100644 crates/reflexo-vfs/src/system.rs delete mode 100644 crates/reflexo-vfs/src/trace.rs delete mode 100644 crates/reflexo-vfs/src/utils.rs delete mode 100644 crates/reflexo-world/Cargo.toml delete mode 100644 crates/reflexo-world/README.md delete mode 100644 crates/reflexo-world/src/browser.rs delete mode 100644 crates/reflexo-world/src/config.rs delete mode 100644 crates/reflexo-world/src/entry.rs delete mode 100644 crates/reflexo-world/src/font/cache.rs delete mode 100644 crates/reflexo-world/src/font/info.rs delete mode 100644 crates/reflexo-world/src/font/loader.rs delete mode 100644 crates/reflexo-world/src/font/mod.rs delete mode 100644 crates/reflexo-world/src/font/partial_book.rs delete mode 100644 crates/reflexo-world/src/font/profile.rs delete mode 100644 crates/reflexo-world/src/font/pure.rs delete mode 100644 crates/reflexo-world/src/font/resolver.rs delete mode 100644 crates/reflexo-world/src/font/slot.rs delete mode 100644 crates/reflexo-world/src/font/system.rs delete mode 100644 crates/reflexo-world/src/font/web/mod.rs delete mode 100644 crates/reflexo-world/src/lib.rs delete mode 100644 crates/reflexo-world/src/package/browser.rs delete mode 100644 crates/reflexo-world/src/package/dummy.rs delete mode 100644 crates/reflexo-world/src/package/http.rs delete mode 100644 crates/reflexo-world/src/package/mod.rs delete mode 100644 crates/reflexo-world/src/parser/mod.rs delete mode 100644 crates/reflexo-world/src/parser/modifier_set.rs delete mode 100644 crates/reflexo-world/src/parser/semantic_tokens.rs delete mode 100644 crates/reflexo-world/src/parser/typst_tokens.rs delete mode 100644 crates/reflexo-world/src/source.rs delete mode 100644 crates/reflexo-world/src/system.rs delete mode 100644 crates/reflexo-world/src/world.rs delete mode 100644 crates/reflexo/src/adt/fmap.rs delete mode 100644 crates/reflexo/src/adt/mod.rs delete mode 100644 crates/reflexo/src/concepts/cow_mut.rs delete mode 100644 crates/reflexo/src/concepts/hash.rs delete mode 100644 crates/reflexo/src/concepts/marker.rs delete mode 100644 crates/reflexo/src/concepts/mod.rs delete mode 100644 crates/reflexo/src/concepts/query.rs delete mode 100644 crates/reflexo/src/concepts/read.rs delete mode 100644 crates/reflexo/src/concepts/takable.rs delete mode 100644 crates/reflexo/src/debug_loc.rs delete mode 100644 crates/reflexo/src/error.rs delete mode 100644 crates/reflexo/src/hash.rs delete mode 100644 crates/reflexo/src/path.rs delete mode 100644 crates/reflexo/src/time.rs diff --git a/Cargo.lock b/Cargo.lock index 34318d9e0..6afa806a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,7 +23,7 @@ version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ - "getrandom", + "getrandom 0.2.15", "once_cell", "version_check", ] @@ -495,8 +495,10 @@ checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", + "js-sys", "num-traits", "serde", + "wasm-bindgen", "windows-targets 0.52.6", ] @@ -706,6 +708,16 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -1142,6 +1154,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1" +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + [[package]] name = "fd-lock" version = "4.0.2" @@ -1360,10 +1378,22 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "wasm-bindgen", ] +[[package]] +name = "getrandom" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.13.3+wasi-0.2.2", + "windows-targets 0.52.6", +] + [[package]] name = "gif" version = "0.13.1" @@ -1392,7 +1422,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.6.0", + "indexmap 2.7.1", "slab", "tokio", "tokio-util", @@ -1442,7 +1472,7 @@ dependencies = [ "biblatex", "ciborium", "citationberg", - "indexmap 2.6.0", + "indexmap 2.7.1", "numerals", "paste", "serde", @@ -1967,9 +1997,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" dependencies = [ "equivalent", "hashbrown 0.15.1", @@ -2167,6 +2197,19 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +[[package]] +name = "lsp-types" +version = "0.95.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "158c1911354ef73e8fe42da6b10c0484cb65c7f1007f28022e847706c1ab6984" +dependencies = [ + "bitflags 1.3.2", + "serde", + "serde_json", + "serde_repr", + "url", +] + [[package]] name = "memchr" version = "2.7.4" @@ -2232,7 +2275,7 @@ checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.48.0", ] @@ -2244,7 +2287,7 @@ checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ "hermit-abi", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.52.0", ] @@ -2636,7 +2679,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016" dependencies = [ "base64 0.22.1", - "indexmap 2.6.0", + "indexmap 2.7.1", "quick-xml 0.32.0", "serde", "time", @@ -2797,7 +2840,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" dependencies = [ "bytes", - "getrandom", + "getrandom 0.2.15", "rand", "ring", "rustc-hash 2.0.0", @@ -2876,7 +2919,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.15", ] [[package]] @@ -2923,7 +2966,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom", + "getrandom 0.2.15", "libredox", "thiserror 1.0.69", ] @@ -2942,7 +2985,6 @@ dependencies = [ "js-sys", "parking_lot", "path-clean", - "reflexo-typst-shim", "rkyv", "rustc-hash 2.0.0", "serde", @@ -2951,6 +2993,7 @@ dependencies = [ "serde_with", "siphasher 1.0.1", "tiny-skia-path", + "tinymist-std", "wasm-bindgen", "web-time", ] @@ -2967,7 +3010,7 @@ dependencies = [ "fontdb", "futures", "fxhash", - "indexmap 2.6.0", + "indexmap 2.7.1", "js-sys", "log", "nohash-hasher", @@ -2978,12 +3021,11 @@ dependencies = [ "reflexo", "reflexo-typst2vec", "reflexo-vec2svg", - "reflexo-vfs", - "reflexo-world", "rkyv", "serde", "serde_json", "tar", + "tinymist-world", "tokio", "typst", "typst-pdf", @@ -2991,15 +3033,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "reflexo-typst-shim" -version = "0.5.4" -dependencies = [ - "cfg-if", - "typst", - "typst-syntax", -] - [[package]] name = "reflexo-typst2vec" version = "0.5.4" @@ -3104,53 +3137,6 @@ dependencies = [ "typst", ] -[[package]] -name = "reflexo-vfs" -version = "0.5.4" -dependencies = [ - "indexmap 2.6.0", - "js-sys", - "log", - "nohash-hasher", - "parking_lot", - "reflexo", - "rpds", - "typst", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "reflexo-world" -version = "0.5.4" -dependencies = [ - "chrono", - "codespan-reporting", - "comemo", - "dirs", - "ecow", - "flate2", - "fontdb", - "hex", - "js-sys", - "log", - "parking_lot", - "reflexo", - "reflexo-typst-shim", - "reflexo-vfs", - "reqwest", - "serde", - "serde-wasm-bindgen", - "serde_json", - "serde_with", - "sha2", - "strum", - "tar", - "typst", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "regex" version = "1.11.1" @@ -3273,7 +3259,7 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", "cfg-if", - "getrandom", + "getrandom 0.2.15", "libc", "spin", "untrusted", @@ -3638,7 +3624,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.6.0", + "indexmap 2.7.1", "serde", "serde_derive", "serde_json", @@ -3664,7 +3650,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.6.0", + "indexmap 2.7.1", "itoa", "ryu", "serde", @@ -3983,6 +3969,20 @@ dependencies = [ "xattr", ] +[[package]] +name = "tempfile" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c246215d7d24f48ae091a2902398798e05d978b24315d6efbc00ede9a8bb91" +dependencies = [ + "cfg-if", + "fastrand", + "getrandom 0.3.1", + "once_cell", + "rustix", + "windows-sys 0.52.0", +] + [[package]] name = "termcolor" version = "1.4.1" @@ -4113,6 +4113,106 @@ dependencies = [ "strict-num", ] +[[package]] +name = "tinymist-analysis" +version = "0.12.18" +source = "git+https://github.com/Myriad-Dreamin/tinymist.git?rev=7b8739487ed959b295c4df39e5cc2ebd47b4e066#7b8739487ed959b295c4df39e5cc2ebd47b4e066" +dependencies = [ + "ecow", + "lsp-types", + "serde", + "strum", + "toml", + "typst", +] + +[[package]] +name = "tinymist-std" +version = "0.12.18" +source = "git+https://github.com/Myriad-Dreamin/tinymist.git?rev=7b8739487ed959b295c4df39e5cc2ebd47b4e066#7b8739487ed959b295c4df39e5cc2ebd47b4e066" +dependencies = [ + "anyhow", + "base64 0.22.1", + "bitvec", + "comemo", + "core-foundation", + "dashmap", + "ecow", + "fxhash", + "js-sys", + "libc", + "log", + "parking_lot", + "path-clean", + "rkyv", + "rustc-hash 2.0.0", + "same-file", + "serde", + "serde_json", + "serde_repr", + "serde_with", + "siphasher 1.0.1", + "tempfile", + "tinymist-analysis", + "typst", + "typst-shim", + "wasm-bindgen", + "web-time", + "windows-sys 0.59.0", +] + +[[package]] +name = "tinymist-vfs" +version = "0.12.18" +source = "git+https://github.com/Myriad-Dreamin/tinymist.git?rev=7b8739487ed959b295c4df39e5cc2ebd47b4e066#7b8739487ed959b295c4df39e5cc2ebd47b4e066" +dependencies = [ + "comemo", + "indexmap 2.7.1", + "js-sys", + "log", + "nohash-hasher", + "parking_lot", + "rpds", + "tinymist-std", + "typst", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "tinymist-world" +version = "0.12.18" +source = "git+https://github.com/Myriad-Dreamin/tinymist.git?rev=7b8739487ed959b295c4df39e5cc2ebd47b4e066#7b8739487ed959b295c4df39e5cc2ebd47b4e066" +dependencies = [ + "anyhow", + "chrono", + "clap", + "codespan-reporting", + "comemo", + "dirs", + "ecow", + "flate2", + "fontdb", + "hex", + "js-sys", + "log", + "parking_lot", + "reqwest", + "serde", + "serde-wasm-bindgen", + "serde_json", + "serde_with", + "sha2", + "strum", + "tar", + "tinymist-std", + "tinymist-vfs", + "typst", + "typst-assets", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "tinystr" version = "0.7.6" @@ -4219,7 +4319,7 @@ version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap 2.6.0", + "indexmap 2.7.1", "serde", "serde_spanned", "toml_datetime", @@ -4331,7 +4431,7 @@ dependencies = [ "icu_segmenter", "if_chain", "image", - "indexmap 2.6.0", + "indexmap 2.7.1", "kamadak-exif", "kurbo", "lipsum", @@ -4421,7 +4521,7 @@ dependencies = [ "comemo", "ecow", "image", - "indexmap 2.6.0", + "indexmap 2.7.1", "miniz_oxide", "once_cell", "pdf-writer", @@ -4437,6 +4537,16 @@ dependencies = [ "xmp-writer", ] +[[package]] +name = "typst-shim" +version = "0.12.18" +source = "git+https://github.com/Myriad-Dreamin/tinymist.git?rev=7b8739487ed959b295c4df39e5cc2ebd47b4e066#7b8739487ed959b295c4df39e5cc2ebd47b4e066" +dependencies = [ + "cfg-if", + "typst", + "typst-syntax", +] + [[package]] name = "typst-svg" version = "0.12.0" @@ -4920,7 +5030,7 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" dependencies = [ - "getrandom", + "getrandom 0.2.15", ] [[package]] @@ -5023,6 +5133,15 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.13.3+wasi-0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "wasm-bindgen" version = "0.2.95" @@ -5427,6 +5546,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "wit-bindgen-rt" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags 2.6.0", +] + [[package]] name = "write16" version = "1.0.0" diff --git a/Cargo.toml b/Cargo.toml index cf6141291..f5d504478 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,8 +14,6 @@ members = [ "benches/lowering", "crates/reflexo", - "crates/reflexo-vfs", - "crates/reflexo-world", "crates/reflexo-typst", "crates/conversion/typst2vec", "crates/conversion/vec2canvas", @@ -193,12 +191,15 @@ vergen = { version = "9.0.1", features = [ ] } vergen-gitcl = { version = "1.0.1" } +# tinymist's world implementation +typst-shim = { git = "https://github.com/Myriad-Dreamin/tinymist.git", rev = "7b8739487ed959b295c4df39e5cc2ebd47b4e066" } +tinymist-analysis = { git = "https://github.com/Myriad-Dreamin/tinymist.git", rev = "7b8739487ed959b295c4df39e5cc2ebd47b4e066" } +tinymist-std = { git = "https://github.com/Myriad-Dreamin/tinymist.git", rev = "7b8739487ed959b295c4df39e5cc2ebd47b4e066", default-features = false } +tinymist-world = { git = "https://github.com/Myriad-Dreamin/tinymist.git", rev = "7b8739487ed959b295c4df39e5cc2ebd47b4e066", default-features = false } + # project core reflexo = { version = "0.5.4", path = "crates/reflexo", default-features = false } -reflexo-vfs = { version = "0.5.4", path = "crates/reflexo-vfs" } -reflexo-world = { version = "0.5.4", path = "crates/reflexo-world" } reflexo-typst = { version = "0.5.4", path = "crates/reflexo-typst", default-features = false } -reflexo-typst-shim = { version = "0.5.4", path = "crates/reflexo-typst-shim" } # conversions reflexo-typst2vec = { version = "0.5.4", path = "crates/conversion/typst2vec" } @@ -214,7 +215,12 @@ typst-ts-dev-server = { version = "0.5.4", path = "server/dev" } typst-ts-cli = { version = "0.5.4", path = "cli" } [workspace.lints.rust] -missing_docs = "warn" +# missing_docs = "warn" +unexpected_cfgs = { level = "allow", check-cfg = [ + 'cfg(wasm_bindgen_unstable_test_coverage)', + 'cfg(noop)', + 'cfg(used_linker)', +] } [workspace.lints.clippy] uninlined_format_args = "warn" @@ -245,3 +251,9 @@ typst-pdf = { git = "https://github.com/Myriad-Dreamin/typst", tag = "typst.ts/v # typst-pdf = { path = "../typst/crates/typst-pdf" } # fontdb = { path = "../fontdb" } + +# [patch."https://github.com/Myriad-Dreamin/tinymist.git"] +# typst-shim = { path = "../tinymist/crates/typst-shim" } +# tinymist-analysis = { path = "../tinymist/crates/tinymist-analysis" } +# tinymist-std = { path = "../tinymist/crates/tinymist-std" } +# tinymist-world = { path = "../tinymist/crates/tinymist-world" } diff --git a/benches/lowering/src/lowering.rs b/benches/lowering/src/lowering.rs index 08aca335c..267980740 100644 --- a/benches/lowering/src/lowering.rs +++ b/benches/lowering/src/lowering.rs @@ -26,9 +26,9 @@ static TEST_DOC: LazyLock> = fn compile(driver: &CompileDriver, src: &str) -> Arc { let mut driver = driver.lock().unwrap(); - let e = driver.entry_file().to_owned().unwrap(); + let e = driver.main_id(); driver - .with_shadow_file(&e, src.as_bytes().into(), |this| { + .with_shadow_file_by_id(e, src.as_bytes().into(), |this| { std::marker::PhantomData.compile(&this.snapshot(), &mut Default::default()) }) .unwrap() diff --git a/cli/src/compile.rs b/cli/src/compile.rs index b142ba28d..e3d19b537 100644 --- a/cli/src/compile.rs +++ b/cli/src/compile.rs @@ -19,7 +19,6 @@ use typst::foundations::{Bytes, Dict, IntoValue}; use typst::model::Document; use crate::font::fonts; -use crate::utils::current_dir; use crate::{ utils::{self, UnwrapOrExit}, CompileArgs, CompileOnceArgs, @@ -82,7 +81,9 @@ pub fn create_driver(args: CompileOnceArgs) -> CompileDriver CompileDriver) -> ! { - let is_stdin = args.compile.entry == "-"; let (intr_tx, intr_rx) = mpsc::unbounded_channel(); - let driver = create_driver(args.compile.clone()); - // todo: make dynamic layout exporter let output_dir = { - // If output is specified, use it. - let dir = (!args.compile.output.is_empty()).then(|| Path::new(&args.compile.output)); - // Otherwise, use the parent directory of the entry file. - let entry = driver.entry_file().expect("entry_file is not set"); - let dir = dir.map(Path::to_owned).unwrap_or_else(|| { - if is_stdin { - current_dir() - } else { - entry.parent().expect("entry_file has no parent").to_owned() - } - }); - if is_stdin { + let dir = args.compile.output_dir(); + if args.compile.is_stdin() { dir.join("main") } else { - dir.join(entry.file_name().expect("entry_file has no file name")) + dir.join( + args.compile + .main_id() + .vpath() + .as_rooted_path() + .file_name() + .expect("entry_file has no file name"), + ) } }; + let driver = create_driver(args.compile); + let feature_set = FeatureSet::default().configure(&DIAG_FMT_FEATURE, args.diagnostic_format.into()); diff --git a/cli/src/lib.rs b/cli/src/lib.rs index 40f32a57c..22f2ab427 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -9,11 +9,19 @@ pub mod utils; pub mod version; use core::fmt; -use std::{borrow::Cow, path::PathBuf}; +use std::{ + borrow::Cow, + path::{Path, PathBuf}, + sync::OnceLock, +}; use chrono::{DateTime, Utc}; use clap::{builder::ValueParser, ArgAction, Args, Command, Parser, Subcommand, ValueEnum}; -use reflexo_typst::build_info::VERSION; +use reflexo_typst::{ + build_info::VERSION, vfs::WorkspaceResolver, ImmutPath, TypstFileId, MEMORY_MAIN_ENTRY, +}; +use typst::syntax::VirtualPath; +use utils::current_dir; use version::VersionFormat; /// The character typically used to separate path components @@ -147,6 +155,94 @@ pub struct CompileOnceArgs { #[clap(skip)] pub extra_embedded_fonts: Vec>, + + /// The root of workspace of the compilation. + #[clap(skip)] + pub parsed_entry: OnceLock, + + /// The root of workspace of the compilation. + #[clap(skip)] + pub main_id: OnceLock, + + /// The output directory of the compilation. + #[clap(skip)] + pub parsed_output: OnceLock, +} + +impl CompileOnceArgs { + pub fn is_stdin(&self) -> bool { + self.entry == "-" + } + + pub fn root(&self) -> &ImmutPath { + self.parsed_entry.get_or_init(|| { + let root = Path::new(&self.workspace); + + if root.is_absolute() { + root.into() + } else { + current_dir().join(root).into() + } + }) + } + + pub fn main_id(&self) -> &TypstFileId { + self.main_id.get_or_init(|| { + if self.is_stdin() { + *MEMORY_MAIN_ENTRY + } else { + let root = self.root(); + let entry = Path::new(&self.entry); + + let entry = if entry.is_absolute() { + entry.to_owned() + } else { + current_dir().join(entry) + }; + + let path = match entry.strip_prefix(root) { + Ok(rel) => VirtualPath::new(rel), + Err(_) => clap::Error::raw( + clap::error::ErrorKind::InvalidValue, + format!( + "entry file path must be in workspace directory: {workspace_dir}\n", + workspace_dir = root.display() + ), + ) + .exit(), + }; + + WorkspaceResolver::workspace_file(Some(root), path) + } + }) + } + + pub fn output_dir(&self) -> &ImmutPath { + self.parsed_output.get_or_init(|| { + let input = self.main_id(); + + if self.output.is_empty() { + if self.is_stdin() { + current_dir().into() + } else { + input + .vpath() + .as_rooted_path() + .parent() + .unwrap_or_else(|| { + clap::Error::raw( + clap::error::ErrorKind::InvalidValue, + "entry file has no parent", + ) + .exit() + }) + .into() + } + } else { + Path::new(&self.output).into() + } + }) + } } /// Parses key/value pairs split by the first equal sign. diff --git a/cli/src/main.rs b/cli/src/main.rs index ec6b2802d..ad050344f 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -7,7 +7,6 @@ use std::{ use clap::FromArgMatches; use reflexo_typst::config::{entry::EntryOpts, CompileOpts}; -use reflexo_typst::error::prelude::*; use reflexo_typst::exporter_builtins::GroupExporter; use reflexo_typst::exporter_utils::map_err; use reflexo_typst::path::{unix_slash, PathClean}; diff --git a/cli/src/query_repl.rs b/cli/src/query_repl.rs index 03ba5a6c2..55c452f46 100644 --- a/cli/src/query_repl.rs +++ b/cli/src/query_repl.rs @@ -113,7 +113,7 @@ impl Completer for ReplContext { // commit line changes - let entry = driver.entry_file().unwrap(); + let entry = driver.entry_file().unwrap().to_err().unwrap(); let content = std::fs::read_to_string(&entry).map_err(ReadlineError::Io)?; let static_prefix = content + "\n#show "; let static_prefix_len = static_prefix.len(); diff --git a/crates/conversion/typst2vec/Cargo.toml b/crates/conversion/typst2vec/Cargo.toml index 80d880215..295ff295a 100644 --- a/crates/conversion/typst2vec/Cargo.toml +++ b/crates/conversion/typst2vec/Cargo.toml @@ -40,3 +40,6 @@ no-content-hint = [] glyph2vec = [] debug-gc = [] item-dashmap = ["reflexo/item-dashmap"] + +[lints] +workspace = true diff --git a/crates/conversion/typst2vec/src/font/glyph.rs b/crates/conversion/typst2vec/src/font/glyph.rs index 9091f39dd..af85b65d8 100644 --- a/crates/conversion/typst2vec/src/font/glyph.rs +++ b/crates/conversion/typst2vec/src/font/glyph.rs @@ -1,15 +1,14 @@ +pub use ttf_parser::GlyphId; + use std::fmt::Write; use std::hash::{Hash, Hasher}; use std::{ops::Deref, sync::Arc}; -pub use ttf_parser::GlyphId; +use reflexo::hash::{item_hash128, HashedTrait, StaticHash128}; +use reflexo::ImmutStr; use typst::text::Font; -// use typst::geom::Axes; use typst::visualize::{Image as TypstImage, RasterFormat}; -use reflexo::hash::item_hash128; -use reflexo::{HashedTrait, ImmutStr, StaticHash128}; - use super::ligature::resolve_ligature; /// IGlyphProvider extracts the font data from the font. @@ -168,19 +167,19 @@ struct SvgOutlineBuilder(pub String); impl ttf_parser::OutlineBuilder for SvgOutlineBuilder { fn move_to(&mut self, x: f32, y: f32) { - write!(&mut self.0, "M {} {} ", x, y).unwrap(); + write!(&mut self.0, "M {x} {y} ").unwrap(); } fn line_to(&mut self, x: f32, y: f32) { - write!(&mut self.0, "L {} {} ", x, y).unwrap(); + write!(&mut self.0, "L {x} {y} ").unwrap(); } fn quad_to(&mut self, x1: f32, y1: f32, x: f32, y: f32) { - write!(&mut self.0, "Q {} {} {} {} ", x1, y1, x, y).unwrap(); + write!(&mut self.0, "Q {x1} {y1} {x} {y} ").unwrap(); } fn curve_to(&mut self, x1: f32, y1: f32, x2: f32, y2: f32, x: f32, y: f32) { - write!(&mut self.0, "C {} {} {} {} {} {} ", x1, y1, x2, y2, x, y).unwrap(); + write!(&mut self.0, "C {x1} {y1} {x2} {y2} {x} {y} ").unwrap(); } fn close(&mut self) { diff --git a/crates/conversion/typst2vec/src/font/ligature.rs b/crates/conversion/typst2vec/src/font/ligature.rs index f8fff47b3..9a7d30e9d 100644 --- a/crates/conversion/typst2vec/src/font/ligature.rs +++ b/crates/conversion/typst2vec/src/font/ligature.rs @@ -86,7 +86,7 @@ impl LigatureResolver { .into_iter() .map(|g| { self.rev_cmap.get(&g).unwrap_or_else(|| { - println!("ligature component not found: {:?} {:?}", g, face); + eprintln!("ligature component not found: {g:?} {face:?}"); &' ' }) }) @@ -131,6 +131,6 @@ fn get_ligature_resolver(font: &Font) -> Arc { pub(super) fn resolve_ligature(font: &Font, id: GlyphId) -> Option { let resolver = get_ligature_resolver(font); // let res = resolver.resolve(font.ttf(), id); - // println!("resolve_ligature {:?} {:?} -> {:?}", font, id, res); + // eprintln!("resolve_ligature {:?} {:?} -> {:?}", font, id, res); resolver.resolve(font.ttf(), id) } diff --git a/crates/conversion/typst2vec/src/incr.rs b/crates/conversion/typst2vec/src/incr.rs index 1e051b0d7..d23baa0b0 100644 --- a/crates/conversion/typst2vec/src/incr.rs +++ b/crates/conversion/typst2vec/src/incr.rs @@ -62,7 +62,7 @@ impl IncrDocServer { .map(|i| i.1 .0) .min() .unwrap_or(0); - println!( + eprintln!( "gc[{}]: max: {}, min: {}, remove: {}", self.typst2vec.lifetime, self.typst2vec @@ -78,7 +78,7 @@ impl IncrDocServer { // for (fg, (_, item)) in // self.typst2vec.items.iter().filter(|(_, i)| i.0 == mi) { - // println!("mi {fg:?} => {item:#?}"); + // eprintln!("mi {fg:?} => {item:#?}"); // } } @@ -135,7 +135,7 @@ impl IncrDocServer { pub fn resolve_element_paths_by_span( &mut self, span_offset: SourceSpanOffset, - ) -> ZResult>> { + ) -> Result>> { self.typst2vec.spans.query_element_paths(span_offset) } @@ -143,7 +143,7 @@ impl IncrDocServer { pub fn resolve_span_by_element_path( &mut self, path: &[ElementPoint], - ) -> ZResult> { + ) -> Result> { self.typst2vec.spans.query(path) } } diff --git a/crates/conversion/typst2vec/src/pass/glyph2vec.rs b/crates/conversion/typst2vec/src/pass/glyph2vec.rs index 49ac65204..db5506c99 100644 --- a/crates/conversion/typst2vec/src/pass/glyph2vec.rs +++ b/crates/conversion/typst2vec/src/pass/glyph2vec.rs @@ -424,7 +424,7 @@ impl ConvertInnerImpl { .as_ref() .map(|s| { WARN_VIEW_BOX.get_or_init(|| { - println!( + eprintln!( "render_svg_glyph with viewBox, This should be helpful if you can help us verify the result: {:?} {:?}", font.info().family, doc_string diff --git a/crates/conversion/typst2vec/src/pass/span2vec.rs b/crates/conversion/typst2vec/src/pass/span2vec.rs index 1159e9d8b..d4b820274 100644 --- a/crates/conversion/typst2vec/src/pass/span2vec.rs +++ b/crates/conversion/typst2vec/src/pass/span2vec.rs @@ -309,7 +309,7 @@ impl Span2VecPass { pub fn query_element_paths( &mut self, span_offset: SourceSpanOffset, - ) -> ZResult>> { + ) -> Result>> { self.span_tree.get_or_init(|| { log::info!("lazy spans are initializing"); std::mem::take(&mut self.collector).into() @@ -510,7 +510,7 @@ impl Span2VecPass { pub fn query( &mut self, path: &[ElementPoint], - ) -> ZResult> { + ) -> Result> { self.span_tree.get_or_init(|| { log::info!("lazy spans are initializing"); std::mem::take(&mut self.collector).into() diff --git a/crates/conversion/typst2vec/src/utils.rs b/crates/conversion/typst2vec/src/utils.rs index 3ff59a052..520431a77 100644 --- a/crates/conversion/typst2vec/src/utils.rs +++ b/crates/conversion/typst2vec/src/utils.rs @@ -26,7 +26,7 @@ impl ToCssExt for Rgba8Item { fn to_css(self) -> String { let Rgba8Item { r, g, b, a } = self; if a == 255 { - let shorter = format!("#{:02x}{:02x}{:02x}", r, g, b); + let shorter = format!("#{r:02x}{g:02x}{b:02x}"); if shorter.chars().nth(1) == shorter.chars().nth(2) && shorter.chars().nth(3) == shorter.chars().nth(4) && shorter.chars().nth(5) == shorter.chars().nth(6) @@ -41,7 +41,7 @@ impl ToCssExt for Rgba8Item { return shorter; } - format!("#{:02x}{:02x}{:02x}{:02x}", r, g, b, a) + format!("#{r:02x}{g:02x}{b:02x}{a:02x}") } } diff --git a/crates/conversion/vec2bbox/Cargo.toml b/crates/conversion/vec2bbox/Cargo.toml index 85d05d332..b3a2dfb6c 100644 --- a/crates/conversion/vec2bbox/Cargo.toml +++ b/crates/conversion/vec2bbox/Cargo.toml @@ -19,3 +19,6 @@ tiny-skia-path.workspace = true [features] incremental = ["reflexo/flat-vector"] default = ["incremental"] + +[lints] +workspace = true diff --git a/crates/conversion/vec2bbox/src/lib.rs b/crates/conversion/vec2bbox/src/lib.rs index 88f2ecd7a..9a58160d7 100644 --- a/crates/conversion/vec2bbox/src/lib.rs +++ b/crates/conversion/vec2bbox/src/lib.rs @@ -19,7 +19,7 @@ impl Vec2BBoxPass { } let bbox = self.bbox_of_(module, v, ts); - println!("bbox_of({v:?}, {ts:?}) = {bbox:?}"); + eprintln!("bbox_of({v:?}, {ts:?}) = {bbox:?}"); self.bbox_caches.insert((v, ts), bbox); bbox } diff --git a/crates/conversion/vec2canvas/Cargo.toml b/crates/conversion/vec2canvas/Cargo.toml index 2be082b83..52f220e1b 100644 --- a/crates/conversion/vec2canvas/Cargo.toml +++ b/crates/conversion/vec2canvas/Cargo.toml @@ -48,3 +48,6 @@ incremental = ["reflexo/flat-vector"] report_group = [] render_bbox = [] rasterize_glyph = [] + +[lints] +workspace = true diff --git a/crates/conversion/vec2canvas/src/bounds.rs b/crates/conversion/vec2canvas/src/bounds.rs index 4c2788b14..2c6063f03 100644 --- a/crates/conversion/vec2canvas/src/bounds.rs +++ b/crates/conversion/vec2canvas/src/bounds.rs @@ -19,7 +19,7 @@ pub enum CanvasBBox { impl fmt::Debug for CanvasBBox { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - CanvasBBox::Static(r) => write!(f, "Static({:?})", r), + CanvasBBox::Static(r) => write!(f, "Static({r:?})"), CanvasBBox::Dynamic(..) => write!(f, "Dynamic(..)"), } } diff --git a/crates/conversion/vec2canvas/src/incr.rs b/crates/conversion/vec2canvas/src/incr.rs index 1b09a5815..a5e587151 100644 --- a/crates/conversion/vec2canvas/src/incr.rs +++ b/crates/conversion/vec2canvas/src/incr.rs @@ -117,7 +117,7 @@ impl IncrCanvasDocClient { canvas: &dyn CanvasDevice, idx: usize, _rect: Rect, - ) -> ZResult<()> { + ) -> Result<()> { self.patch_delta(kern); if idx >= self.vec2canvas.pages.len() { diff --git a/crates/conversion/vec2canvas/src/lib.rs b/crates/conversion/vec2canvas/src/lib.rs index 468292e78..c1f379861 100644 --- a/crates/conversion/vec2canvas/src/lib.rs +++ b/crates/conversion/vec2canvas/src/lib.rs @@ -394,7 +394,9 @@ impl Drop for CanvasStateGuard<'_> { #[derive(Debug, Clone)] struct UnsafeMemorize(T); +// Safety: `UnsafeMemorize` is only used in wasm targets unsafe impl Send for UnsafeMemorize {} +// Safety: `UnsafeMemorize` is only used in wasm targets unsafe impl Sync for UnsafeMemorize {} #[derive(Debug, Clone)] diff --git a/crates/conversion/vec2canvas/src/utils.rs b/crates/conversion/vec2canvas/src/utils.rs index 708f65c95..ab1e8fab5 100644 --- a/crates/conversion/vec2canvas/src/utils.rs +++ b/crates/conversion/vec2canvas/src/utils.rs @@ -12,7 +12,7 @@ macro_rules! console_log { #[allow(unused_macros)] macro_rules! console_log { ($($arg:tt)*) => { - println!( + eprintln!( $($arg)* ); } diff --git a/crates/conversion/vec2dom/Cargo.toml b/crates/conversion/vec2dom/Cargo.toml index babdfb494..4230c703e 100644 --- a/crates/conversion/vec2dom/Cargo.toml +++ b/crates/conversion/vec2dom/Cargo.toml @@ -55,3 +55,6 @@ debug_repaint_semantics = [] debug_recalc_stage = [] debug_attach = [] debug_relayout = [] + +[lints] +workspace = true diff --git a/crates/conversion/vec2dom/src/canvas_backend.rs b/crates/conversion/vec2dom/src/canvas_backend.rs index 07ac5e737..e2ab34d32 100644 --- a/crates/conversion/vec2dom/src/canvas_backend.rs +++ b/crates/conversion/vec2dom/src/canvas_backend.rs @@ -27,7 +27,7 @@ impl CanvasBackend { self.pixel_per_pt = 3.; } - pub fn render_page(&mut self, module: &Module, page: &Page) -> ZResult { + pub fn render_page(&mut self, module: &Module, page: &Page) -> Result { // todo: incremental let mut ct = self.vec2canvas.fork_canvas_render_task(module); diff --git a/crates/conversion/vec2dom/src/dom.rs b/crates/conversion/vec2dom/src/dom.rs index a262c3eab..e9f1cd7ac 100644 --- a/crates/conversion/vec2dom/src/dom.rs +++ b/crates/conversion/vec2dom/src/dom.rs @@ -124,7 +124,7 @@ impl DomPage { } pub fn track_data(&mut self, data: &Page) -> bool { - if self.layout_data.as_ref().map_or(false, |d| d == data) { + if self.layout_data.as_ref() == Some(data) { return false; } @@ -177,7 +177,7 @@ impl DomPage { } } - pub fn relayout(&mut self, ctx: &CanvasBackend) -> ZResult<()> { + pub fn relayout(&mut self, ctx: &CanvasBackend) -> Result<()> { if let Some(data) = self.dirty_layout.take() { self.do_relayout(ctx, data)? } @@ -185,7 +185,7 @@ impl DomPage { Ok(()) } - fn do_relayout(&mut self, ctx: &CanvasBackend, data: Page) -> ZResult<()> { + fn do_relayout(&mut self, ctx: &CanvasBackend, data: Page) -> Result<()> { #[cfg(feature = "debug_relayout")] web_sys::console::log_2( &format!("re-layout {idx} {data:?}", idx = self.idx).into(), @@ -213,16 +213,13 @@ impl DomPage { .unwrap(); let style = self.elem.style(); style - .set_property("--data-page-width", &format!("{:.3}px", w)) + .set_property("--data-page-width", &format!("{w:.3}px")) .unwrap(); style - .set_property("--data-page-height", &format!("{:.3}px", h)) + .set_property("--data-page-height", &format!("{h:.3}px")) .unwrap(); self.svg - .set_attribute( - "viewBox", - &format!("0 0 {width} {height}", width = w, height = h), - ) + .set_attribute("viewBox", &format!("0 0 {w} {h}")) .unwrap(); self.svg @@ -287,7 +284,7 @@ impl DomPage { should_visible } - pub fn repaint_svg(&mut self, ctx: &mut DomContext<'_, '_>) -> ZResult<()> { + pub fn repaint_svg(&mut self, ctx: &mut DomContext<'_, '_>) -> Result<()> { let should_visible = !self.bbox.intersect(&self.viewport).is_empty(); if cfg!(feature = "debug_repaint") { @@ -377,7 +374,7 @@ impl DomPage { }) } - pub fn repaint_semantics(&mut self, ctx: &mut DomContext<'_, '_>) -> ZResult<()> { + pub fn repaint_semantics(&mut self, ctx: &mut DomContext<'_, '_>) -> Result<()> { let init_semantics = self.semantics_state.as_ref().map_or(true, |e| { let (data, _layout_heavy) = e; e.0.content != data.content @@ -415,7 +412,7 @@ impl DomPage { Ok(()) } - pub fn need_prepare_canvas(&mut self, module: &Module, b: &mut CanvasBackend) -> ZResult { + pub fn need_prepare_canvas(&mut self, module: &Module, b: &mut CanvasBackend) -> Result { // already pulled // self.pull_viewport(viewport); @@ -451,7 +448,7 @@ impl DomPage { pub fn prepare_canvas( &mut self, ctx: &mut DomContext<'_, '_>, - ) -> ZResult>> { + ) -> Result>> { let need_repaint = self.need_repaint_canvas(ctx.canvas_backend); let res = if need_repaint { @@ -492,7 +489,7 @@ impl DomPage { &mut self, viewport: Option, ppp: f32, - ) -> ZResult> { + ) -> Result> { let render_entire_page = self.realized.lock().unwrap().is_none() || !self.is_visible; if let Some(attached) = self.realized.lock().unwrap().as_mut() { @@ -525,7 +522,7 @@ impl DomPage { let mut elem = elem.lock().unwrap(); - web_sys::console::log_1(&format!("canvas render: {idx} {:?}", viewport).into()); + web_sys::console::log_1(&format!("canvas render: {idx} {viewport:?}").into()); 'render_canvas: { let _global_guard = CanvasStateGuard::new(&canvas_ctx); @@ -534,7 +531,7 @@ impl DomPage { .lock() .unwrap() .as_ref() - .map_or(false, |s| s.rendered == state && s.ppp == ppp) + .is_some_and(|s| s.rendered == state && s.ppp == ppp) { break 'render_canvas; } @@ -576,7 +573,7 @@ impl DomPage { .lock() .unwrap() .as_ref() - .map_or(false, |e| e.render_entire_page); + .is_some_and(|e| e.render_entire_page); let Some(elem) = elem.as_mut() else { panic!("realized is none for partial canvas render"); @@ -616,7 +613,7 @@ impl DomPage { } } - let clip_key = format!("{:?}", clip_rect); + let clip_key = format!("{clip_rect:?}"); // data-clip-rect-state const CLIP_KEY: &str = "data-clip-rect-state"; @@ -626,7 +623,7 @@ impl DomPage { let _ = canvas.set_attribute(CLIP_KEY, &clip_key); if let Some((x, y, w, h)) = clip_rect { - let modify = |p, x| canvas.style().set_property(p, &format!("{:.3}%", x)); + let modify = |p, x| canvas.style().set_property(p, &format!("{x:.3}%")); let _ = modify("--reflexo-clip-lo-x", x); let _ = modify("--reflexo-clip-lo-y", y); let _ = modify("--reflexo-clip-hi-x", x + w); diff --git a/crates/conversion/vec2dom/src/incr.rs b/crates/conversion/vec2dom/src/incr.rs index 7c5341395..99de2f0b8 100644 --- a/crates/conversion/vec2dom/src/incr.rs +++ b/crates/conversion/vec2dom/src/incr.rs @@ -71,7 +71,7 @@ impl IncrDomDocClient { } /// Relayout the document in the given window. - pub async fn relayout(&mut self, x: f32, y: f32, w: f32, h: f32) -> ZResult { + pub async fn relayout(&mut self, x: f32, y: f32, w: f32, h: f32) -> Result { // todo: overflow let viewport = Some(tiny_skia::Rect::from_xywh(x, y, w, h).unwrap()); @@ -95,7 +95,7 @@ impl IncrDomDocClient { w: f32, h: f32, stage: u8, - ) -> ZResult { + ) -> Result { // todo: overflow let viewport = Some(tiny_skia::Rect::from_xywh(x, y, w, h).unwrap()); #[cfg(feature = "debug_recalc_stage")] @@ -130,7 +130,7 @@ impl IncrDomDocClient { w: f32, h: f32, stage: u8, - ) -> ZResult { + ) -> Result { // todo: overflow let viewport = Some(tiny_skia::Rect::from_xywh(x, y, w, h).unwrap()); #[cfg(feature = "debug_recalc_stage")] @@ -178,7 +178,7 @@ impl IncrDomDocClient { .into()); } web_sys::console::log_1( - &format!("canvas state prepare done: {}", page_num).into(), + &format!("canvas state prepare done: {page_num}").into(), ); } } @@ -282,7 +282,7 @@ impl IncrDomDocClient { kern.set_layout(layout.1.clone()); } - fn retrack_pages(&mut self, kern: &mut IncrDocClient, elem: HookedElement) -> ZResult { + fn retrack_pages(&mut self, kern: &mut IncrDocClient, elem: HookedElement) -> Result { // Checks out the current document layout. let pages = self.checkout_pages(kern); @@ -321,7 +321,7 @@ impl IncrDomDocClient { } /// Render the document in the given window. - pub async fn mount(&mut self, elem: HtmlElement) -> ZResult<()> { + pub async fn mount(&mut self, elem: HtmlElement) -> Result<()> { if let Some(old_elem) = self.elem.as_ref() { return Err(error_once!( "already mounted to", diff --git a/crates/conversion/vec2dom/src/svg_backend.rs b/crates/conversion/vec2dom/src/svg_backend.rs index 71b0327f5..34dc84764 100644 --- a/crates/conversion/vec2dom/src/svg_backend.rs +++ b/crates/conversion/vec2dom/src/svg_backend.rs @@ -161,7 +161,7 @@ impl TypstPageElem { .ok_or_else(|| { web_sys::console::log_2( &should_ch, - &format!("Invalid group translate: {:?}", item).into(), + &format!("Invalid group translate: {item:?}").into(), ); panic!("Invalid group translate: {}", fg.as_svg_id("g")); }) @@ -182,7 +182,7 @@ impl TypstPageElem { .ok_or_else(|| { web_sys::console::log_2( &g, - &format!("Invalid item reference: {:?}", item).into(), + &format!("Invalid item reference: {item:?}").into(), ); panic!("Invalid item reference: {}", fg.as_svg_id("g")); }) @@ -207,7 +207,7 @@ impl TypstPageElem { .ok_or_else(|| { web_sys::console::log_2( &g, - &format!("Invalid item translate: {:?}", item).into(), + &format!("Invalid item translate: {item:?}").into(), ); panic!("Invalid item translate: {}", fg.as_svg_id("g")); }) diff --git a/crates/conversion/vec2sema/Cargo.toml b/crates/conversion/vec2sema/Cargo.toml index 7aa43596f..c82ce3e81 100644 --- a/crates/conversion/vec2sema/Cargo.toml +++ b/crates/conversion/vec2sema/Cargo.toml @@ -24,3 +24,6 @@ web-sys.workspace = true [features] incremental = ["reflexo/flat-vector"] default = ["incremental"] + +[lints] +workspace = true diff --git a/crates/conversion/vec2svg/Cargo.toml b/crates/conversion/vec2svg/Cargo.toml index e6d5d1d96..23aab07de 100644 --- a/crates/conversion/vec2svg/Cargo.toml +++ b/crates/conversion/vec2svg/Cargo.toml @@ -24,3 +24,6 @@ experimental-ligature = ["reflexo-typst2vec/experimental-ligature"] aggresive-browser-rasterization = ["reflexo-vec2canvas"] no-content-hint = ["reflexo-typst2vec/no-content-hint"] default = [] + +[lints] +workspace = true diff --git a/crates/conversion/vec2svg/src/backend/glyph.rs b/crates/conversion/vec2svg/src/backend/glyph.rs index cedde447b..2be741bff 100644 --- a/crates/conversion/vec2svg/src/backend/glyph.rs +++ b/crates/conversion/vec2svg/src/backend/glyph.rs @@ -20,9 +20,9 @@ impl SvgGlyphBuilder { } fn render_ligature_attr(ll: u8) -> String { - // println!("ligature len: {}", ll); + // eprintln!("ligature len: {}", ll); if ll > 0 { - format!(r#" data-liga-len="{}""#, ll) + format!(r#" data-liga-len="{ll}""#) } else { "".to_owned() } @@ -51,8 +51,7 @@ impl SvgGlyphBuilder { let li = Self::render_ligature_attr(ig.ligature_len); let symbol_def = format!( - r#"{}"#, - glyph_id, img + r#"{img}"# ); Some(symbol_def) } diff --git a/crates/conversion/vec2svg/src/backend/mod.rs b/crates/conversion/vec2svg/src/backend/mod.rs index 265712d85..8307feb70 100644 --- a/crates/conversion/vec2svg/src/backend/mod.rs +++ b/crates/conversion/vec2svg/src/backend/mod.rs @@ -273,7 +273,7 @@ impl SvgTextBuilder { .as_svg_id("g"); let mut do_trans = |obj: &PaintObj, pref: &'static str| -> String { let og = obj.id.as_svg_id(pref); - let ng = format!("{}-{adjusted_offset}", og).replace('.', "-"); + let ng = format!("{og}-{adjusted_offset}").replace('.', "-"); let new_color = Self::transform_color( obj.kind, @@ -356,7 +356,7 @@ impl TransformContext for SvgTextBuilder { clip_id, path.d ))); self.attributes - .push(("clip-path", format!(r"url(#{})", clip_id))); + .push(("clip-path", format!(r"url(#{clip_id})"))); self } } @@ -478,8 +478,7 @@ impl< #[inline] fn attach_debug_info(&mut self, ctx: &mut C, span_id: u64) { if ctx.should_attach_debug_info() { - self.attributes - .push(("data-span", format!("{:x}", span_id))); + self.attributes.push(("data-span", format!("{span_id:x}"))); } } fn render_item_at(&mut self, ctx: &mut C, pos: crate::ir::Point, item: &Fingerprint) { @@ -509,8 +508,7 @@ impl< self.content.push(SvgText::Plain(format!( // r##""##, - r##""##, - adjusted_offset, glyph_id + r##""## ))); } @@ -648,7 +646,7 @@ fn render_path( p.push(format!(r#"d="{}" "#, path.d)); let (fill_color, stroke_color) = attach_path_styles(&path.styles, None, &mut |x, y| { - p.push(format!(r#"{}="{}" "#, x, y)) + p.push(format!(r#"{x}="{y}" "#)) }); let contextual_id = |id: &'static str| abs_ref.as_svg_id(id); @@ -656,7 +654,7 @@ fn render_path( if fill_color.starts_with('@') { p.push(format!(r#"fill="url(#{})" "#, contextual_id("pf"))); } else { - p.push(format!(r#"fill="{}" "#, fill_color)); + p.push(format!(r#"fill="{fill_color}" "#)); } } else { p.push(r#"fill="none" "#.to_string()); @@ -665,7 +663,7 @@ fn render_path( if stroke_color.starts_with('@') { p.push(format!(r#"stroke="url(#{})" "#, contextual_id("ps"))); } else { - p.push(format!(r#"stroke="{}" "#, stroke_color)); + p.push(format!(r#"stroke="{stroke_color}" "#)); } } p.push("/>".to_owned()); diff --git a/crates/conversion/vec2svg/src/frontend/context.rs b/crates/conversion/vec2svg/src/frontend/context.rs index 6440cf4f2..437ecb225 100644 --- a/crates/conversion/vec2svg/src/frontend/context.rs +++ b/crates/conversion/vec2svg/src/frontend/context.rs @@ -97,7 +97,7 @@ impl<'m, Feat: ExportFeature> FontIndice<'m> for RenderContext<'m, '_, Feat> { self.module.fonts.get(value.idx as usize).inspect(|e| { // canary check if e.hash != value.hash { - panic!("Invalid font reference: {:?}", value); + panic!("Invalid font reference: {value:?}"); } }) } @@ -156,7 +156,7 @@ impl NotifyPaint for RenderContext<'_, '_, Feat> { self.patterns.insert(id); (kind, id, transform) } else { - panic!("Invalid url reference: {}", url_ref); + panic!("Invalid url reference: {url_ref}"); } } } @@ -257,8 +257,7 @@ impl RenderContext<'_, '_, Feat> { let descender = font.descender.0 * upem.0; group_ctx.content.push(SvgText::Plain(format!( - r#""#, - clip_id + r#""# ))); let mut width = 0f32; diff --git a/crates/conversion/vec2svg/src/frontend/flat.rs b/crates/conversion/vec2svg/src/frontend/flat.rs index 52d724ec0..25e9a3379 100644 --- a/crates/conversion/vec2svg/src/frontend/flat.rs +++ b/crates/conversion/vec2svg/src/frontend/flat.rs @@ -26,7 +26,7 @@ impl SvgTask<'_, Feat> { svg_body.push(SvgText::Content(Arc::new(SvgTextNode { attributes: vec![ ("class", "typst-page".into()), - ("transform", format!("translate(0, {})", acc_height)), + ("transform", format!("translate(0, {acc_height})")), ("data-tid", entry.as_svg_id("p")), ("data-page-width", size.x.to_string()), ("data-page-height", size.y.to_string()), diff --git a/crates/conversion/vec2svg/src/frontend/incremental.rs b/crates/conversion/vec2svg/src/frontend/incremental.rs index bfabce6e4..d2c5027eb 100644 --- a/crates/conversion/vec2svg/src/frontend/incremental.rs +++ b/crates/conversion/vec2svg/src/frontend/incremental.rs @@ -65,8 +65,8 @@ impl SvgTask<'_, Feat> { } } - // println!("reusable: {:?}", reusable); - // println!("unused_prev: {:?}", unused_prev); + // eprintln!("reusable: {:?}", reusable); + // eprintln!("unused_prev: {:?}", unused_prev); for Page { content: entry, @@ -76,7 +76,7 @@ impl SvgTask<'_, Feat> { let size = Self::page_size(*size_f32); let mut attributes = vec![ ("class", "typst-page".into()), - ("transform", format!("translate(0, {})", acc_height)), + ("transform", format!("translate(0, {acc_height})")), ("data-tid", entry.as_svg_id("p")), ("data-page-width", size.x.to_string()), ("data-page-height", size.y.to_string()), @@ -84,7 +84,7 @@ impl SvgTask<'_, Feat> { if *entry == NULL_PAGE { attributes.push(("data-dummy", "1".into())); - // println!("reuse page: {} {:?}", idx, entry); + // eprintln!("reuse page: {} {:?}", idx, entry); svg_body.push(SvgText::Content(Arc::new(SvgTextNode { attributes, content: vec![], @@ -93,11 +93,11 @@ impl SvgTask<'_, Feat> { acc_height += size.y; continue; } - // println!("page: {} {:?} {:?}", acc_height, entry, EMPTY_PAGE); + // eprintln!("page: {} {:?} {:?}", acc_height, entry, EMPTY_PAGE); if reusable.contains(entry) { attributes.push(("data-reuse-from", entry.as_svg_id("p"))); - // println!("reuse page: {} {:?}", idx, entry); + // eprintln!("reuse page: {} {:?}", idx, entry); svg_body.push(SvgText::Content(Arc::new(SvgTextNode { attributes, content: vec![], @@ -109,13 +109,13 @@ impl SvgTask<'_, Feat> { // todo: evaluate simlarity let item = if let Some(prev_entry) = unused_prev.pop_first().map(|(_, v)| v) { - // println!("diff page: {} {:?} {:?}", idx, entry, prev_entry); + // eprintln!("diff page: {} {:?} {:?}", idx, entry, prev_entry); attributes.push(("data-reuse-from", prev_entry.as_svg_id("p"))); render_task.render_diff_item(entry, &prev_entry) } else { // todo: find a bbox - // println!("rebuild page: {} {:?}", idx, entry); + // eprintln!("rebuild page: {} {:?}", idx, entry); render_task.render_item(entry) }; diff --git a/crates/conversion/vec2svg/src/frontend/mod.rs b/crates/conversion/vec2svg/src/frontend/mod.rs index 7115cf635..97aa440d8 100644 --- a/crates/conversion/vec2svg/src/frontend/mod.rs +++ b/crates/conversion/vec2svg/src/frontend/mod.rs @@ -59,8 +59,7 @@ impl SvgExporter { /// ^^^^^ fn header_inner(w: f32, h: f32) -> String { format!( - r#""#, - w, h, w, h, w, h, + r#""#, ) } @@ -532,11 +531,11 @@ impl SvgPath2DBuilder { impl SvgPath2DBuilder { fn move_to(&mut self, x: f32, y: f32) { - write!(&mut self.0, "M {} {} ", x, y).unwrap(); + write!(&mut self.0, "M {x} {y} ").unwrap(); } fn line_to(&mut self, x: f32, y: f32) { - write!(&mut self.0, "L {} {} ", x, y).unwrap(); + write!(&mut self.0, "L {x} {y} ").unwrap(); } /// Creates an arc path. diff --git a/crates/conversion/vec2svg/src/transform/minify.rs b/crates/conversion/vec2svg/src/transform/minify.rs index 67ff959e9..b31f988d7 100644 --- a/crates/conversion/vec2svg/src/transform/minify.rs +++ b/crates/conversion/vec2svg/src/transform/minify.rs @@ -19,8 +19,8 @@ pub fn minify_one(text: &mut SvgText) -> bool { { // let transform = content.attributes[0].1.as_str(); - // println!("minify_one fold transform: {:#?}", transform); - // println!("minify_one fold transform after: {:#?}", transform); + // eprintln!("minify_one fold transform: {:#?}", transform); + // eprintln!("minify_one fold transform after: {:#?}", transform); let sub_content = match &mut content.content[0] { SvgText::Plain(_) => unreachable!(), @@ -65,12 +65,12 @@ pub fn minify_one(text: &mut SvgText) -> bool { /// Do semantic-aware minification of SVG. pub fn minify(mut svg: Vec) -> Vec { - // println!("minify_svg: {:#?}", svg); + // eprintln!("minify_svg: {:#?}", svg); for text in svg.iter_mut() { minify_one(text); } - // println!("minify_svg after: {:#?}", svg); + // eprintln!("minify_svg after: {:#?}", svg); svg } diff --git a/crates/reflexo-typst-shim/Cargo.toml b/crates/reflexo-typst-shim/Cargo.toml deleted file mode 100644 index b0f689f31..000000000 --- a/crates/reflexo-typst-shim/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "reflexo-typst-shim" -description = "A compatibility layer for Typst release and mainline versions." -authors = ["The Typst Project Developers"] -version.workspace = true -edition.workspace = true -readme.workspace = true -license.workspace = true -homepage.workspace = true -repository.workspace = true - -[features] -default = [] -nightly = [] - -[dependencies] -typst-syntax.workspace = true -typst.workspace = true -cfg-if.workspace = true - -[lints] -workspace = true diff --git a/crates/reflexo-typst-shim/src/lib.rs b/crates/reflexo-typst-shim/src/lib.rs deleted file mode 100644 index 841d50b17..000000000 --- a/crates/reflexo-typst-shim/src/lib.rs +++ /dev/null @@ -1,13 +0,0 @@ -//! # typst-shim - -pub use cfg_if::cfg_if; - -cfg_if! { - if #[cfg(feature = "nightly")] { - mod nightly; - pub use nightly::*; - } else { - mod stable; - pub use stable::*; - } -} diff --git a/crates/reflexo-typst-shim/src/nightly/mod.rs b/crates/reflexo-typst-shim/src/nightly/mod.rs deleted file mode 100644 index 4a39d2cfa..000000000 --- a/crates/reflexo-typst-shim/src/nightly/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod syntax; diff --git a/crates/reflexo-typst-shim/src/nightly/syntax.rs b/crates/reflexo-typst-shim/src/nightly/syntax.rs deleted file mode 100644 index 590463fa1..000000000 --- a/crates/reflexo-typst-shim/src/nightly/syntax.rs +++ /dev/null @@ -1,16 +0,0 @@ -//! Typst Syntax -use typst::syntax::LinkedNode; -use typst::syntax::Side; - -/// The `LinkedNodeExt` trait is designed for compatibility between new and old -/// versions of `typst`. -pub trait LinkedNodeExt: Sized { - /// Get the leaf at the specified byte offset. - fn leaf_at_compat(&self, cursor: usize) -> Option; -} - -impl LinkedNodeExt for LinkedNode<'_> { - fn leaf_at_compat(&self, cursor: usize) -> Option { - self.leaf_at(cursor, Side::Before) - } -} diff --git a/crates/reflexo-typst-shim/src/stable/mod.rs b/crates/reflexo-typst-shim/src/stable/mod.rs deleted file mode 100644 index 4a39d2cfa..000000000 --- a/crates/reflexo-typst-shim/src/stable/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod syntax; diff --git a/crates/reflexo-typst-shim/src/stable/syntax.rs b/crates/reflexo-typst-shim/src/stable/syntax.rs deleted file mode 100644 index 590463fa1..000000000 --- a/crates/reflexo-typst-shim/src/stable/syntax.rs +++ /dev/null @@ -1,16 +0,0 @@ -//! Typst Syntax -use typst::syntax::LinkedNode; -use typst::syntax::Side; - -/// The `LinkedNodeExt` trait is designed for compatibility between new and old -/// versions of `typst`. -pub trait LinkedNodeExt: Sized { - /// Get the leaf at the specified byte offset. - fn leaf_at_compat(&self, cursor: usize) -> Option; -} - -impl LinkedNodeExt for LinkedNode<'_> { - fn leaf_at_compat(&self, cursor: usize) -> Option { - self.leaf_at(cursor, Side::Before) - } -} diff --git a/crates/reflexo-typst/Cargo.toml b/crates/reflexo-typst/Cargo.toml index e5034fabd..c2287b6db 100644 --- a/crates/reflexo-typst/Cargo.toml +++ b/crates/reflexo-typst/Cargo.toml @@ -14,8 +14,7 @@ typst-pdf = { workspace = true, optional = true } reflexo-typst2vec.workspace = true reflexo.workspace = true -reflexo-vfs.workspace = true -reflexo-world.workspace = true +tinymist-world.workspace = true comemo.workspace = true ecow.workspace = true @@ -64,20 +63,17 @@ no-content-hint = ["reflexo-typst2vec/no-content-hint"] glyph2vec = ["reflexo-typst2vec/glyph2vec"] dynamic-layout = ["dep:reflexo-vec2svg"] -system-compile = ["glyph2vec", "reflexo-vfs/system", "reflexo-world/system"] +system-compile = ["glyph2vec", "tinymist-world/system"] system-watch = ["dep:notify", "dep:tokio"] -browser-compile = [ - "__web", - "web-render", - "glyph2vec", - "reflexo-vfs/browser", - "reflexo-world/browser", -] +browser-compile = ["__web", "web-render", "glyph2vec", "tinymist-world/browser"] browser-embedded-fonts = ["__web"] __web = ["dep:js-sys", "dep:web-sys"] -__web_render = ["__web", "reflexo-vfs/web", "reflexo-world/web"] +__web_render = ["__web", "tinymist-world/web"] web-render = ["__web_render"] ast = ["ansi_term"] pdf = ["typst-pdf"] svg = ["dep:reflexo-vec2svg"] + +[lints] +workspace = true diff --git a/crates/reflexo-typst/src/compile.rs b/crates/reflexo-typst/src/compile.rs index 6ac29d386..89c95e90a 100644 --- a/crates/reflexo-typst/src/compile.rs +++ b/crates/reflexo-typst/src/compile.rs @@ -9,21 +9,20 @@ use std::{ sync::{Arc, OnceLock}, }; -use reflexo_vfs::notify::UpstreamUpdateEvent; -use reflexo_world::{EntryReader, Revising, TaskInputs}; use tokio::sync::{mpsc, oneshot}; -use crate::{exporter::GenericExporter, ExportSignal, TypstDocument}; +use crate::features::{FeatureSet, WITH_COMPILING_STATUS_FEATURE}; +use crate::task::CacheTask; +use crate::vfs::notify::{FilesystemEvent, MemoryEvent, NotifyMessage, UpstreamUpdateEvent}; +use crate::vfs::FsProvider; +use crate::world::{ + CompilerFeat, CompilerUniverse, CompilerWorld, EntryReader, RevisingUniverse, TaskInputs, +}; +use crate::{exporter::GenericExporter, watch::watch_deps, ExportSignal, TypstDocument}; use crate::{ - features::{FeatureSet, WITH_COMPILING_STATUS_FEATURE}, - vfs::notify::{FilesystemEvent, MemoryEvent, NotifyMessage}, - watch_deps, - world::{CompilerFeat, CompilerUniverse, CompilerWorld}, CompileEnv, CompileReport, CompileSnapshot, CompiledArtifact, ConsoleDiagReporter, WorldDeps, }; -use crate::task::CacheTask; - pub trait CompilationHandle: Send + Sync + 'static { fn status(&self, revision: usize, rep: CompileReport); fn notify_compile(&self, res: &CompiledArtifact, rep: CompileReport); @@ -441,11 +440,13 @@ impl CompileActor { // Notify the new file dependencies. let mut deps = vec![]; - artifact - .world - .iter_dependencies(&mut |dep| deps.push(dep.clone())); + artifact.world.iter_dependencies(&mut |dep| { + if let Ok(x) = artifact.world.file_path(dep).and_then(|e| e.to_err()) { + deps.push(x.into()) + } + }); send(CompilerResponse::Notify(NotifyMessage::SyncDependency( - deps, + Box::new(deps), ))); // Trigger an evict task. @@ -459,7 +460,9 @@ impl CompileActor { match event { Interrupt::Compile => { // Increment the revision anyway. - self.verse.increment_revision(|_| {}); + self.verse.increment_revision(|verse| { + verse.flush(); + }); reason_by_entry_change() } @@ -468,7 +471,7 @@ impl CompileActor { if self .watch_snap .get() - .is_some_and(|e| e.world.revision() < *self.verse.revision.read()) + .is_some_and(|e| e.world.revision() < self.verse.revision) { self.watch_snap = OnceLock::new(); } @@ -503,7 +506,7 @@ impl CompileActor { if self.suspended { log::info!("CompileActor: removing diag"); self.compile_handle - .status(self.verse.revision.get_mut().get(), CompileReport::Suspend); + .status(self.verse.revision.get(), CompileReport::Suspend); } // Reset the watch state and document state. @@ -572,7 +575,7 @@ impl CompileActor { // Actual a delayed memory event. reason = reason_by_mem(); } - verse.notify_fs_event(event) + verse.vfs().notify_fs_event(event) }); reason @@ -589,7 +592,7 @@ impl CompileActor { /// Apply delayed memory changes to underlying compiler. fn apply_delayed_memory_changes( - verse: &mut Revising>, + verse: &mut RevisingUniverse, dirty_shadow_logical_tick: &mut usize, event: &mut FilesystemEvent, ) -> Option<()> { @@ -613,25 +616,18 @@ impl CompileActor { } /// Apply memory changes to underlying compiler. - fn apply_memory_changes(verse: &mut Revising>, event: MemoryEvent) { + fn apply_memory_changes(verse: &mut RevisingUniverse, event: MemoryEvent) { + let mut vfs = verse.vfs(); if matches!(event, MemoryEvent::Sync(..)) { - verse.reset_shadow(); + vfs.reset_shadow(); } match event { MemoryEvent::Update(event) | MemoryEvent::Sync(event) => { - for removes in event.removes { - let _ = verse.unmap_shadow(&removes); + for path in event.removes { + let _ = vfs.unmap_shadow(&path); } - for (p, t) in event.inserts { - let insert_file = match t.content().cloned() { - Ok(content) => content, - Err(err) => { - log::error!("CompileActor: read memory file at {p:?}: {err}"); - continue; - } - }; - - let _ = verse.map_shadow(&p, insert_file); + for (path, snap) in event.inserts { + let _ = vfs.map_shadow(&path, snap); } } } diff --git a/crates/reflexo-typst/src/config/mod.rs b/crates/reflexo-typst/src/config/mod.rs index 9450bdbd8..b5821c525 100644 --- a/crates/reflexo-typst/src/config/mod.rs +++ b/crates/reflexo-typst/src/config/mod.rs @@ -1,5 +1,5 @@ -pub use reflexo_world::config as compiler; -pub use reflexo_world::entry; +pub use tinymist_world::config as compiler; +pub use tinymist_world::entry; pub mod workspace; pub use compiler::CompileFontOpts; diff --git a/crates/reflexo-typst/src/diag/console.rs b/crates/reflexo-typst/src/diag/console.rs index d483a5b34..e30340a71 100644 --- a/crates/reflexo-typst/src/diag/console.rs +++ b/crates/reflexo-typst/src/diag/console.rs @@ -1,4 +1,5 @@ use std::io::IsTerminal; +use std::marker::PhantomData; use std::sync::Arc; use codespan_reporting::files::Files; @@ -21,7 +22,7 @@ use crate::features::{ CompileFeature, FeatureSet, DIAG_FMT_FEATURE, WITH_COMPILING_STATUS_FEATURE, }; use crate::CompileReport; -use crate::{typst::prelude::*, GenericExporter, PhantomParamData, TakeAs, TypstFileId}; +use crate::{typst::prelude::*, GenericExporter, TakeAs, TypstFileId}; use super::DiagnosticFormat; @@ -93,14 +94,14 @@ fn label<'files, W: World + Files<'files, FileId = TypstFileId>>( } #[derive(Debug, Clone, Copy)] -pub struct ConsoleDiagReporter(PhantomParamData); +pub struct ConsoleDiagReporter(PhantomData); impl Default for ConsoleDiagReporter where W: for<'files> codespan_reporting::files::Files<'files, FileId = TypstFileId>, { fn default() -> Self { - Self(PhantomParamData::default()) + Self(PhantomData) } } diff --git a/crates/reflexo-typst/src/driver.rs b/crates/reflexo-typst/src/driver.rs index cdd96d1ec..ed3a35aca 100644 --- a/crates/reflexo-typst/src/driver.rs +++ b/crates/reflexo-typst/src/driver.rs @@ -1,19 +1,14 @@ -use std::{ - path::{Path, PathBuf}, - sync::Arc, -}; +use std::{path::Path, sync::Arc}; -use reflexo_world::DETACHED_ENTRY; use typst::{ - diag::{eco_format, EcoString, SourceResult, Warned}, + diag::{eco_format, EcoString, FileResult, SourceResult, Warned}, foundations::Content, }; use super::{CompileEnv, Compiler}; -use crate::EntryReader; -use crate::{ - world::{CompilerFeat, CompilerUniverse, CompilerWorld}, - ShadowApi, +use crate::vfs::{FileId, PathResolution}; +use crate::world::{ + CompilerFeat, CompilerUniverse, CompilerWorld, EntryReader, ShadowApi, DETACHED_ENTRY, }; use crate::{Bytes, TypstDocument, TypstFileId}; @@ -27,9 +22,8 @@ pub struct CompileDriverImpl { } impl CompileDriverImpl { - pub fn entry_file(&self) -> Option { - let main = self.universe.entry_state().main()?; - self.universe.path_for_id(main).ok() + pub fn entry_file(&self) -> Option { + self.universe.path_for_id(self.main_id()).ok() } } @@ -73,8 +67,14 @@ impl CompileDriverImpl { /// reset the compilation state pub fn reset(&mut self) -> SourceResult<()> { - // reset the world caches self.universe.reset(); + Ok(()) + } + + /// evict the compilation state + pub fn evict(&mut self, vfs_threshold: usize) -> SourceResult<()> { + // evict the world caches + self.universe.evict(vfs_threshold); Ok(()) } @@ -146,13 +146,13 @@ impl CompileDriverImpl { impl ShadowApi for CompileDriverImpl { #[inline] - fn _shadow_map_id(&self, file_id: TypstFileId) -> typst::diag::FileResult { - self.universe._shadow_map_id(file_id) + fn shadow_paths(&self) -> Vec> { + self.universe.shadow_paths() } #[inline] - fn shadow_paths(&self) -> Vec> { - self.universe.shadow_paths() + fn shadow_ids(&self) -> Vec { + self.universe.shadow_ids() } #[inline] @@ -161,14 +161,24 @@ impl ShadowApi for CompileDriverImpl { } #[inline] - fn map_shadow(&mut self, path: &Path, content: Bytes) -> typst::diag::FileResult<()> { + fn map_shadow(&mut self, path: &Path, content: Bytes) -> FileResult<()> { self.universe.map_shadow(path, content) } #[inline] - fn unmap_shadow(&mut self, path: &Path) -> typst::diag::FileResult<()> { + fn unmap_shadow(&mut self, path: &Path) -> FileResult<()> { self.universe.unmap_shadow(path) } + + #[inline] + fn map_shadow_by_id(&mut self, file_id: FileId, content: Bytes) -> FileResult<()> { + self.universe.map_shadow_by_id(file_id, content) + } + + #[inline] + fn unmap_shadow_by_id(&mut self, file_id: FileId) -> FileResult<()> { + self.universe.unmap_shadow_by_id(file_id) + } } struct AtFile(TypstFileId); diff --git a/crates/reflexo-typst/src/error.rs b/crates/reflexo-typst/src/error.rs index 4ea077c07..af79f96d1 100644 --- a/crates/reflexo-typst/src/error.rs +++ b/crates/reflexo-typst/src/error.rs @@ -1,15 +1,15 @@ use core::fmt; -use reflexo::debug_loc::CharRange; -pub use reflexo::error::*; - +use ecow::eco_format; +use reflexo::debug_loc::{LspPosition, LspRange}; use reflexo::path::unix_slash; -use typst::syntax::Source; +use typst::syntax::{Source, Span}; -pub use typst::diag::SourceDiagnostic as TypstSourceDiagnostic; +use crate::vfs::{WorkspaceResolution, WorkspaceResolver}; +pub use reflexo::error::*; pub use typst::diag::FileError as TypstFileError; -use typst::syntax::Span; +pub use typst::diag::SourceDiagnostic as TypstSourceDiagnostic; struct DiagMsgFmt<'a>(&'a TypstSourceDiagnostic); @@ -30,9 +30,9 @@ struct PosFmt<'a>(&'a typst::diag::Tracepoint); impl fmt::Display for PosFmt<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match &self.0 { - typst::diag::Tracepoint::Call(Some(name)) => write!(f, "while calling {}", name), + typst::diag::Tracepoint::Call(Some(name)) => write!(f, "while calling {name}"), typst::diag::Tracepoint::Call(None) => write!(f, "while calling closure"), - typst::diag::Tracepoint::Show(name) => write!(f, "while showing {}", name), + typst::diag::Tracepoint::Show(name) => write!(f, "while showing {name}"), typst::diag::Tracepoint::Import => write!(f, "import"), } } @@ -41,16 +41,30 @@ impl fmt::Display for PosFmt<'_> { fn resolve_source_span( s: Span, world: Option<&dyn typst::World>, -) -> (String, String, Option) { +) -> (String, String, Option) { let mut package = String::new(); let mut path = String::new(); let mut range = None; if let Some(id) = s.id() { - if let Some(pkg) = id.package() { - package = pkg.to_string(); - }; - path = unix_slash(id.vpath().as_rooted_path()); + match WorkspaceResolver::resolve(id) { + Ok(WorkspaceResolution::Package) => { + package = id.package().unwrap().to_string(); + path = unix_slash(id.vpath().as_rooted_path()); + } + Ok(WorkspaceResolution::Rootless | WorkspaceResolution::UntitledRooted(..)) => { + path = unix_slash(id.vpath().as_rooted_path()); + } + Ok(WorkspaceResolution::Workspace(workspace)) => { + path = id + .vpath() + .resolve(&workspace.path()) + .as_deref() + .map(unix_slash) + .unwrap_or_default(); + } + Err(..) => {} + } if let Some((rng, src)) = world .and_then(|world| world.source(id).ok()) @@ -58,9 +72,13 @@ fn resolve_source_span( { let resolve_off = |src: &Source, off: usize| src.byte_to_line(off).zip(src.byte_to_column(off)); - range = Some(CharRange { - start: resolve_off(&src, rng.start).into(), - end: resolve_off(&src, rng.end).into(), + range = Some(LspRange { + start: resolve_off(&src, rng.start) + .map(|(l, c)| LspPosition::new(l as u32, c as u32)) + .unwrap_or_default(), + end: resolve_off(&src, rng.end) + .map(|(l, c)| LspPosition::new(l as u32, c as u32)) + .unwrap_or_default(), }); } } @@ -76,7 +94,7 @@ pub fn diag_from_std(diag: TypstSourceDiagnostic, world: Option<&dyn typst::Worl DiagMessage { package, path, - message: DiagMsgFmt(&diag).to_string(), + message: eco_format!("{}", DiagMsgFmt(&diag)), severity: match diag.severity { typst::diag::Severity::Error => DiagSeverity::Error, typst::diag::Severity::Warning => DiagSeverity::Warning, @@ -98,7 +116,7 @@ pub fn long_diag_from_std( DiagMessage { package, path, - message: PosFmt(&trace.v).to_string(), + message: eco_format!("{}", PosFmt(&trace.v)), severity: DiagSeverity::Hint, range, } @@ -119,15 +137,15 @@ pub trait ErrorConverter { arguments.push(("path", msg.path)); if let Some(range) = msg.range { arguments.push(("start_line", range.start.line.to_string())); - arguments.push(("start_column", range.start.column.to_string())); + arguments.push(("start_column", range.start.character.to_string())); arguments.push(("end_line", range.end.line.to_string())); - arguments.push(("end_column", range.end.column.to_string())); + arguments.push(("end_column", range.end.character.to_string())); } Error::new( "typst", ErrKind::Msg(msg.message), - arguments.into_boxed_slice(), + Some(arguments.into_boxed_slice()), ) } } diff --git a/crates/reflexo-typst/src/export.rs b/crates/reflexo-typst/src/export.rs index 47a16078f..2ca47c81f 100644 --- a/crates/reflexo-typst/src/export.rs +++ b/crates/reflexo-typst/src/export.rs @@ -1,16 +1,14 @@ use std::sync::Arc; use reflexo_typst2vec::pass::Typst2VecPass; -use reflexo_world::{CompilerFeat, CompilerWorld}; use typst::{ diag::{SourceResult, Warned}, World, }; -use crate::{ - vector::ir::{LayoutRegion, LayoutRegionNode}, - CompiledArtifact, -}; +use crate::vector::ir::{LayoutRegion, LayoutRegionNode}; +use crate::world::{CompilerFeat, CompilerWorld}; +use crate::CompiledArtifact; #[cfg(feature = "dynamic-layout")] mod dynamic_layout; diff --git a/crates/reflexo-typst/src/export/dynamic_layout.rs b/crates/reflexo-typst/src/export/dynamic_layout.rs index ef7be9a6f..de1599491 100644 --- a/crates/reflexo-typst/src/export/dynamic_layout.rs +++ b/crates/reflexo-typst/src/export/dynamic_layout.rs @@ -3,7 +3,7 @@ use std::{path::PathBuf, sync::Arc}; use reflexo_typst2vec::pass::{CommandExecutor, Typst2VecPass}; use reflexo_typst2vec::IntoTypst; use reflexo_vec2svg::{DynamicLayoutSvgExporter, MultiVecDocument}; -use reflexo_world::TaskInputs; +use tinymist_world::TaskInputs; use typst::diag::Warned; use typst::foundations::IntoValue; use typst::utils::LazyHash; @@ -240,10 +240,6 @@ impl> + Clone> Exporter>> Compiler for DynamicLayoutCompiler { type W = CompilerWorld; - fn reset(&mut self) -> SourceResult<()> { - Ok(()) - } - fn compile( &mut self, world: &Self::W, diff --git a/crates/reflexo-typst/src/exporter/ast.rs b/crates/reflexo-typst/src/exporter/ast.rs index 38374a2b7..b7e9404ac 100644 --- a/crates/reflexo-typst/src/exporter/ast.rs +++ b/crates/reflexo-typst/src/exporter/ast.rs @@ -52,7 +52,7 @@ const MARKED: ansi_term::Color = ansi_term::Color::RGB(0x7d, 0xcf, 0xff); impl AstWriter<'_, W> { fn write_num_repr(&mut self, sk: SyntaxKind, ast: T) -> Option<()> { - self.painted(NUMBER, format!("Num({:?}, {})", sk, ast)); + self.painted(NUMBER, format!("Num({sk:?}, {ast})")); Some(()) } @@ -65,27 +65,27 @@ impl AstWriter<'_, W> { if let Some(hl) = typst::syntax::highlight(ast) { match hl { Tag::Comment => { - self.painted(COMMENT, format!("Ct::{:?}", k)); + self.painted(COMMENT, format!("Ct::{k:?}")); return; } Tag::Escape => { - self.w.write_fmt(format_args!("Escape::{:?}", k)).unwrap(); + self.w.write_fmt(format_args!("Escape::{k:?}")).unwrap(); return; } Tag::Keyword => { - self.painted(KEYWORD, format!("Kw::{:?}", k)); + self.painted(KEYWORD, format!("Kw::{k:?}")); return; } Tag::Operator => { - self.painted(OPERATOR, format!("Op::{:?}", k)); + self.painted(OPERATOR, format!("Op::{k:?}")); return; } Tag::Punctuation => { - self.painted(PUNC, format!("Punc::{:?}", k)); + self.painted(PUNC, format!("Punc::{k:?}")); return; } Tag::Function => { - self.painted(FUNCTION, format!("Fn::({:?})", ast)); + self.painted(FUNCTION, format!("Fn::({ast:?})")); return; } Tag::String => { @@ -111,7 +111,7 @@ impl AstWriter<'_, W> { return; } Tag::Interpolated => { - self.painted(VARIABLE, format!("Var::({:?})", ast)); + self.painted(VARIABLE, format!("Var::({ast:?})")); return; } _ => {} @@ -119,10 +119,10 @@ impl AstWriter<'_, W> { } if k == SyntaxKind::Ident { - self.painted(MARKED, format!("Marked::({:?})", ast)); + self.painted(MARKED, format!("Marked::({ast:?})")); return; } - self.painted(MARKED, format!("Marked::{:?}", k)); + self.painted(MARKED, format!("Marked::{k:?}")); } fn write_ast(&mut self, src: &Source, ast: &LinkedNode) { diff --git a/crates/reflexo-typst/src/lib.rs b/crates/reflexo-typst/src/lib.rs index 92c17ec89..32820a919 100644 --- a/crates/reflexo-typst/src/lib.rs +++ b/crates/reflexo-typst/src/lib.rs @@ -96,11 +96,11 @@ pub use world::font; /// time things about compiler. pub use reflexo::time; -/// A vfs implementation for compiler. -pub use reflexo_vfs as vfs; -/// A common implementation of [`::typst::World`] -pub use reflexo_world as world; pub use time::Time; +/// A common implementation of [`::typst::World`] +pub use tinymist_world as world; +/// A vfs implementation for compiler. +pub use tinymist_world::vfs; /// package things about compiler. pub use world::package; /// Diff and parse the source code. @@ -121,7 +121,7 @@ pub mod task; #[cfg(feature = "system-compile")] pub use diag::ConsoleDiagReporter; #[cfg(feature = "system-compile")] -pub type CompileDriver = CompileDriverImpl; +pub type CompileDriver = CompileDriverImpl; pub use self::{diag::DiagnosticFormat, features::FeatureSet}; pub use driver::*; @@ -140,6 +140,7 @@ use ::typst::{ utils::Deferred, World, }; +use vfs::WorkspaceResolver; #[derive(Clone, Default)] pub struct CompileEnv { @@ -221,10 +222,10 @@ impl fmt::Display for CompileReportMsg<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use CompileReport::*; - let input = self.0.compiling_id(); + let input = WorkspaceResolver::display(self.0.compiling_id()); match self.0 { Suspend => write!(f, "suspended"), - Stage(_, stage, ..) => write!(f, "{:?}: {} ...", input, stage), + Stage(_, stage, ..) => write!(f, "{input:?}: {stage} ..."), CompileSuccess(_, warnings, duration) => { if warnings.is_empty() { write!(f, "{input:?}: compilation succeeded in {duration:?}") @@ -237,7 +238,7 @@ impl fmt::Display for CompileReportMsg<'_> { } } CompileError(_, _, duration) | ExportError(_, _, duration) => { - write!(f, "{:?}: compilation failed after {:?}", input, duration) + write!(f, "{input:?}: compilation failed after {duration:?}") } } } @@ -389,9 +390,6 @@ pub trait EnvWorld { pub trait Compiler { type W: World; - /// reset the compilation state - fn reset(&mut self) -> SourceResult<()>; - fn ensure_main(&self, world: &Self::W) -> SourceResult<()> where Self::W: EntryReader, @@ -406,8 +404,6 @@ pub trait Compiler { world: &Self::W, _env: &mut CompileEnv, ) -> SourceResult>> { - self.reset()?; - let res = ::typst::compile(world); // compile document // res.output.map(Arc::new) @@ -463,10 +459,6 @@ pub type PureCompiler = std::marker::PhantomData; impl Compiler for PureCompiler { type W = W; - - fn reset(&mut self) -> SourceResult<()> { - Ok(()) - } } pub trait CompileMiddleware { @@ -476,11 +468,6 @@ pub trait CompileMiddleware { fn inner_mut(&mut self) -> &mut Self::Compiler; - /// Hooked reset the compilation state - fn wrap_reset(&mut self) -> SourceResult<()> { - self.inner_mut().reset() - } - /// Hooked compile once from scratch. fn wrap_compile( &mut self, @@ -508,11 +495,6 @@ pub trait CompileMiddleware { impl Compiler for T { type W = <::Compiler as Compiler>::W; - #[inline] - fn reset(&mut self) -> SourceResult<()> { - self.wrap_reset() - } - #[inline] fn pure_compile( &mut self, diff --git a/crates/reflexo-typst/src/task.rs b/crates/reflexo-typst/src/task.rs index 95a13076e..4b2325d0a 100644 --- a/crates/reflexo-typst/src/task.rs +++ b/crates/reflexo-typst/src/task.rs @@ -42,7 +42,7 @@ struct FutureFolder { } impl FutureFolder { - async fn compute<'scope, OP, R: Send + 'static>(op: OP) -> ZResult + async fn compute<'scope, OP, R: Send + 'static>(op: OP) -> Result where OP: FnOnce(&Scope<'scope>) -> R + Send + 'static, { diff --git a/crates/reflexo-typst/src/utils.rs b/crates/reflexo-typst/src/utils.rs index a9025b715..4fb7d8607 100644 --- a/crates/reflexo-typst/src/utils.rs +++ b/crates/reflexo-typst/src/utils.rs @@ -13,7 +13,7 @@ macro_rules! console_log { #[allow(unused_macros)] macro_rules! console_log { ($($arg:tt)*) => { - println!( + eprintln!( $($arg)* ); } diff --git a/crates/reflexo-typst/src/watch.rs b/crates/reflexo-typst/src/watch.rs index 96dd77687..cf5e6ed84 100644 --- a/crates/reflexo-typst/src/watch.rs +++ b/crates/reflexo-typst/src/watch.rs @@ -12,20 +12,19 @@ use std::collections::HashMap; use notify::{Config, RecommendedWatcher, RecursiveMode, Watcher}; +use reflexo::ImmutPath; use tokio::sync::mpsc; -use typst::diag::{EcoString, FileError, FileResult}; +use typst::diag::FileError; use crate::vfs::{ - notify::{FileChangeSet, FileSnapshot, FilesystemEvent, NotifyMessage, UpstreamUpdateEvent}, + notify::{FilesystemEvent, NotifyDeps, NotifyMessage, UpstreamUpdateEvent}, system::SystemAccessModel, - AccessModel, + FileChangeSet, FileSnapshot, PathAccessModel, }; -use crate::{Bytes, ImmutPath}; type WatcherPair = (RecommendedWatcher, mpsc::UnboundedReceiver); type NotifyEvent = notify::Result; type FileEntry = (/* key */ ImmutPath, /* value */ FileSnapshot); -type NotifyFilePair = FileResult<(/* mtime */ crate::Time, /* content */ Bytes)>; /// The state of a watched file. /// @@ -39,7 +38,7 @@ enum WatchState { /// stable. So we need to recheck the file after a while. EmptyOrRemoval { recheck_at: usize, - payload: NotifyFilePair, + payload: FileSnapshot, }, } @@ -65,9 +64,7 @@ struct WatchedEntry { /// The state of the entry. state: WatchState, /// Previous content of the file. - prev: Option, - /// Previous metadata of the file. - prev_meta: FileResult, + prev: Option, } /// Self produced event that check whether the file is stable after a while. @@ -85,7 +82,7 @@ struct UndeterminedNotifyEvent { /// The actor that watches files. /// It is used to watch files and send events to the consumers #[derive(Debug)] -pub struct NotifyActor { +pub struct NotifyActor { /// The access model of the actor. /// We concrete the access model to `SystemAccessModel` for now. inner: SystemAccessModel, @@ -95,10 +92,6 @@ pub struct NotifyActor { /// The logical tick of the actor. logical_tick: usize, - /// Output of the actor. - /// See [`FilesystemEvent`] for more information. - sender: mpsc::UnboundedSender, - /// Internal channel for recheck events. undetermined_send: mpsc::UnboundedSender, undetermined_recv: mpsc::UnboundedReceiver, @@ -106,13 +99,15 @@ pub struct NotifyActor { /// The hold entries for watching, one entry for per file. watched_entries: HashMap, + interrupted_by_events: F, + /// The builtin watcher object. watcher: Option, } -impl NotifyActor { +impl NotifyActor { /// Create a new actor. - fn new(sender: mpsc::UnboundedSender) -> NotifyActor { + pub fn new(interrupted_by_events: F) -> Self { let (undetermined_send, undetermined_recv) = mpsc::unbounded_channel(); let (watcher_sender, watcher_receiver) = mpsc::unbounded_channel(); let watcher = log_notify_error( @@ -134,7 +129,7 @@ impl NotifyActor { lifetime: 1, logical_tick: 1, - sender, + interrupted_by_events, undetermined_send, undetermined_recv, @@ -144,11 +139,6 @@ impl NotifyActor { } } - /// Send a filesystem event to remove. - fn send(&mut self, msg: FilesystemEvent) { - log_send_error("fs_event", self.sender.send(msg)); - } - /// Get the notify event from the watcher. async fn get_notify_event(watcher: &mut Option) -> Option { match watcher { @@ -158,14 +148,15 @@ impl NotifyActor { } /// Main loop of the actor. - async fn run(mut self, mut inbox: mpsc::UnboundedReceiver) { + pub async fn run(mut self, mut inbox: mpsc::UnboundedReceiver) { + use NotifyMessage::*; /// The event of the actor. #[derive(Debug)] enum ActorEvent { /// Recheck the notify event. ReCheck(UndeterminedNotifyEvent), /// external message to change notifier's state - Message(NotifyMessage), + Message(Option), /// notify event from builtin watcher NotifyEvent(NotifyEvent), } @@ -173,15 +164,9 @@ impl NotifyActor { 'event_loop: loop { // Get the event from the inbox or the watcher. let event = tokio::select! { - Some(it) = inbox.recv() => Some(ActorEvent::Message(it)), - Some(it) = Self::get_notify_event(&mut self.watcher) => Some(ActorEvent::NotifyEvent(it)), - Some(it) = self.undetermined_recv.recv() => Some(ActorEvent::ReCheck(it)), - }; - - // Failed to get the event. - let Some(event) = event else { - log::info!("failed to get event, exiting..."); - return; + it = inbox.recv() => ActorEvent::Message(it), + Some(it) = Self::get_notify_event(&mut self.watcher) => ActorEvent::NotifyEvent(it), + Some(it) = self.undetermined_recv.recv() => ActorEvent::ReCheck(it), }; // Increase the logical tick per event. @@ -190,16 +175,20 @@ impl NotifyActor { // log::info!("vfs-notify event {event:?}"); // function entries to handle some event match event { - ActorEvent::Message(NotifyMessage::Settle) => { + ActorEvent::Message(None) => { + log::info!("failed to get event, exiting..."); + break 'event_loop; + } + ActorEvent::Message(Some(Settle)) => { log::info!("NotifyActor: settle event received"); break 'event_loop; } - ActorEvent::Message(NotifyMessage::UpstreamUpdate(event)) => { + ActorEvent::Message(Some(UpstreamUpdate(event))) => { self.invalidate_upstream(event); } - ActorEvent::Message(NotifyMessage::SyncDependency(paths)) => { - if let Some(changeset) = self.update_watches(&paths) { - self.send(FilesystemEvent::Update(changeset)); + ActorEvent::Message(Some(SyncDependency(paths))) => { + if let Some(changeset) = self.update_watches(paths.as_ref()) { + (self.interrupted_by_events)(FilesystemEvent::Update(changeset)); } } ActorEvent::NotifyEvent(event) => { @@ -223,14 +212,14 @@ impl NotifyActor { let changeset = self.update_watches(&event.invalidates).unwrap_or_default(); // Send the event to the consumer. - self.send(FilesystemEvent::UpstreamUpdate { + (self.interrupted_by_events)(FilesystemEvent::UpstreamUpdate { changeset, upstream_event: Some(event), }); } /// Update the watches of corresponding files. - fn update_watches(&mut self, paths: &[ImmutPath]) -> Option { + fn update_watches(&mut self, paths: &dyn NotifyDeps) -> Option { // Increase the lifetime per external message. self.lifetime += 1; @@ -245,7 +234,7 @@ impl NotifyActor { // // Also check whether the file is updated since there is a window // between unwatch the file and watch the file again. - for path in paths.iter() { + paths.dependencies(&mut |path| { let mut contained = false; // Update or insert the entry with the new lifetime. let entry = self @@ -254,17 +243,20 @@ impl NotifyActor { .and_modify(|watch_entry| { contained = true; watch_entry.lifetime = self.lifetime; - watch_entry.seen = true; }) .or_insert_with(|| WatchedEntry { lifetime: self.lifetime, watching: false, - seen: true, + seen: false, state: WatchState::Stable, prev: None, - prev_meta: Err(FileError::Other(Some(EcoString::from("_not-init_")))), }); + if entry.seen { + return; + } + entry.seen = true; + // Update in-memory metadata for now. let meta = path.metadata().map_err(|e| FileError::from_io(e, path)); @@ -285,15 +277,12 @@ impl NotifyActor { .is_some(); } - changeset.may_insert(self.notify_entry_update(path.clone(), Some(meta))); + changeset.may_insert(self.notify_entry_update(path.clone())); } else { - let watched = meta.and_then(|meta| { - let content = self.inner.content(path)?; - Ok((meta.modified().unwrap(), content)) - }); + let watched = self.inner.content(path); changeset.inserts.push((path.clone(), watched.into())); } - } + }); // Remove old entries. // Note: since we have increased the lifetime, it is safe to remove the @@ -323,7 +312,7 @@ impl NotifyActor { let mut changeset = FileChangeSet::default(); for path in event.paths.iter() { // todo: remove this clone: path.into() - changeset.may_insert(self.notify_entry_update(path.as_path().into(), None)); + changeset.may_insert(self.notify_entry_update(path.as_path().into())); } // Workaround for notify-rs' implicit unwatch on remove/rename @@ -356,19 +345,12 @@ impl NotifyActor { // Send file updates. if !changeset.is_empty() { - self.send(FilesystemEvent::Update(changeset)); + (self.interrupted_by_events)(FilesystemEvent::Update(changeset)); } } /// Notify any update of the file entry - fn notify_entry_update( - &mut self, - path: ImmutPath, - meta: Option>, - ) -> Option { - let mut meta = - meta.unwrap_or_else(|| path.metadata().map_err(|e| FileError::from_io(e, &path))); - + fn notify_entry_update(&mut self, path: ImmutPath) -> Option { // The following code in rust-analyzer is commented out // todo: check whether we need this // if meta.file_type().is_dir() && self @@ -381,53 +363,24 @@ impl NotifyActor { // Find entry and continue let entry = self.watched_entries.get_mut(&path)?; - std::mem::swap(&mut entry.prev_meta, &mut meta); - let prev_meta = meta; - let next_meta = &entry.prev_meta; - - let meta = match (prev_meta, next_meta) { - (Err(prev), Err(next)) => { - if prev != *next { - return Some((path.clone(), FileSnapshot::from(Err(next.clone())))); - } - return None; - } - // todo: check correctness - (Ok(..), Err(next)) => { - // Invalidate the entry content - entry.prev = None; - - return Some((path.clone(), FileSnapshot::from(Err(next.clone())))); - } - (_, Ok(meta)) => meta, - }; - - if !meta.file_type().is_file() { - return None; - } - // Check meta, path, and content - - // Get meta, real path and ignore errors - let mtime = meta.modified().ok()?; - - let mut file = self.inner.content(&path).map(|it| (mtime, it)); + let file = FileSnapshot::from(self.inner.content(&path)); // Check state in fast path: compare state, return None on not sending // the file change - match (&entry.prev, &mut file) { + match (entry.prev.as_deref(), file.as_ref()) { // update the content of the entry in the following cases: // + Case 1: previous content is clear // + Case 2: previous content is not clear but some error, and the // current content is ok (None, ..) | (Some(Err(..)), Ok(..)) => {} // Meet some error currently - (Some(..), Err(err)) => match &mut entry.state { + (Some(it), Err(err)) => match &mut entry.state { // If the file is stable, check whether the editor is removing // or truncating the file. They are possibly flushing the file // but not finished yet. WatchState::Stable => { - if matches!(err, FileError::NotFound(..) | FileError::Other(..)) { + if matches!(err.as_ref(), FileError::NotFound(..) | FileError::Other(..)) { entry.state = WatchState::EmptyOrRemoval { recheck_at: self.logical_tick, payload: file.clone(), @@ -442,6 +395,11 @@ impl NotifyActor { return None; } // Otherwise, we push the error to the consumer. + + // Ignores the error if the error is stable + if it.as_ref().is_err_and(|it| it == err) { + return None; + } } // Very complicated case of check error sequence, so we simplify @@ -453,7 +411,7 @@ impl NotifyActor { } }, // Compare content for transitional the state - (Some(Ok((prev_tick, prev_content))), Ok((next_tick, next_content))) => { + (Some(Ok(prev_content)), Ok(next_content)) => { // So far it is accurately no change for the file, skip it if prev_content == next_content { return None; @@ -485,27 +443,6 @@ impl NotifyActor { // Otherwise, we push the diff to the consumer. WatchState::EmptyOrRemoval { .. } => {} } - - // We have found a change, however, we need to check whether the - // mtime is changed. Generally, the mtime should be changed. - // However, It is common that editor (VSCode) to change the - // mtime after writing - // - // this condition should be never happen, but we still check it - // - // There will be cases that user change content of a file and - // then also modify the mtime of the file, so we need to check - // `next_tick == prev_tick`: Whether mtime is changed. - // `matches!(entry.state, WatchState::Fresh)`: Whether the file - // is fresh. We have not submit the file to the compiler, so - // that is ok. - if next_tick == prev_tick && matches!(entry.state, WatchState::Stable) { - // this is necessary to invalidate our mtime-based cache - *next_tick = prev_tick - .checked_add(std::time::Duration::from_micros(1)) - .unwrap(); - log::warn!("same content but mtime is different...: {:?} content: prev:{:?} v.s. curr:{:?}", path, prev_content, next_content); - }; } }; @@ -515,7 +452,7 @@ impl NotifyActor { entry.prev = Some(file.clone()); // Slow path: trigger the file change for consumer - Some((path, file.into())) + Some((path, file)) } /// Recheck the notify event after a while. @@ -528,6 +465,7 @@ impl NotifyActor { if reserved < std::time::Duration::from_millis(50) { let send = self.undetermined_send.clone(); tokio::spawn(async move { + // todo: sleep in browser tokio::time::sleep(std::time::Duration::from_millis(50) - reserved).await; log_send_error("reschedule", send.send(event)); }); @@ -548,12 +486,17 @@ impl NotifyActor { payload, } => { if recheck_at == event.at_logical_tick { - log::debug!("notify event real happened {event:?}, state: {:?}", payload); + log::debug!("notify event real happened {event:?}, state: {payload:?}"); + + if Some(&payload) == entry.prev.as_ref() { + return None; + } // Send the underlying change to the consumer let mut changeset = FileChangeSet::default(); - changeset.inserts.push((event.path, payload.into())); - self.send(FilesystemEvent::Update(changeset)); + changeset.inserts.push((event.path, payload)); + + (self.interrupted_by_events)(FilesystemEvent::Update(changeset)); } } }; @@ -574,21 +517,12 @@ fn log_send_error(chan: &'static str, res: Result<(), mpsc::error::SendError< .is_ok() } +/// Watches on a set of *files*. pub async fn watch_deps( inbox: mpsc::UnboundedReceiver, - mut interrupted_by_events: impl FnMut(FilesystemEvent), + interrupted_by_events: impl FnMut(FilesystemEvent) + Send + Sync + 'static, ) { - // Setup file watching. - let (tx, mut rx) = mpsc::unbounded_channel(); - let actor = NotifyActor::new(tx); - - // Watch messages to notify - tokio::spawn(actor.run(inbox)); - - // Handle events. log::debug!("start watching files..."); - while let Some(event) = rx.recv().await { - interrupted_by_events(event); - } - log::debug!("stop watching files..."); + // Watch messages to notify + tokio::spawn(NotifyActor::new(interrupted_by_events).run(inbox)); } diff --git a/crates/reflexo-vfs/Cargo.toml b/crates/reflexo-vfs/Cargo.toml deleted file mode 100644 index f9a990c4b..000000000 --- a/crates/reflexo-vfs/Cargo.toml +++ /dev/null @@ -1,29 +0,0 @@ -[package] -name = "reflexo-vfs" -description = "Vfs for reflexo." -authors.workspace = true -version.workspace = true -license.workspace = true -edition.workspace = true -homepage.workspace = true -repository.workspace = true - -[dependencies] - -typst.workspace = true -reflexo.workspace = true -parking_lot.workspace = true -nohash-hasher.workspace = true -indexmap.workspace = true -log.workspace = true -rpds = "1" - -wasm-bindgen = { workspace = true, optional = true } -web-sys = { workspace = true, optional = true } -js-sys = { workspace = true, optional = true } - -[features] - -web = ["wasm-bindgen", "web-sys", "js-sys", "reflexo/web"] -browser = ["web"] -system = ["reflexo/system"] diff --git a/crates/reflexo-vfs/README.md b/crates/reflexo-vfs/README.md deleted file mode 100644 index 49b333a82..000000000 --- a/crates/reflexo-vfs/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# reflexo-vfs - -Vfs for reflexo. - -See [Typst.ts](https://github.com/Myriad-Dreamin/typst.ts) diff --git a/crates/reflexo-vfs/src/browser.rs b/crates/reflexo-vfs/src/browser.rs deleted file mode 100644 index a84f3fc83..000000000 --- a/crates/reflexo-vfs/src/browser.rs +++ /dev/null @@ -1,97 +0,0 @@ -use std::path::Path; - -use reflexo::ImmutPath; -use typst::diag::{FileError, FileResult}; -use wasm_bindgen::prelude::*; - -use crate::{AccessModel, Bytes, Time}; - -/// Provides proxy access model from typst compiler to some JavaScript -/// implementation. -#[derive(Debug, Clone)] -pub struct ProxyAccessModel { - /// The `this` value when calling the JavaScript functions - pub context: JsValue, - /// The JavaScript function to get the mtime of a file - pub mtime_fn: js_sys::Function, - /// The JavaScript function to check if a path corresponds to a file or a - /// directory - pub is_file_fn: js_sys::Function, - /// The JavaScript function to get the real path of a file - pub real_path_fn: js_sys::Function, - /// The JavaScript function to get the content of a file - pub read_all_fn: js_sys::Function, -} - -impl AccessModel for ProxyAccessModel { - fn mtime(&self, src: &Path) -> FileResult(source: &Cow<'b, [u8]>, serializer: S) -> Result - where - S: Serializer, - { - let t: &[u8] = source.borrow(); - StdBase64::serialize_as(&t, serializer) - } -} - -impl<'b, 'de> DeserializeAs<'de, Cow<'b, [u8]>> for AsCowBytes { - fn deserialize_as(deserializer: D) -> Result, D::Error> - where - D: Deserializer<'de>, - { - let buf: Vec = StdBase64::deserialize_as(deserializer)?; - Ok(Cow::Owned(buf)) - } -} diff --git a/crates/reflexo/src/concepts/mod.rs b/crates/reflexo/src/concepts/mod.rs deleted file mode 100644 index f27176567..000000000 --- a/crates/reflexo/src/concepts/mod.rs +++ /dev/null @@ -1,22 +0,0 @@ -mod takable; -use std::{path::Path, sync::Arc}; - -pub use takable::*; - -mod hash; -pub use hash::*; - -pub mod cow_mut; - -mod query; -pub use query::*; - -mod read; -pub use read::*; - -mod marker; -pub use marker::*; - -pub type ImmutStr = Arc; -pub type ImmutBytes = Arc<[u8]>; -pub type ImmutPath = Arc; diff --git a/crates/reflexo/src/concepts/query.rs b/crates/reflexo/src/concepts/query.rs deleted file mode 100644 index 021662488..000000000 --- a/crates/reflexo/src/concepts/query.rs +++ /dev/null @@ -1,83 +0,0 @@ -use core::fmt; -use std::sync::OnceLock; - -use parking_lot::Mutex; - -/// Represent the result of an immutable query reference. -/// The compute function should be pure enough. -/// -/// [`compute`]: Self::compute -/// [`compute_ref`]: Self::compute_ref -pub struct QueryRef { - ctx: Mutex>, - /// `None` means no value has been computed yet. - cell: OnceLock>, -} - -impl QueryRef { - pub fn with_value(value: T) -> Self { - let cell = OnceLock::new(); - cell.get_or_init(|| Ok(value)); - Self { - ctx: Mutex::new(None), - cell, - } - } - - pub fn with_context(ctx: QC) -> Self { - Self { - ctx: Mutex::new(Some(ctx)), - cell: OnceLock::new(), - } - } -} - -impl QueryRef { - /// Compute and return a checked reference guard. - #[inline] - pub fn compute Result>(&self, f: F) -> Result<&T, E> { - self.compute_with_context(|_| f()) - } - - /// Compute with context and return a checked reference guard. - #[inline] - pub fn compute_with_context Result>(&self, f: F) -> Result<&T, E> { - let result = self.cell.get_or_init(|| f(self.ctx.lock().take().unwrap())); - result.as_ref().map_err(Clone::clone) - } - - /// Gets the reference to the (maybe uninitialized) result. - /// - /// Returns `None` if the cell is empty, or being initialized. This - /// method never blocks. - /// - /// It is possible not hot, so that it is non-inlined - pub fn get_uninitialized(&self) -> Option<&Result> { - self.cell.get() - } -} - -impl Default for QueryRef { - fn default() -> Self { - QueryRef { - ctx: Mutex::new(Some(())), - cell: OnceLock::new(), - } - } -} - -impl fmt::Debug for QueryRef -where - T: fmt::Debug, - E: fmt::Debug, - QC: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let ctx = self.ctx.lock(); - let res = self.cell.get(); - f.debug_struct("QueryRef") - .field("context", &ctx) - .field("result", &res) - .finish() - } -} diff --git a/crates/reflexo/src/concepts/read.rs b/crates/reflexo/src/concepts/read.rs deleted file mode 100644 index e5c67a5e7..000000000 --- a/crates/reflexo/src/concepts/read.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub trait ReadAllOnce { - fn read_all(self, buf: &mut Vec) -> std::io::Result; -} diff --git a/crates/reflexo/src/concepts/takable.rs b/crates/reflexo/src/concepts/takable.rs deleted file mode 100644 index 5bba52e1f..000000000 --- a/crates/reflexo/src/concepts/takable.rs +++ /dev/null @@ -1,17 +0,0 @@ -use std::sync::Arc; - -/// Trait for values being taken. -pub trait TakeAs { - /// Takes the inner value if there is exactly one strong reference and - /// clones it otherwise. - fn take(self) -> T; -} - -impl TakeAs for Arc { - fn take(self) -> T { - match Arc::try_unwrap(self) { - Ok(v) => v, - Err(rc) => (*rc).clone(), - } - } -} diff --git a/crates/reflexo/src/debug_loc.rs b/crates/reflexo/src/debug_loc.rs deleted file mode 100644 index d1f1ec334..000000000 --- a/crates/reflexo/src/debug_loc.rs +++ /dev/null @@ -1,174 +0,0 @@ -use core::fmt; - -use serde::{Deserialize, Serialize}; - -/// A serializable physical position in a document. -/// -/// Note that it uses [`f32`] instead of [`f64`] as same as -/// `TypstPosition` for the coordinates to improve both performance -/// of serialization and calculation. It does sacrifice the floating -/// precision, but it is enough in our use cases. -/// -/// Also see `TypstPosition`. -#[derive(Debug, Clone, Copy, Serialize, Deserialize)] -pub struct DocumentPosition { - /// The page, starting at 1. - pub page_no: usize, - /// The exact x-coordinate on the page (from the left, as usual). - pub x: f32, - /// The exact y-coordinate on the page (from the top, as usual). - pub y: f32, -} - -// impl From for DocumentPosition { -// fn from(position: TypstPosition) -> Self { -// Self { -// page_no: position.page.into(), -// x: position.point.x.to_pt() as f32, -// y: position.point.y.to_pt() as f32, -// } -// } -// } - -/// Raw representation of a source span. -pub type RawSourceSpan = u64; - -/// A resolved source (text) location. -/// -/// See [`CharPosition`] for the definition of the position inside a file. -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct FileLocation { - pub filepath: String, -} - -/// A char position represented in form of line and column. -/// The position is encoded in Utf-8 or Utf-16, and the encoding is -/// determined by usage. -#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq, Hash)] -pub struct CharPosition { - /// The line number, starting at 0. - pub line: usize, - /// The column number, starting at 0. - pub column: usize, -} - -impl fmt::Display for CharPosition { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}:{}", self.line, self.column) - } -} - -impl From> for CharPosition { - fn from(loc: Option<(usize, usize)>) -> Self { - let (start, end) = loc.unwrap_or_default(); - CharPosition { - line: start, - column: end, - } - } -} - -/// A resolved source (text) location. -/// -/// See [`CharPosition`] for the definition of the position inside a file. -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct SourceLocation { - pub filepath: String, - pub pos: CharPosition, -} - -impl SourceLocation { - pub fn from_flat( - flat: FlatSourceLocation, - i: &impl std::ops::Index, - ) -> Self { - Self { - filepath: i[flat.filepath as usize].filepath.clone(), - pos: flat.pos, - } - } -} - -/// A flat resolved source (text) location. -/// -/// See [`CharPosition`] for the definition of the position inside a file. -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct FlatSourceLocation { - pub filepath: u32, - pub pos: CharPosition, -} - -// /// A resolved file range. -// /// -// /// See [`CharPosition`] for the definition of the position inside a file. -#[derive(Debug, Clone, Serialize, Deserialize, Default)] -pub struct CharRange { - pub start: CharPosition, - pub end: CharPosition, -} - -impl fmt::Display for CharRange { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if self.start == self.end { - write!(f, "{}", self.start) - } else { - write!(f, "{}-{}", self.start, self.end) - } - } -} - -// /// A resolved source (text) range. -// /// -// /// See [`CharPosition`] for the definition of the position inside a file. -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct SourceRange { - pub path: String, - pub range: CharRange, -} - -/// A point on the element tree. -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct ElementPoint { - /// The element kind. - pub kind: u32, - /// The index of the element. - pub index: u32, - /// The fingerprint of the element. - pub fingerprint: String, -} - -impl From<(u32, u32, String)> for ElementPoint { - fn from((kind, index, fingerprint): (u32, u32, String)) -> Self { - Self { - kind, - index, - fingerprint, - } - } -} - -/// A file system data source. -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] -pub struct FsDataSource { - /// The name of the data source. - pub path: String, -} - -/// A in-memory data source. -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] -pub struct MemoryDataSource { - /// The name of the data source. - pub name: String, -} - -/// Data source for a document. -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] -#[serde(tag = "kind")] -pub enum DataSource { - /// File system data source. - #[serde(rename = "fs")] - Fs(FsDataSource), - /// Memory data source. - #[serde(rename = "memory")] - Memory(MemoryDataSource), -} diff --git a/crates/reflexo/src/error.rs b/crates/reflexo/src/error.rs deleted file mode 100644 index 33ada8534..000000000 --- a/crates/reflexo/src/error.rs +++ /dev/null @@ -1,327 +0,0 @@ -use core::fmt; - -use ecow::EcoString; -use serde::{Deserialize, Serialize}; - -use crate::debug_loc::CharRange; - -#[derive(serde_repr::Serialize_repr, serde_repr::Deserialize_repr, Debug, Clone)] -#[repr(u8)] -pub enum DiagSeverity { - Error = 1, - Warning = 2, - Information = 3, - Hint = 4, -} - -impl fmt::Display for DiagSeverity { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - DiagSeverity::Error => write!(f, "error"), - DiagSeverity::Warning => write!(f, "warning"), - DiagSeverity::Information => write!(f, "information"), - DiagSeverity::Hint => write!(f, "hint"), - } - } -} - -/// -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct DiagMessage { - pub package: String, - pub path: String, - pub message: String, - pub severity: DiagSeverity, - pub range: Option, - // These field could be added to ErrorImpl::arguments - // owner: Option, - // source: ImmutStr, -} - -impl DiagMessage {} - -#[derive(Debug, Clone)] -#[non_exhaustive] -pub enum ErrKind { - None, - Msg(String), - Diag(DiagMessage), - Inner(Error), -} - -pub trait ErrKindExt { - fn to_error_kind(self) -> ErrKind; -} - -impl ErrKindExt for ErrKind { - fn to_error_kind(self) -> Self { - self - } -} - -impl ErrKindExt for std::io::Error { - fn to_error_kind(self) -> ErrKind { - ErrKind::Msg(self.to_string()) - } -} - -impl ErrKindExt for String { - fn to_error_kind(self) -> ErrKind { - ErrKind::Msg(self) - } -} - -impl ErrKindExt for &str { - fn to_error_kind(self) -> ErrKind { - ErrKind::Msg(self.to_string()) - } -} - -impl ErrKindExt for &String { - fn to_error_kind(self) -> ErrKind { - ErrKind::Msg(self.to_string()) - } -} - -impl ErrKindExt for EcoString { - fn to_error_kind(self) -> ErrKind { - ErrKind::Msg(self.to_string()) - } -} - -impl ErrKindExt for &dyn std::fmt::Display { - fn to_error_kind(self) -> ErrKind { - ErrKind::Msg(self.to_string()) - } -} - -impl ErrKindExt for serde_json::Error { - fn to_error_kind(self) -> ErrKind { - ErrKind::Msg(self.to_string()) - } -} - -#[derive(Debug, Clone)] -pub struct ErrorImpl { - loc: &'static str, - kind: ErrKind, - arguments: Box<[(&'static str, String)]>, -} - -/// This type represents all possible errors that can occur in typst.ts -#[derive(Debug, Clone)] -pub struct Error { - /// This `Box` allows us to keep the size of `Error` as small as possible. A - /// larger `Error` type was substantially slower due to all the functions - /// that pass around `Result`. - err: Box, -} - -impl Error { - pub fn new(loc: &'static str, kind: ErrKind, arguments: Box<[(&'static str, String)]>) -> Self { - Self { - err: Box::new(ErrorImpl { - loc, - kind, - arguments, - }), - } - } - - pub fn loc(&self) -> &'static str { - self.err.loc - } - - pub fn kind(&self) -> &ErrKind { - &self.err.kind - } - - pub fn arguments(&self) -> &[(&'static str, String)] { - &self.err.arguments - } -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let err = &self.err; - match &err.kind { - ErrKind::Msg(msg) => write!(f, "{}: {} with {:?}", err.loc, msg, err.arguments), - ErrKind::Diag(diag) => { - write!(f, "{}: {} with {:?}", err.loc, diag.message, err.arguments) - } - ErrKind::Inner(e) => write!(f, "{}: {} with {:?}", err.loc, e, err.arguments), - ErrKind::None => write!(f, "{}: with {:?}", err.loc, err.arguments), - } - } -} - -impl std::error::Error for Error {} - -#[cfg(feature = "web")] -impl ErrKindExt for wasm_bindgen::JsValue { - fn to_error_kind(self) -> ErrKind { - ErrKind::Msg(format!("{:?}", self)) - } -} - -#[cfg(feature = "web")] -impl From for wasm_bindgen::JsValue { - fn from(e: Error) -> Self { - js_sys::Error::new(&e.to_string()).into() - } -} - -#[cfg(feature = "web")] -impl From<&Error> for wasm_bindgen::JsValue { - fn from(e: &Error) -> Self { - js_sys::Error::new(&e.to_string()).into() - } -} - -pub mod prelude { - - use super::ErrKindExt; - use crate::Error; - - pub type ZResult = Result; - - pub trait WithContext: Sized { - fn context(self, loc: &'static str) -> ZResult; - - fn with_context(self, loc: &'static str, f: F) -> ZResult - where - F: FnOnce() -> Box<[(&'static str, String)]>; - } - - impl WithContext for Result { - fn context(self, loc: &'static str) -> ZResult { - self.map_err(|e| Error::new(loc, e.to_error_kind(), Box::new([]))) - } - - fn with_context(self, loc: &'static str, f: F) -> ZResult - where - F: FnOnce() -> Box<[(&'static str, String)]>, - { - self.map_err(|e| Error::new(loc, e.to_error_kind(), f())) - } - } - - pub fn map_string_err(loc: &'static str) -> impl Fn(T) -> Error { - move |e| Error::new(loc, e.to_string().to_error_kind(), Box::new([])) - } - - pub fn map_into_err>(loc: &'static str) -> impl Fn(T) -> Error { - move |e| Error::new(loc, e.into().to_error_kind(), Box::new([])) - } - - pub fn map_err(loc: &'static str) -> impl Fn(T) -> Error { - move |e| Error::new(loc, e.to_error_kind(), Box::new([])) - } - - pub fn wrap_err(loc: &'static str) -> impl Fn(Error) -> Error { - move |e| Error::new(loc, crate::ErrKind::Inner(e), Box::new([])) - } - - pub fn map_string_err_with_args< - T: ToString, - Args: IntoIterator, - >( - loc: &'static str, - arguments: Args, - ) -> impl FnOnce(T) -> Error { - move |e| { - Error::new( - loc, - e.to_string().to_error_kind(), - arguments.into_iter().collect::>().into_boxed_slice(), - ) - } - } - - pub fn map_into_err_with_args< - S: ErrKindExt, - T: Into, - Args: IntoIterator, - >( - loc: &'static str, - arguments: Args, - ) -> impl FnOnce(T) -> Error { - move |e| { - Error::new( - loc, - e.into().to_error_kind(), - arguments.into_iter().collect::>().into_boxed_slice(), - ) - } - } - - pub fn map_err_with_args>( - loc: &'static str, - arguments: Args, - ) -> impl FnOnce(T) -> Error { - move |e| { - Error::new( - loc, - e.to_error_kind(), - arguments.into_iter().collect::>().into_boxed_slice(), - ) - } - } - - pub fn wrap_err_with_args>( - loc: &'static str, - arguments: Args, - ) -> impl FnOnce(Error) -> Error { - move |e| { - Error::new( - loc, - crate::ErrKind::Inner(e), - arguments.into_iter().collect::>().into_boxed_slice(), - ) - } - } - - pub fn _error_once(loc: &'static str, args: Box<[(&'static str, String)]>) -> Error { - Error::new(loc, crate::ErrKind::None, args) - } - - #[macro_export] - macro_rules! error_once { - ($loc:expr, $($arg_key:ident: $arg:expr),+ $(,)?) => { - _error_once($loc, Box::new([$((stringify!($arg_key), $arg.to_string())),+])) - }; - ($loc:expr $(,)?) => { - _error_once($loc, Box::new([])) - }; - } - - #[macro_export] - macro_rules! error_once_map { - ($loc:expr, $($arg_key:ident: $arg:expr),+ $(,)?) => { - map_err_with_args($loc, [$((stringify!($arg_key), $arg.to_string())),+]) - }; - ($loc:expr $(,)?) => { - map_err($loc) - }; - } - - #[macro_export] - macro_rules! error_once_map_string { - ($loc:expr, $($arg_key:ident: $arg:expr),+ $(,)?) => { - map_string_err_with_args($loc, [$((stringify!($arg_key), $arg.to_string())),+]) - }; - ($loc:expr $(,)?) => { - map_string_err($loc) - }; - } - - pub use error_once; - pub use error_once_map; - pub use error_once_map_string; -} - -#[test] -fn test_send() { - fn is_send() {} - is_send::(); -} diff --git a/crates/reflexo/src/hash.rs b/crates/reflexo/src/hash.rs deleted file mode 100644 index e0c624b58..000000000 --- a/crates/reflexo/src/hash.rs +++ /dev/null @@ -1,313 +0,0 @@ -use core::fmt; -use std::{ - any::Any, - hash::{Hash, Hasher}, -}; - -use base64::Engine; -use fxhash::FxHasher32; -use siphasher::sip128::{Hasher128, SipHasher13}; - -#[cfg(feature = "rkyv")] -use rkyv::{Archive, Deserialize as rDeser, Serialize as rSer}; - -use crate::error::prelude::ZResult; - -pub(crate) type FxBuildHasher = std::hash::BuildHasherDefault; -pub use rustc_hash::{FxHashMap, FxHashSet, FxHasher}; -// pub type FxIndexSet = indexmap::IndexSet; -// pub type FxIndexMap = indexmap::IndexMap; -pub type FxDashMap = dashmap::DashMap; - -/// See -/// The fingerprint conflicts should be very rare and should be handled by the -/// compiler. -/// -/// > That being said, given a high quality hash function, the collision -/// > probabilities in question are very small. For example, for a big crate -/// > like `rustc_middle` (with ~50000 `LocalDefId`s as of the time of writing) -/// > there is a probability of roughly 1 in 14,750,000,000 of a crate-internal -/// > collision occurring. For a big crate graph with 1000 crates in it, there -/// > is a probability of 1 in 36,890,000,000,000 of a `StableCrateId` -/// > collision. -#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] -#[cfg_attr(feature = "rkyv", derive(Archive, rDeser, rSer))] -#[cfg_attr(feature = "rkyv-validation", archive(check_bytes))] -pub struct Fingerprint { - lo: u64, - hi: u64, -} - -impl fmt::Debug for Fingerprint { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(&self.as_svg_id("fg")) - } -} - -impl serde::Serialize for Fingerprint { - fn serialize(&self, serializer: S) -> Result { - serializer.serialize_str(&self.as_svg_id("")) - } -} - -impl<'de> serde::Deserialize<'de> for Fingerprint { - fn deserialize>(deserializer: D) -> Result { - let s = ::deserialize(deserializer)?; - Fingerprint::try_from_str(&s).map_err(serde::de::Error::custom) - } -} - -impl Fingerprint { - /// Create a new fingerprint from the given pair of 64-bit integers. - pub fn from_pair(lo: u64, hi: u64) -> Self { - Self { lo, hi } - } - - /// Create a new fingerprint from the given 128-bit integer. - pub const fn from_u128(hash: u128) -> Self { - // Self(hash as u64, (hash >> 64) as u64) - Self { - lo: hash as u64, - hi: (hash >> 64) as u64, - } - } - - /// Get the fingerprint as a 128-bit integer. - pub fn to_u128(self) -> u128 { - ((self.hi as u128) << 64) | self.lo as u128 - } - - /// Cut the fingerprint into a 32-bit integer. - /// It could be used as a hash value if the fingerprint is calculated from a - /// stable hash function. - pub fn lower32(self) -> u32 { - self.lo as u32 - } - - /// Creates a new `Fingerprint` from a svg id that **doesn't have prefix**. - pub fn try_from_str(s: &str) -> ZResult { - let bytes = base64::engine::general_purpose::STANDARD_NO_PAD - .decode(&s.as_bytes()[..11]) - .expect("invalid base64 string"); - let lo = u64::from_le_bytes(bytes.try_into().unwrap()); - let mut bytes = base64::engine::general_purpose::STANDARD_NO_PAD - .decode(&s.as_bytes()[11..]) - .expect("invalid base64 string"); - bytes.resize(8, 0); - let hi = u64::from_le_bytes(bytes.try_into().unwrap()); - Ok(Self::from_pair(lo, hi)) - } - - /// Create a xml id from the given prefix and the fingerprint of this - /// reference. Note that the entire html document shares namespace for - /// ids. - #[comemo::memoize] - pub fn as_svg_id(self, prefix: &'static str) -> String { - let fingerprint_lo = - base64::engine::general_purpose::STANDARD_NO_PAD.encode(self.lo.to_le_bytes()); - if self.hi == 0 { - return [prefix, &fingerprint_lo].join(""); - } - - // possible the id in the lower 64 bits. - let fingerprint_hi = { - let id = self.hi.to_le_bytes(); - // truncate zero - let rev_zero = id.iter().rev().skip_while(|&&b| b == 0).count(); - let id = &id[..rev_zero]; - base64::engine::general_purpose::STANDARD_NO_PAD.encode(id) - }; - [prefix, &fingerprint_lo, &fingerprint_hi].join("") - } -} - -/// A fingerprint hasher that extends the [`std::hash::Hasher`] trait. -pub trait FingerprintHasher: std::hash::Hasher { - /// Finish the fingerprint and return the fingerprint and the data. - /// The data is used to resolve the conflict. - fn finish_fingerprint(self) -> (Fingerprint, Vec); -} - -/// A fingerprint hasher that uses the [`SipHasher13`] algorithm. -#[derive(Default)] -pub struct FingerprintSipHasher { - /// The underlying data passed to the hasher. - data: Vec, -} - -pub type FingerprintSipHasherBase = SipHasher13; - -impl FingerprintSipHasher { - pub fn fast_hash(&self) -> (u32, &Vec) { - let mut inner = FxHasher32::default(); - self.data.hash(&mut inner); - (inner.finish() as u32, &self.data) - } -} - -impl std::hash::Hasher for FingerprintSipHasher { - fn write(&mut self, bytes: &[u8]) { - self.data.extend_from_slice(bytes); - } - - fn finish(&self) -> u64 { - let mut inner = FingerprintSipHasherBase::default(); - self.data.hash(&mut inner); - inner.finish() - } -} - -impl FingerprintHasher for FingerprintSipHasher { - fn finish_fingerprint(self) -> (Fingerprint, Vec) { - let buffer = self.data.clone(); - let mut inner = FingerprintSipHasherBase::default(); - buffer.hash(&mut inner); - let hash = inner.finish128(); - ( - Fingerprint { - lo: hash.h1, - hi: hash.h2, - }, - buffer, - ) - } -} - -/// A fingerprint builder that produces unique fingerprint for each item. -/// It resolves the conflict by checking the underlying data. -/// See [`Fingerprint`] for more information. -#[derive(Default)] -pub struct FingerprintBuilder { - /// The fast conflict checker mapping fingerprints to their underlying data. - #[cfg(feature = "bi-hash")] - fast_conflict_checker: crate::adt::CHashMap>, - /// The conflict checker mapping fingerprints to their underlying data. - conflict_checker: crate::adt::CHashMap>, -} - -#[cfg(not(feature = "bi-hash"))] -impl FingerprintBuilder { - pub fn resolve_unchecked(&self, item: &T) -> Fingerprint { - let mut s = FingerprintSipHasher { data: Vec::new() }; - item.hash(&mut s); - let (fingerprint, _featured_data) = s.finish_fingerprint(); - fingerprint - } - - pub fn resolve(&self, item: &T) -> Fingerprint { - let mut s = FingerprintSipHasher { data: Vec::new() }; - item.type_id().hash(&mut s); - item.hash(&mut s); - - let (fingerprint, featured_data) = s.finish_fingerprint(); - let Some(prev_featured_data) = self.conflict_checker.get(&fingerprint) else { - self.conflict_checker.insert(fingerprint, featured_data); - return fingerprint; - }; - - if *prev_featured_data == *featured_data { - return fingerprint; - } - - // todo: soft error - panic!("Fingerprint conflict detected!"); - } -} - -#[cfg(feature = "bi-hash")] -impl FingerprintBuilder { - pub fn resolve_unchecked(&self, item: &T) -> Fingerprint { - let mut s = FingerprintSipHasher { data: Vec::new() }; - item.hash(&mut s); - let (fingerprint, featured_data) = s.fast_hash(); - let Some(prev_featured_data) = self.fast_conflict_checker.get(&fingerprint) else { - self.fast_conflict_checker.insert(fingerprint, s.data); - return Fingerprint::from_pair(fingerprint as u64, 0); - }; - - if *prev_featured_data == *featured_data { - return Fingerprint::from_pair(fingerprint as u64, 0); - } - - let (fingerprint, _featured_data) = s.finish_fingerprint(); - fingerprint - } - - pub fn resolve(&self, item: &T) -> Fingerprint { - let mut s = FingerprintSipHasher { data: Vec::new() }; - item.type_id().hash(&mut s); - item.hash(&mut s); - let (fingerprint, featured_data) = s.fast_hash(); - let Some(prev_featured_data) = self.fast_conflict_checker.get(&fingerprint) else { - self.fast_conflict_checker.insert(fingerprint, s.data); - return Fingerprint::from_pair(fingerprint as u64, 0); - }; - - if *prev_featured_data == *featured_data { - return Fingerprint::from_pair(fingerprint as u64, 0); - } - - let (fingerprint, featured_data) = s.finish_fingerprint(); - let Some(prev_featured_data) = self.conflict_checker.get(&fingerprint) else { - self.conflict_checker.insert(fingerprint, featured_data); - return fingerprint; - }; - - if *prev_featured_data == *featured_data { - return fingerprint; - } - - // todo: soft error - panic!("Fingerprint conflict detected!"); - } -} - -/// This function provides a hash function for items, which also includes a type -/// id as part of the hash. Note: This function is not stable across different -/// versions of typst-ts, so it is preferred to be always used in memory. -/// Currently, this function use [`SipHasher13`] as the underlying hash -/// algorithm. -pub fn item_hash128(item: &T) -> u128 { - // Also hash the TypeId because the type might be converted - // through an unsized coercion. - let mut state = SipHasher13::new(); - item.type_id().hash(&mut state); - item.hash(&mut state); - state.finish128().as_u128() -} - -/// Calculate a 128-bit siphash of a value. -/// Currently, this function use [`SipHasher13`] as the underlying hash -/// algorithm. -#[inline] -pub fn hash128(value: &T) -> u128 { - let mut state = SipHasher13::new(); - value.hash(&mut state); - state.finish128().as_u128() -} - -/// A convenience function for when you need a quick 64-bit hash. -#[inline] -pub fn hash64(v: &T) -> u64 { - let mut state = FxHasher::default(); - v.hash(&mut state); - state.finish() -} - -// todo: rustc hash doesn't have 32-bit hash -pub use fxhash::hash32; - -#[test] -fn test_fingerprint() { - let t = Fingerprint::from_pair(0, 1); - assert_eq!(Fingerprint::try_from_str(&t.as_svg_id("")).unwrap(), t); - - let t = Fingerprint::from_pair(1, 1); - assert_eq!(Fingerprint::try_from_str(&t.as_svg_id("")).unwrap(), t); - - let t = Fingerprint::from_pair(1, 0); - assert_eq!(Fingerprint::try_from_str(&t.as_svg_id("")).unwrap(), t); - - let t = Fingerprint::from_pair(0, 0); - assert_eq!(Fingerprint::try_from_str(&t.as_svg_id("")).unwrap(), t); -} diff --git a/crates/reflexo/src/lib.rs b/crates/reflexo/src/lib.rs index b0b57da3c..e614e3b4e 100644 --- a/crates/reflexo/src/lib.rs +++ b/crates/reflexo/src/lib.rs @@ -1,19 +1,7 @@ -pub mod adt; -pub mod debug_loc; -pub mod error; +// pub mod error; pub mod escape; -pub mod hash; -pub mod path; -pub mod time; -pub(crate) mod concepts; - -pub use concepts::*; - -pub use error::{ErrKind, Error}; - -#[cfg(feature = "typst")] -pub use reflexo_typst_shim as typst_shim; +pub use tinymist_std::*; pub mod vector { #[cfg(feature = "rkyv")] diff --git a/crates/reflexo/src/path.rs b/crates/reflexo/src/path.rs deleted file mode 100644 index 9f4a0bb3d..000000000 --- a/crates/reflexo/src/path.rs +++ /dev/null @@ -1,229 +0,0 @@ -use std::path::{Component, Path}; - -pub use path_clean::PathClean; - -/// Get the path cleaned as a unix-style string. -pub fn unix_slash(root: &Path) -> String { - let mut res = String::with_capacity(root.as_os_str().len()); - let mut parent_norm = false; - for comp in root.components() { - match comp { - Component::Prefix(p) => { - res.push_str(&p.as_os_str().to_string_lossy()); - parent_norm = false; - } - Component::RootDir => { - res.push('/'); - parent_norm = false; - } - Component::CurDir => { - parent_norm = false; - } - Component::ParentDir => { - if parent_norm { - res.push('/'); - } - res.push_str(".."); - parent_norm = true; - } - Component::Normal(p) => { - if parent_norm { - res.push('/'); - } - res.push_str(&p.to_string_lossy()); - parent_norm = true; - } - } - } - - if res.is_empty() { - res.push('.'); - } - - res -} - -/// Get the path cleaned as a platform-style string. -pub use path_clean::clean; - -#[cfg(test)] -mod test { - use std::path::{Path, PathBuf}; - - use super::{clean as inner_path_clean, unix_slash, PathClean}; - - pub fn clean>(path: P) -> String { - unix_slash(&inner_path_clean(path)) - } - - #[test] - fn test_unix_slash() { - if cfg!(target_os = "windows") { - // windows group - assert_eq!( - unix_slash(std::path::Path::new("C:\\Users\\a\\b\\c")), - "C:/Users/a/b/c" - ); - assert_eq!( - unix_slash(std::path::Path::new("C:\\Users\\a\\b\\c\\")), - "C:/Users/a/b/c" - ); - assert_eq!(unix_slash(std::path::Path::new("a\\b\\c")), "a/b/c"); - assert_eq!(unix_slash(std::path::Path::new("C:\\")), "C:/"); - assert_eq!(unix_slash(std::path::Path::new("C:\\\\")), "C:/"); - assert_eq!(unix_slash(std::path::Path::new("C:")), "C:"); - assert_eq!(unix_slash(std::path::Path::new("C:\\a")), "C:/a"); - assert_eq!(unix_slash(std::path::Path::new("C:\\a\\")), "C:/a"); - assert_eq!(unix_slash(std::path::Path::new("C:\\a\\b")), "C:/a/b"); - assert_eq!( - unix_slash(std::path::Path::new("C:\\Users\\a\\..\\b\\c")), - "C:/Users/a/../b/c" - ); - assert_eq!( - unix_slash(std::path::Path::new("C:\\Users\\a\\..\\b\\c\\")), - "C:/Users/a/../b/c" - ); - assert_eq!( - unix_slash(std::path::Path::new("C:\\Users\\a\\..\\..")), - "C:/Users/a/../.." - ); - assert_eq!( - unix_slash(std::path::Path::new("C:\\Users\\a\\..\\..\\")), - "C:/Users/a/../.." - ); - } - // unix group - assert_eq!(unix_slash(std::path::Path::new("/a/b/c")), "/a/b/c"); - assert_eq!(unix_slash(std::path::Path::new("/a/b/c/")), "/a/b/c"); - assert_eq!(unix_slash(std::path::Path::new("/")), "/"); - assert_eq!(unix_slash(std::path::Path::new("//")), "/"); - assert_eq!(unix_slash(std::path::Path::new("a")), "a"); - assert_eq!(unix_slash(std::path::Path::new("a/")), "a"); - assert_eq!(unix_slash(std::path::Path::new("a/b")), "a/b"); - assert_eq!(unix_slash(std::path::Path::new("a/b/")), "a/b"); - assert_eq!(unix_slash(std::path::Path::new("a/..")), "a/.."); - assert_eq!(unix_slash(std::path::Path::new("a/../")), "a/.."); - assert_eq!(unix_slash(std::path::Path::new("a/../..")), "a/../.."); - assert_eq!(unix_slash(std::path::Path::new("a/../../")), "a/../.."); - assert_eq!(unix_slash(std::path::Path::new("a/./b")), "a/b"); - assert_eq!(unix_slash(std::path::Path::new("a/./b/")), "a/b"); - assert_eq!(unix_slash(std::path::Path::new(".")), "."); - assert_eq!(unix_slash(std::path::Path::new("./")), "."); - assert_eq!(unix_slash(std::path::Path::new("./a")), "a"); - assert_eq!(unix_slash(std::path::Path::new("./a/")), "a"); - assert_eq!(unix_slash(std::path::Path::new("./a/b")), "a/b"); - assert_eq!(unix_slash(std::path::Path::new("./a/b/")), "a/b"); - assert_eq!(unix_slash(std::path::Path::new("./a/./b/")), "a/b"); - } - - #[test] - fn test_path_clean_empty_path_is_current_dir() { - assert_eq!(clean(""), "."); - } - - #[test] - fn test_path_clean_clean_paths_dont_change() { - let tests = vec![(".", "."), ("..", ".."), ("/", "/")]; - - for test in tests { - assert_eq!(clean(test.0), test.1); - } - } - - #[test] - fn test_path_clean_replace_multiple_slashes() { - let tests = vec![ - ("/", "/"), - ("//", "/"), - ("///", "/"), - (".//", "."), - ("//..", "/"), - ("..//", ".."), - ("/..//", "/"), - ("/.//./", "/"), - ("././/./", "."), - ("path//to///thing", "path/to/thing"), - ("/path//to///thing", "/path/to/thing"), - ]; - - for test in tests { - assert_eq!(clean(test.0), test.1); - } - } - - #[test] - fn test_path_clean_eliminate_current_dir() { - let tests = vec![ - ("./", "."), - ("/./", "/"), - ("./test", "test"), - ("./test/./path", "test/path"), - ("/test/./path/", "/test/path"), - ("test/path/.", "test/path"), - ]; - - for test in tests { - assert_eq!(clean(test.0), test.1); - } - } - - #[test] - fn test_path_clean_eliminate_parent_dir() { - let tests = vec![ - ("/..", "/"), - ("/../test", "/test"), - ("test/..", "."), - ("test/path/..", "test"), - ("test/../path", "path"), - ("/test/../path", "/path"), - ("test/path/../../", "."), - ("test/path/../../..", ".."), - ("/test/path/../../..", "/"), - ("/test/path/../../../..", "/"), - ("test/path/../../../..", "../.."), - ("test/path/../../another/path", "another/path"), - ("test/path/../../another/path/..", "another"), - ("../test", "../test"), - ("../test/", "../test"), - ("../test/path", "../test/path"), - ("../test/..", ".."), - ]; - - for test in tests { - assert_eq!(clean(test.0), test.1); - } - } - - #[test] - fn test_path_clean_pathbuf_trait() { - assert_eq!( - unix_slash(&PathBuf::from("/test/../path/").clean()), - "/path" - ); - } - - #[test] - fn test_path_clean_path_trait() { - assert_eq!(unix_slash(&Path::new("/test/../path/").clean()), "/path"); - } - - #[test] - #[cfg(target_os = "windows")] - fn test_path_clean_windows_paths() { - let tests = vec![ - ("\\..", "/"), - ("\\..\\test", "/test"), - ("test\\..", "."), - ("test\\path\\..\\..\\..", ".."), - ("test\\path/..\\../another\\path", "another/path"), // Mixed - ("test\\path\\my/path", "test/path/my/path"), // Mixed 2 - ("/dir\\../otherDir/test.json", "/otherDir/test.json"), // User example - ("c:\\test\\..", "c:/"), // issue #12 - ("c:/test/..", "c:/"), // issue #12 - ]; - - for test in tests { - assert_eq!(clean(test.0), test.1); - } - } -} diff --git a/crates/reflexo/src/time.rs b/crates/reflexo/src/time.rs deleted file mode 100644 index 0a439fe86..000000000 --- a/crates/reflexo/src/time.rs +++ /dev/null @@ -1,23 +0,0 @@ -pub use std::time::SystemTime as Time; -pub use web_time::Duration; -pub use web_time::Instant; - -/// Returns the current system time (UTC+0). -#[cfg(any(feature = "system", feature = "web"))] -pub fn now() -> Time { - #[cfg(not(all(target_family = "wasm", target_os = "unknown")))] - { - Time::now() - } - #[cfg(all(target_family = "wasm", target_os = "unknown"))] - { - use web_time::web::SystemTimeExt; - web_time::SystemTime::now().to_std() - } -} - -/// Returns a dummy time on environments that do not support time. -#[cfg(not(any(feature = "system", feature = "web")))] -pub fn now() -> Time { - Time::UNIX_EPOCH -} diff --git a/crates/reflexo/src/vector/incr.rs b/crates/reflexo/src/vector/incr.rs index 9df1e6809..864c5a8fa 100644 --- a/crates/reflexo/src/vector/incr.rs +++ b/crates/reflexo/src/vector/incr.rs @@ -62,7 +62,7 @@ impl IncrDocClient { } } -fn access_slice<'a, T>(v: &'a [T], idx: usize, kind: &'static str, pos: usize) -> ZResult<&'a T> { +fn access_slice<'a, T>(v: &'a [T], idx: usize, kind: &'static str, pos: usize) -> Result<&'a T> { v.get(idx).ok_or_else( || error_once!("out of bound access", pos: pos, kind: kind, idx: idx, actual: v.len()), ) @@ -94,7 +94,7 @@ impl<'a> IncrDocClientKern<'a> { } /// Get the source location of the given path. - pub fn source_span(&self, path: &[u32]) -> ZResult> { + pub fn source_span(&self, path: &[u32]) -> Result> { const SOURCE_MAPPING_TYPE_TEXT: u32 = 0; const SOURCE_MAPPING_TYPE_GROUP: u32 = 1; const SOURCE_MAPPING_TYPE_IMAGE: u32 = 2; diff --git a/crates/reflexo/src/vector/ir/layout.rs b/crates/reflexo/src/vector/ir/layout.rs index 415c2dbfa..4c12264d4 100644 --- a/crates/reflexo/src/vector/ir/layout.rs +++ b/crates/reflexo/src/vector/ir/layout.rs @@ -150,15 +150,15 @@ pub trait LayoutSelector { &self, kind: &str, layouts: &[(Scalar, LayoutRegionNode)], - ) -> ZResult; + ) -> Result; fn select_by_str( &self, kind: &str, layouts: &[(ImmutStr, LayoutRegionNode)], - ) -> ZResult; + ) -> Result; - fn resolve_indirect(&self, ind: usize) -> ZResult<&LayoutRegion> { + fn resolve_indirect(&self, ind: usize) -> Result<&LayoutRegion> { Err(error_once!( "LayoutSelector: unimplemented indirect layout selector", ind: ind, @@ -215,7 +215,7 @@ impl LayoutRegion { } } - pub fn by_selector(&self, selector: &impl LayoutSelector) -> ZResult { + pub fn by_selector(&self, selector: &impl LayoutSelector) -> Result { let mut t = Ok(self); loop { let next = match t? { @@ -357,7 +357,7 @@ impl LayoutSelector for LayoutSelectorExpr { &self, kind: &str, layouts: &[(Scalar, LayoutRegionNode)], - ) -> ZResult { + ) -> Result { let t = match self { LayoutSelectorExpr::Any | LayoutSelectorExpr::First => layouts.first(), LayoutSelectorExpr::Last => layouts.last(), @@ -386,7 +386,7 @@ impl LayoutSelector for LayoutSelectorExpr { &self, kind: &str, layouts: &[(ImmutStr, LayoutRegionNode)], - ) -> ZResult { + ) -> Result { let t = match self { LayoutSelectorExpr::Any | LayoutSelectorExpr::First => { layouts.first().map(|(_, v)| v.clone()) @@ -420,7 +420,7 @@ impl LayoutSelector for LayoutMappingSelector { &self, kind: &str, layouts: &[(Scalar, LayoutRegionNode)], - ) -> ZResult { + ) -> Result { self.selectors .get(kind) .unwrap_or(&LayoutSelectorExpr::Any) @@ -431,7 +431,7 @@ impl LayoutSelector for LayoutMappingSelector { &self, kind: &str, layouts: &[(ImmutStr, LayoutRegionNode)], - ) -> ZResult { + ) -> Result { self.selectors .get(kind) .unwrap_or(&LayoutSelectorExpr::Any) @@ -450,7 +450,7 @@ impl LayoutSelector for LayoutNestSelector<'_, T> { &self, kind: &str, layouts: &[(Scalar, LayoutRegionNode)], - ) -> ZResult { + ) -> Result { self.inner.select_by_scalar(kind, layouts) } @@ -458,11 +458,11 @@ impl LayoutSelector for LayoutNestSelector<'_, T> { &self, kind: &str, layouts: &[(ImmutStr, LayoutRegionNode)], - ) -> ZResult { + ) -> Result { self.inner.select_by_str(kind, layouts) } - fn resolve_indirect(&self, ind: usize) -> ZResult<&LayoutRegion> { + fn resolve_indirect(&self, ind: usize) -> Result<&LayoutRegion> { self.layouts .get(ind) .ok_or_else(|| error_once!("LayoutNestSelector: indirect layout not found", ind: ind)) diff --git a/crates/reflexo/src/vector/ir/module.rs b/crates/reflexo/src/vector/ir/module.rs index 051e4c224..227422fe9 100644 --- a/crates/reflexo/src/vector/ir/module.rs +++ b/crates/reflexo/src/vector/ir/module.rs @@ -143,6 +143,7 @@ pub struct ModuleView { impl ModuleView { /// See [`std::path::Path`] pub fn new + ?Sized>(m: &M) -> &Self { + // SAFETY: The std::path::Path does similar conversion and is safe. unsafe { &*(m.as_ref() as *const Module as *const ModuleView) } } } diff --git a/crates/reflexo/src/vector/ir/visualize.rs b/crates/reflexo/src/vector/ir/visualize.rs index bfa07df88..09558a088 100644 --- a/crates/reflexo/src/vector/ir/visualize.rs +++ b/crates/reflexo/src/vector/ir/visualize.rs @@ -1,5 +1,5 @@ use super::preludes::*; -use crate::StaticHash128; +use crate::hash::StaticHash128; /// Item representing an `` element. #[derive(Debug, Clone, Hash, PartialEq, Eq)] diff --git a/crates/reflexo/src/vector/vm.rs b/crates/reflexo/src/vector/vm.rs index 08f8e18b3..9f1306ddf 100644 --- a/crates/reflexo/src/vector/vm.rs +++ b/crates/reflexo/src/vector/vm.rs @@ -156,7 +156,7 @@ pub trait RenderVm<'m>: Sized + FontIndice<'m> { | ir::VecItem::Gradient(..) | ir::VecItem::Pattern(..) | ir::VecItem::None => { - panic!("FlatRenderVm.RenderFrame.UnknownItem {:?}", item) + panic!("FlatRenderVm.RenderFrame.UnknownItem {item:?}") } } } @@ -277,7 +277,7 @@ where | ir::VecItem::Gradient(..) | ir::VecItem::Pattern(..) | ir::VecItem::None => { - panic!("FlatRenderVm.RenderFrame.UnknownItem {:?}", next_item) + panic!("FlatRenderVm.RenderFrame.UnknownItem {next_item:?}") } } .into() diff --git a/fuzzers/incremental/src/main.rs b/fuzzers/incremental/src/main.rs index ca20048b7..e597a0430 100644 --- a/fuzzers/incremental/src/main.rs +++ b/fuzzers/incremental/src/main.rs @@ -58,7 +58,7 @@ pub fn test_compiler( std::fs::write("mutate_sequence.log", "").unwrap(); for i in 0..200 { - println!("Iteration {}", i); + eprintln!("Iteration {}", i); if cfg!(feature = "generate") { content.push_str(" #lorem(50)"); diff --git a/packages/compiler/Cargo.toml b/packages/compiler/Cargo.toml index 9de1be642..c6e460f35 100644 --- a/packages/compiler/Cargo.toml +++ b/packages/compiler/Cargo.toml @@ -59,3 +59,6 @@ no-content-hint = [ "reflexo-typst/no-content-hint", "reflexo-vec2svg/no-content-hint", ] + +[lints] +workspace = true diff --git a/packages/compiler/src/builder.rs b/packages/compiler/src/builder.rs index b2247f3fa..409222369 100644 --- a/packages/compiler/src/builder.rs +++ b/packages/compiler/src/builder.rs @@ -18,7 +18,7 @@ pub struct TypstCompilerBuilder { #[wasm_bindgen] impl TypstCompilerBuilder { #[wasm_bindgen(constructor)] - pub fn new() -> ZResult { + pub fn new() -> Result { console_error_panic_hook::set_once(); let mut res = Self { access_model: None, @@ -29,7 +29,7 @@ impl TypstCompilerBuilder { Ok(res) } - pub fn set_dummy_access_model(&mut self) -> ZResult<()> { + pub fn set_dummy_access_model(&mut self) -> Result<()> { self.access_model = Some(ProxyAccessModel { context: wasm_bindgen::JsValue::UNDEFINED, mtime_fn: js_sys::Function::new_no_args("return 0"), @@ -55,7 +55,7 @@ impl TypstCompilerBuilder { is_file_fn: js_sys::Function, real_path_fn: js_sys::Function, read_all_fn: js_sys::Function, - ) -> ZResult<()> { + ) -> Result<()> { self.access_model = Some(ProxyAccessModel { context, mtime_fn, @@ -71,7 +71,7 @@ impl TypstCompilerBuilder { &mut self, context: JsValue, real_resolve_fn: js_sys::Function, - ) -> ZResult<()> { + ) -> Result<()> { self.package_registry = Some(ProxyRegistry { context: ProxyContext::new(context), real_resolve_fn, @@ -81,17 +81,17 @@ impl TypstCompilerBuilder { } // 400 KB - pub async fn add_raw_font(&mut self, font_buffer: Uint8Array) -> ZResult<()> { + pub async fn add_raw_font(&mut self, font_buffer: Uint8Array) -> Result<()> { self.add_raw_font_internal(font_buffer.to_vec().into()); Ok(()) } // 100 KB - pub async fn add_web_fonts(&mut self, fonts: js_sys::Array) -> ZResult<()> { + pub async fn add_web_fonts(&mut self, fonts: js_sys::Array) -> Result<()> { self.searcher.add_web_fonts(fonts).await } - pub async fn add_glyph_pack(&mut self, _pack: JsValue) -> ZResult<()> { + pub async fn add_glyph_pack(&mut self, _pack: JsValue) -> Result<()> { self.searcher.add_glyph_pack().await } diff --git a/packages/compiler/src/lib.rs b/packages/compiler/src/lib.rs index 0aa0254ad..394b522b0 100644 --- a/packages/compiler/src/lib.rs +++ b/packages/compiler/src/lib.rs @@ -11,7 +11,7 @@ use std::{fmt::Write, path::Path, sync::Arc}; use error::TypstSourceDiagnostic; use font::cache::FontInfoCache; use js_sys::{Array, JsString, Uint32Array, Uint8Array}; -use reflexo_typst::error::{long_diag_from_std, prelude::*, DiagMessage}; +use reflexo_typst::error::{long_diag_from_std, DiagMessage}; use reflexo_typst::font::web::BrowserFontSearcher; use reflexo_typst::package::browser::ProxyRegistry; use reflexo_typst::parser::OffsetEncoding; @@ -58,10 +58,7 @@ impl fmt::Display for UnixFmt { f.write_char(':')?; if let Some(r) = self.0.range.as_ref() { - let mut r = r.clone(); - r.start.line += 1; - r.start.column += 1; - write!(f, "{}:", r.start)?; + write!(f, "{}:{}:", r.start.line + 1, r.start.character + 1)?; } write!(f, " {}: {}", self.0.severity, self.0.message) @@ -78,12 +75,17 @@ fn convert_diag( js_sys::Reflect::set(&obj, &"package".into(), &e.package.into()).unwrap(); js_sys::Reflect::set(&obj, &"path".into(), &e.path.into()).unwrap(); if let Some(range) = e.range { - js_sys::Reflect::set(&obj, &"range".into(), &range.to_string().into()).unwrap(); + let rng = format!( + "{}:{}-{}:{}", + range.start.line, range.start.character, range.end.line, range.end.character + ) + .into(); + js_sys::Reflect::set(&obj, &"range".into(), &rng).unwrap(); } else { js_sys::Reflect::set(&obj, &"range".into(), &"".into()).unwrap(); } js_sys::Reflect::set(&obj, &"severity".into(), &e.severity.to_string().into()).unwrap(); - js_sys::Reflect::set(&obj, &"message".into(), &e.message.into()).unwrap(); + js_sys::Reflect::set(&obj, &"message".into(), &e.message.as_str().into()).unwrap(); obj.into() } @@ -143,7 +145,7 @@ pub fn get_font_info(buffer: Uint8Array) -> JsValue { impl TypstCompiler { pub fn reset(&mut self) -> Result<(), JsValue> { // reset the world caches - self.driver.reset().map_err(|e| format!("{e:?}"))?; + self.driver.evict(30).map_err(|e| format!("{e:?}"))?; Ok(()) } diff --git a/packages/compiler/src/utils.rs b/packages/compiler/src/utils.rs index 9a743234f..b55245b98 100644 --- a/packages/compiler/src/utils.rs +++ b/packages/compiler/src/utils.rs @@ -12,7 +12,7 @@ macro_rules! console_log { #[allow(unused_macros)] macro_rules! console_log { ($($arg:tt)*) => { - println!( + eprintln!( $($arg)* ); } diff --git a/packages/parser/Cargo.toml b/packages/parser/Cargo.toml index 00d011e6f..7a6ea5aa8 100644 --- a/packages/parser/Cargo.toml +++ b/packages/parser/Cargo.toml @@ -40,3 +40,6 @@ web_test = ["typst-ts-test-common/web_artifacts"] full = ["web", "web_test"] web = [] default = ["full"] + +[lints] +workspace = true diff --git a/packages/parser/src/lib.rs b/packages/parser/src/lib.rs index 0aefda25c..9b1157a17 100644 --- a/packages/parser/src/lib.rs +++ b/packages/parser/src/lib.rs @@ -14,7 +14,7 @@ pub struct TypstParserBuilder {} #[wasm_bindgen] impl TypstParserBuilder { #[wasm_bindgen(constructor)] - pub fn new() -> ZResult { + pub fn new() -> Result { console_error_panic_hook::set_once(); Ok(Self {}) } @@ -53,7 +53,7 @@ impl TypstParser { &self, src: String, offset_encoding: String, - ) -> ZResult { + ) -> Result { let tokens = self.get_semantic_tokens_inner(src, match offset_encoding.as_str() { "utf-16" => OffsetEncoding::Utf16, "utf-8" => OffsetEncoding::Utf8, diff --git a/packages/renderer/Cargo.toml b/packages/renderer/Cargo.toml index 7cb9b8ff5..eaeb25910 100644 --- a/packages/renderer/Cargo.toml +++ b/packages/renderer/Cargo.toml @@ -104,3 +104,6 @@ no-content-hint = [ "reflexo-vec2dom/no-content-hint", "reflexo-vec2svg/no-content-hint", ] + +[lints] +workspace = true diff --git a/packages/renderer/src/builder/glyph_pack.rs b/packages/renderer/src/builder/glyph_pack.rs index 33bcdb08a..48cf45489 100644 --- a/packages/renderer/src/builder/glyph_pack.rs +++ b/packages/renderer/src/builder/glyph_pack.rs @@ -5,7 +5,7 @@ use crate::{TypstRenderer, TypstRendererBuilder}; #[wasm_bindgen] impl TypstRendererBuilder { - pub async fn add_glyph_pack(&mut self, pack: JsValue) -> ZResult<()> { + pub async fn add_glyph_pack(&mut self, pack: JsValue) -> Result<()> { let pack = serde_wasm_bindgen::from_value(pack).unwrap(); self.searcher.add_glyph_pack(pack).await } @@ -13,7 +13,7 @@ impl TypstRendererBuilder { #[wasm_bindgen] impl TypstRenderer { - pub fn load_glyph_pack(&self, v: JsValue) -> ZResult<()> { + pub fn load_glyph_pack(&self, v: JsValue) -> Result<()> { let mut font_resolver = self.session_mgr.font_resolver.write().unwrap(); font_resolver.add_glyph_packs( serde_wasm_bindgen::from_value(v).map_err(map_string_err("GlyphBundleFmt"))?, diff --git a/packages/renderer/src/builder/mod.rs b/packages/renderer/src/builder/mod.rs index 5124ae44c..868efc609 100644 --- a/packages/renderer/src/builder/mod.rs +++ b/packages/renderer/src/builder/mod.rs @@ -29,12 +29,12 @@ pub struct TypstRendererBuilder {} #[wasm_bindgen] impl TypstRendererBuilder { #[wasm_bindgen(constructor)] - pub fn new() -> ZResult { + pub fn new() -> Result { console_error_panic_hook::set_once(); Ok(Self {}) } - pub async fn build(self) -> ZResult { + pub async fn build(self) -> Result { Ok(TypstRenderer::new()) } } @@ -54,7 +54,7 @@ pub mod glyph_pack_stub { #[wasm_bindgen] impl TypstRendererBuilder { - pub async fn add_glyph_pack(&mut self, _pack: JsValue) -> ZResult<()> { + pub async fn add_glyph_pack(&mut self, _pack: JsValue) -> Result<()> { WARN_ONCE1.lock().unwrap().get_or_init(|| { web_sys::console::warn_1( &"[typst-ts-renderer]: build_glyph_pack feature is not enabled, calling TypstRendererBuilder::add_glyph_pack".into(), @@ -66,7 +66,7 @@ pub mod glyph_pack_stub { #[wasm_bindgen] impl TypstRenderer { - pub fn load_glyph_pack(&self, _v: JsValue) -> ZResult<()> { + pub fn load_glyph_pack(&self, _v: JsValue) -> Result<()> { WARN_ONCE2.lock().unwrap().get_or_init(|| { web_sys::console::warn_1( &"[typst-ts-renderer]: build_glyph_pack feature is not enabled, calling TypstRenderer::load_glyph_pack".into(), @@ -95,7 +95,7 @@ pub mod raw_font_stub { #[wasm_bindgen] impl TypstRendererBuilder { - pub async fn add_raw_font(&mut self, _font_buffer: js_sys::Uint8Array) -> ZResult<()> { + pub async fn add_raw_font(&mut self, _font_buffer: js_sys::Uint8Array) -> Result<()> { WARN_ONCE.lock().unwrap().get_or_init(|| { web_sys::console::warn_1( &"[typst-ts-renderer]: build_raw_font feature is not enabled".into(), @@ -123,7 +123,7 @@ pub mod web_font_stub { #[wasm_bindgen] impl TypstRendererBuilder { - pub async fn add_web_fonts(&mut self, _fonts: js_sys::Array) -> ZResult<()> { + pub async fn add_web_fonts(&mut self, _fonts: js_sys::Array) -> Result<()> { WARN_ONCE.lock().unwrap().get_or_init(|| { web_sys::console::warn_1( &"[typst-ts-renderer]: build_web_font feature is not enabled".into(), diff --git a/packages/renderer/src/builder/raw_font.rs b/packages/renderer/src/builder/raw_font.rs index 34ca148f3..dccfb6d07 100644 --- a/packages/renderer/src/builder/raw_font.rs +++ b/packages/renderer/src/builder/raw_font.rs @@ -6,7 +6,7 @@ use crate::TypstRendererBuilder; #[wasm_bindgen] impl TypstRendererBuilder { - pub async fn add_raw_font(&mut self, font_buffer: Uint8Array) -> ZResult<()> { + pub async fn add_raw_font(&mut self, font_buffer: Uint8Array) -> Result<()> { self.add_raw_font_internal(font_buffer.to_vec().into()); Ok(()) } diff --git a/packages/renderer/src/builder/web_font.rs b/packages/renderer/src/builder/web_font.rs index e92805073..e18eafd60 100644 --- a/packages/renderer/src/builder/web_font.rs +++ b/packages/renderer/src/builder/web_font.rs @@ -5,7 +5,7 @@ use crate::TypstRendererBuilder; #[wasm_bindgen] impl TypstRendererBuilder { - pub async fn add_web_fonts(&mut self, font: js_sys::Array) -> ZResult<()> { + pub async fn add_web_fonts(&mut self, font: js_sys::Array) -> Result<()> { self.searcher.add_web_fonts(font).await } } diff --git a/packages/renderer/src/lib.rs b/packages/renderer/src/lib.rs index 8c17b7352..a0db72d22 100644 --- a/packages/renderer/src/lib.rs +++ b/packages/renderer/src/lib.rs @@ -171,7 +171,7 @@ impl TypstRenderer { Self {} } - pub fn create_session(&self, options: Option) -> ZResult { + pub fn create_session(&self, options: Option) -> Result { match options { Some(options) => { let format = options.format.as_deref().unwrap_or("vector"); @@ -187,7 +187,7 @@ impl TypstRenderer { } } - pub fn reset(&mut self, session: &mut RenderSession) -> ZResult<()> { + pub fn reset(&mut self, session: &mut RenderSession) -> Result<()> { session.reset(); Ok(()) } @@ -197,7 +197,7 @@ impl TypstRenderer { session: &mut RenderSession, action: &str, data: &[u8], - ) -> ZResult<()> { + ) -> Result<()> { match action { "reset" => session.reset_current(data), "merge" => session.merge_delta(data), @@ -209,7 +209,7 @@ impl TypstRenderer { &self, artifact_content: &[u8], decoder: &str, - ) -> ZResult { + ) -> Result { if decoder == "vector" { return self.session_from_vector_artifact(artifact_content); } @@ -221,7 +221,7 @@ impl TypstRenderer { Err(error_once!("Renderer.UnsupportedDecoder", decoder: decoder)) } - fn session_from_vector_artifact(&self, artifact_content: &[u8]) -> ZResult { + fn session_from_vector_artifact(&self, artifact_content: &[u8]) -> Result { let mut session = RenderSession::default(); session.reset_current(artifact_content)?; Ok(session) @@ -244,11 +244,11 @@ pub mod canvas_stub { #[wasm_bindgen] impl TypstRenderer { - pub async fn create_worker(&mut self, _w: JsValue) -> ZResult { + pub async fn create_worker(&mut self, _w: JsValue) -> Result { Err(error_once!("Renderer.WorkerFeatureNotEnabled")) } - pub fn create_worker_bridge(self) -> ZResult { + pub fn create_worker_bridge(self) -> Result { Err(error_once!("Renderer.WorkerFeatureNotEnabled")) } } @@ -261,7 +261,7 @@ pub mod canvas_stub { #[wasm_bindgen] impl TypstWorker { - pub fn manipulate_data(&mut self, _action: &str, _data: Uint8Array) -> ZResult { + pub fn manipulate_data(&mut self, _action: &str, _data: Uint8Array) -> Result { Err(error_once!("Renderer.WorkerFeatureNotEnabled")) } @@ -274,7 +274,7 @@ pub mod canvas_stub { _actions: Vec, _canvas_list: Vec, _data: Vec, - ) -> ZResult { + ) -> Result { Err(error_once!("Renderer.WorkerFeatureNotEnabled")) } } diff --git a/packages/renderer/src/render/canvas.rs b/packages/renderer/src/render/canvas.rs index 040c58e67..c04d52c82 100644 --- a/packages/renderer/src/render/canvas.rs +++ b/packages/renderer/src/render/canvas.rs @@ -18,7 +18,7 @@ impl TypstRenderer { ses: &RenderSession, canvas: JsValue, options: Option, - ) -> ZResult { + ) -> Result { let canvas = canvas.as_ref(); let canvas = if canvas == &JsValue::NULL { None @@ -54,7 +54,7 @@ impl TypstRenderer { ses: &RenderSession, canvas: Option<&dyn CanvasDevice>, options: Option, - ) -> ZResult<(Fingerprint, JsValue, Option>)> { + ) -> Result<(Fingerprint, JsValue, Option>)> { let opts = options.unwrap_or_default(); let rect_lo_x: f32 = -1.; let rect_lo_y: f32 = -1.; diff --git a/packages/renderer/src/render/mod.rs b/packages/renderer/src/render/mod.rs index 97656ad37..727428df8 100644 --- a/packages/renderer/src/render/mod.rs +++ b/packages/renderer/src/render/mod.rs @@ -27,7 +27,7 @@ pub mod canvas_stub { _ses: &RenderSession, _canvas: &JsValue, _options: Option, - ) -> ZResult { + ) -> Result { Err(error_once!("Renderer.CanvasFeatureNotEnabled")) } } diff --git a/packages/renderer/src/render/pdf.rs b/packages/renderer/src/render/pdf.rs index 66142d6aa..8abfe6d31 100644 --- a/packages/renderer/src/render/pdf.rs +++ b/packages/renderer/src/render/pdf.rs @@ -6,12 +6,12 @@ use crate::{RenderSession, TypstRenderer}; #[wasm_bindgen] impl TypstRenderer { - pub fn render_to_pdf(&mut self, artifact_content: &[u8]) -> ZResult { + pub fn render_to_pdf(&mut self, artifact_content: &[u8]) -> Result { let session = self.session_from_vector_artifact(artifact_content)?; self.render_to_pdf_in_session(&session) } - pub fn render_to_pdf_in_session(&mut self, session: &RenderSession) -> ZResult { + pub fn render_to_pdf_in_session(&mut self, session: &RenderSession) -> Result { Ok(Uint8Array::from( self.render_to_pdf_internal(session)?.as_slice(), )) @@ -19,7 +19,7 @@ impl TypstRenderer { } impl TypstRenderer { - pub fn render_to_pdf_internal(&self, _session: &RenderSession) -> ZResult> { + pub fn render_to_pdf_internal(&self, _session: &RenderSession) -> Result> { // contribution 510KB // Ok(typst::export::pdf(&session.doc)) Err(error_once!("Renderer.PdfFeatureNotEnabled")) diff --git a/packages/renderer/src/render/svg.rs b/packages/renderer/src/render/svg.rs index 8ef015c19..765048d46 100644 --- a/packages/renderer/src/render/svg.rs +++ b/packages/renderer/src/render/svg.rs @@ -43,7 +43,7 @@ impl TypstRenderer { session.render_in_window(rect_lo_x, rect_lo_y, rect_hi_x, rect_hi_y) } - pub fn svg_data(&mut self, session: &mut RenderSession, parts: Option) -> ZResult { + pub fn svg_data(&mut self, session: &mut RenderSession, parts: Option) -> Result { type UsingExporter = SvgExporter; let client = session.client.lock().unwrap(); @@ -81,7 +81,7 @@ impl TypstRenderer { }) } - pub fn render_svg(&self, session: &RenderSession, root: web_sys::HtmlElement) -> ZResult { + pub fn render_svg(&self, session: &RenderSession, root: web_sys::HtmlElement) -> Result { type UsingExporter = SvgExporter; // todo: leaking abstraction let mut client = session.client.lock().unwrap(); diff --git a/packages/renderer/src/session.rs b/packages/renderer/src/session.rs index 7b93e7ea6..56d2289df 100644 --- a/packages/renderer/src/session.rs +++ b/packages/renderer/src/session.rs @@ -226,7 +226,7 @@ impl RenderSession { self.client().kern().doc_height().unwrap_or_default() } - pub fn source_span(&self, path: &[u32]) -> ZResult> { + pub fn source_span(&self, path: &[u32]) -> Result> { self.client().kern().source_span(path) } @@ -243,7 +243,7 @@ impl RenderSession { } } - pub(crate) fn reset_current(&mut self, delta: &[u8]) -> ZResult<()> { + pub(crate) fn reset_current(&mut self, delta: &[u8]) -> Result<()> { let mut client = self.client.lock().unwrap(); *client = IncrDocClient::default(); if cfg!(feature = "render_canvas") { @@ -257,7 +257,7 @@ impl RenderSession { Self::merge_delta_inner(&mut self.pages_info, &mut client, delta) } - pub(crate) fn merge_delta(&mut self, delta: &[u8]) -> ZResult<()> { + pub(crate) fn merge_delta(&mut self, delta: &[u8]) -> Result<()> { let mut client = self.client.lock().unwrap(); Self::merge_delta_inner(&mut self.pages_info, &mut client, delta) } @@ -266,7 +266,7 @@ impl RenderSession { pages_info: &mut PagesInfo, client: &mut IncrDocClient, delta: &[u8], - ) -> ZResult<()> { + ) -> Result<()> { use reflexo_typst2vec::stream::BytesModuleStream; let delta = BytesModuleStream::from_slice(delta).checkout_owned(); diff --git a/packages/renderer/src/utils.rs b/packages/renderer/src/utils.rs index 9a743234f..b55245b98 100644 --- a/packages/renderer/src/utils.rs +++ b/packages/renderer/src/utils.rs @@ -12,7 +12,7 @@ macro_rules! console_log { #[allow(unused_macros)] macro_rules! console_log { ($($arg:tt)*) => { - println!( + eprintln!( $($arg)* ); } diff --git a/packages/renderer/src/worker.rs b/packages/renderer/src/worker.rs index 14286f06e..50fc04eea 100644 --- a/packages/renderer/src/worker.rs +++ b/packages/renderer/src/worker.rs @@ -24,14 +24,14 @@ use crate::{ #[wasm_bindgen] impl TypstRenderer { - pub async fn create_worker(&mut self, w: web_sys::Worker) -> ZResult { + pub async fn create_worker(&mut self, w: web_sys::Worker) -> Result { let core = create_worker(w); #[allow(clippy::arc_with_non_send_sync)] let rs = Arc::new(core.create_session(None).await?); Ok(TypstWorker { core, rs }) } - pub fn create_worker_bridge(self) -> ZResult { + pub fn create_worker_bridge(self) -> Result { Ok(WorkerBridge { plugin: self, ..Default::default() @@ -68,7 +68,7 @@ pub struct TypstWorker { #[wasm_bindgen] impl TypstWorker { - pub fn manipulate_data(&mut self, action: &str, data: Uint8Array) -> ZResult { + pub fn manipulate_data(&mut self, action: &str, data: Uint8Array) -> Result { let resp = self.core.send_with( Request::ManipulateData(self.rs.session_info, action.to_string()), data.into(), @@ -87,7 +87,7 @@ impl TypstWorker { actions: Vec, canvas_list: Vec, data: Vec, - ) -> ZResult { + ) -> Result { if actions.len() != data.len() || canvas_list.len() != data.len() { return Err(error_once!("Renderer.InvalidActionDataLength")); } @@ -333,7 +333,7 @@ impl WorkerCore { pub async fn create_session( self: &Arc, opts: Option, - ) -> ZResult { + ) -> Result { let req = Request::CreateSession(opts); let res = self.request(req).await; @@ -349,7 +349,7 @@ impl WorkerCore { ses: Arc, canvas: Option<&web_sys::HtmlCanvasElement>, options: Option, - ) -> ZResult<(Fingerprint, JsValue, Option>)> { + ) -> Result<(Fingerprint, JsValue, Option>)> { let canvas = canvas.map(|x| x.transfer_control_to_offscreen().unwrap()); self.clone() .render_page_to_canvas_internal(ses.clone(), canvas, options) @@ -361,7 +361,7 @@ impl WorkerCore { ses: Arc, canvas: Option, options: Option, - ) -> ZResult<(Fingerprint, JsValue, Option>)> { + ) -> Result<(Fingerprint, JsValue, Option>)> { let res = self .request_with( Request::RenderPageToCanvas(ses.session_info, options), diff --git a/packages/typst.node/Cargo.toml b/packages/typst.node/Cargo.toml index 48e608434..9383ad7e6 100644 --- a/packages/typst.node/Cargo.toml +++ b/packages/typst.node/Cargo.toml @@ -34,3 +34,6 @@ napi-build = "2" pdf = ["reflexo-typst/pdf"] svg = ["reflexo-vec2svg", "reflexo-vec2svg/experimental-ligature"] default = ["pdf", "svg"] + +[lints] +workspace = true diff --git a/packages/typst.node/src/compiler/boxed.rs b/packages/typst.node/src/compiler/boxed.rs index 2b9d2627a..6b4d7d51b 100644 --- a/packages/typst.node/src/compiler/boxed.rs +++ b/packages/typst.node/src/compiler/boxed.rs @@ -69,14 +69,13 @@ impl BoxedCompiler { let new_entry = universe .entry_state() - .select_in_workspace(*MEMORY_MAIN_ENTRY); + .select_in_workspace(MEMORY_MAIN_ENTRY.vpath().as_rooted_path()); + + let main_id = new_entry.main().unwrap(); let content = Bytes::from(main_file_content.as_bytes()); // TODO: eliminate the side effect of shadow mapping safely - if let Err(err) = self - .universe_mut() - .map_shadow_by_id(*MEMORY_MAIN_ENTRY, content) - { + if let Err(err) = self.universe_mut().map_shadow_by_id(main_id, content) { return Err(map_node_error(error_once!("cannot map shadow", err: err))); } @@ -94,7 +93,7 @@ impl BoxedCompiler { })?; universe .entry_state() - .try_select_path_in_workspace(fp, true) + .try_select_path_in_workspace(fp) .map_err(map_node_error)? } else { None @@ -134,11 +133,6 @@ impl BoxedCompiler { impl Compiler for BoxedCompiler { type W = TypstSystemWorld; - #[inline] - fn reset(&mut self) -> SourceResult<()> { - self.0.reset() - } - #[inline] fn pure_compile( &mut self, diff --git a/packages/typst.node/src/compiler/mod.rs b/packages/typst.node/src/compiler/mod.rs index 62efc3397..a74cac75e 100644 --- a/packages/typst.node/src/compiler/mod.rs +++ b/packages/typst.node/src/compiler/mod.rs @@ -2,13 +2,14 @@ pub mod boxed; pub use boxed::{BoxedCompiler, NodeCompilerTrait}; +use reflexo_typst::package::RegistryPathMapper; use std::{borrow::Cow, collections::HashMap, path::Path, sync::Arc}; use napi::{bindgen_prelude::*, Either}; use napi_derive::napi; use reflexo_typst::config::{entry::EntryState, CompileFontOpts}; -use reflexo_typst::error::prelude::*; +use reflexo_typst::error::prelude::{Result as ZResult, WithContext}; use reflexo_typst::font::system::SystemFontSearcher; use reflexo_typst::package::http::HttpRegistry; use reflexo_typst::typst::{foundations::IntoValue, LazyHash}; @@ -121,11 +122,13 @@ pub fn create_driver( ..CompileFontOpts::default() })?; + let registry = Arc::new(HttpRegistry::default()); + let resolver = Arc::new(RegistryPathMapper::new(registry.clone())); let world = TypstSystemUniverse::new_raw( EntryState::new_rooted(workspace_dir.into(), None), args.inputs.map(create_inputs), - Vfs::new(SystemAccessModel {}), - HttpRegistry::default(), + Vfs::new(resolver, SystemAccessModel {}), + registry, Arc::new(searcher.into()), ); diff --git a/packages/typst.node/src/lib.rs b/packages/typst.node/src/lib.rs index 5e86b896f..fbf8d0811 100644 --- a/packages/typst.node/src/lib.rs +++ b/packages/typst.node/src/lib.rs @@ -17,10 +17,10 @@ use std::{ use chrono::{DateTime, Datelike, Timelike, Utc}; use napi::bindgen_prelude::*; use napi_derive::napi; -use reflexo_typst::error::prelude::*; -use reflexo_typst::foundations::IntoValue; -use reflexo_typst::syntax::Span; +// use reflexo_typst::error::prelude::*; use reflexo_typst::typst::diag::{At, SourceResult}; +use reflexo_typst::{error::WithContext, foundations::IntoValue}; +use reflexo_typst::{error_once, syntax::Span}; use reflexo_typst::{ Bytes, Compiler, DynamicLayoutCompiler, Exporter, ShadowApi, SystemCompilerFeat, TypstAbs, TypstDatetime, TypstDocument, TypstSystemWorld, TypstWorld, @@ -215,8 +215,10 @@ impl NodeCompiler { /// A suggested `max_age` value for regular non-watch tools is `10`. /// A suggested `max_age` value for regular watch tools is `30`. #[napi] - pub fn evict_cache(&self, max_age: u32) { - comemo::evict(usize::try_from(max_age).unwrap()) + pub fn evict_cache(&mut self, max_age: u32) { + let max_age = usize::try_from(max_age).unwrap(); + comemo::evict(max_age); + let _ = self.driver.assert_mut().evict(max_age); } /// Adds a source file to the compiler. diff --git a/scripts/publish.py b/scripts/publish.py index 8a4631c11..940df56d1 100644 --- a/scripts/publish.py +++ b/scripts/publish.py @@ -5,10 +5,7 @@ pub = ["cargo", "publish", *sys.argv[1:], "-p"] feats = ["--features", "no-content-hint"] -subprocess.run([*pub, "reflexo-typst-shim"]) subprocess.run([*pub, "reflexo"]) -subprocess.run([*pub, "reflexo-vfs"]) -subprocess.run([*pub, "reflexo-world"]) subprocess.run([*pub, "reflexo-typst2vec", *feats]) subprocess.run([*pub, "reflexo-vec2bbox"]) subprocess.run([*pub, "reflexo-vec2canvas"]) diff --git a/server/dev/src/main.rs b/server/dev/src/main.rs index d204352b6..90e339de6 100644 --- a/server/dev/src/main.rs +++ b/server/dev/src/main.rs @@ -185,14 +185,14 @@ async fn watch(watch_sub: WatchSubCommands) { continue; }; - println!("{}: {}", grp, line); + eprintln!("{}: {}", grp, line); } Ok(line) = stderr.next_line() => { let Some(line) = line else { continue; }; - println!("{}: {}", grp, line); + eprintln!("{}: {}", grp, line); } else => { return Ok(()); @@ -202,7 +202,7 @@ async fn watch(watch_sub: WatchSubCommands) { } let _ = watch_stream(child, grp).await; - println!("{}: exited", grp); + eprintln!("{}: exited", grp); std::process::exit(0); })); } diff --git a/tests/common/Cargo.toml b/tests/common/Cargo.toml index 839338b26..41b032c99 100644 --- a/tests/common/Cargo.toml +++ b/tests/common/Cargo.toml @@ -32,3 +32,6 @@ web_artifacts = [ "dep:web-sys", ] default = [] + +[lints] +workspace = true diff --git a/tests/common/src/web_artifact.rs b/tests/common/src/web_artifact.rs index 65b21e980..52366ccc9 100644 --- a/tests/common/src/web_artifact.rs +++ b/tests/common/src/web_artifact.rs @@ -8,7 +8,7 @@ pub async fn get_corpus(corpus: String) -> Result opts.set_method("GET"); opts.set_mode(RequestMode::Cors); - let url = format!("http://127.0.0.1:20810/corpus/{}", corpus); + let url = format!("http://127.0.0.1:20810/corpus/{corpus}"); let request = Request::new_with_str_and_init(&url, &opts)?; diff --git a/tests/heap-profile/src/lib.rs b/tests/heap-profile/src/lib.rs index 02c58e39a..1173ee62e 100644 --- a/tests/heap-profile/src/lib.rs +++ b/tests/heap-profile/src/lib.rs @@ -32,7 +32,7 @@ pub fn test_compiler( let mut content = { std::fs::read_to_string(entry_file_path).expect("Could not read file") }; for i in 0..200 { - println!("Iteration {}", i); + eprintln!("Iteration {}", i); content.push_str(" user edit"); diff --git a/tests/incremental/src/main.rs b/tests/incremental/src/main.rs index 2cc4ca435..74f69a0fd 100644 --- a/tests/incremental/src/main.rs +++ b/tests/incremental/src/main.rs @@ -67,7 +67,7 @@ pub fn test_compiler( let _ = incr_svg_client.render_in_window(&mut incr_client, window); for i in 0..20 { - println!("Iteration {}", i); + eprintln!("Iteration {}", i); // content = content.replace("@netwok2020", "@netwok2020 x"); content += "\n\nx"; @@ -90,7 +90,7 @@ pub fn test_compiler( comemo::evict(10); } - println!("diff: {:?}", diff); + eprintln!("diff: {:?}", diff); } pub fn main() { @@ -111,7 +111,7 @@ pub fn main() { // workspace_dir.join(r#"masterproef/main.typ"#); for i in 0..10 { - println!("Over Iteration {}", i); + eprintln!("Over Iteration {}", i); let noop_exporter = GroupExporter::new(vec![]); test_compiler(&workspace_dir, &entry_file_path, noop_exporter); } diff --git a/tests/integration/src/tests.rs b/tests/integration/src/tests.rs index 1100dc035..5a1365bb3 100644 --- a/tests/integration/src/tests.rs +++ b/tests/integration/src/tests.rs @@ -405,9 +405,9 @@ mod tests { } } - println!("::group::Output of wasm-pack test"); - println!("{}", rest_contents.join("\n")); - println!("::endgroup::"); + eprintln!("::group::Output of wasm-pack test"); + eprintln!("{}", rest_contents.join("\n")); + eprintln!("::endgroup::"); let mut grouped_test_points = { let mut grouped_test_points = HashMap::new(); @@ -449,7 +449,7 @@ mod tests { // check canvas_render_test_points let canvas_render_test_points = grouped_test_points.remove("canvas_render_test").unwrap(); - println!( + eprintln!( "canvas_render_test_points: {:?}", canvas_render_test_points.len() ); diff --git a/tests/integration/src/wasm.rs b/tests/integration/src/wasm.rs index 5494d95b3..1c8d8e51d 100644 --- a/tests/integration/src/wasm.rs +++ b/tests/integration/src/wasm.rs @@ -46,7 +46,7 @@ pub async fn wasm_pack_test( // env: TYPST_CHROME_DRIVER if let Ok(chrome_driver) = std::env::var("TYPST_CHROME_DRIVER") { - println!("wasm-pack test Using ChromeDriver: {}", chrome_driver); + eprintln!("wasm-pack test Using ChromeDriver: {}", chrome_driver); cmd.arg("--chromedriver").arg(chrome_driver); } diff --git a/tests/std/src/main.rs b/tests/std/src/main.rs index 7a413e6ab..5ea40230b 100644 --- a/tests/std/src/main.rs +++ b/tests/std/src/main.rs @@ -40,7 +40,7 @@ fn main() -> anyhow::Result<()> { Some(src_path) }) .flat_map(|src_path| -> anyhow::Result> { - // println!("src_path={}", src_path.display()); + // eprintln!("src_path={}", src_path.display()); // read source let text = std::fs::read_to_string(&src_path)?; @@ -84,7 +84,7 @@ fn main() -> anyhow::Result<()> { for (i, part) in parts.iter().enumerate() { let file_name = rewrite_path.file_stem().unwrap().to_string_lossy(); let file_name = format!("{file_name}_{i:02}"); - println!("scanned {cat:10} {file_name}..."); + eprintln!("scanned {cat:10} {file_name}..."); let rewrite_path = rewrite_path.with_file_name(format!("{file_name}.typ")); diff --git a/tools/rkyv-assertions/src/main.rs b/tools/rkyv-assertions/src/main.rs index 0d409e38f..4edcc6396 100644 --- a/tools/rkyv-assertions/src/main.rs +++ b/tools/rkyv-assertions/src/main.rs @@ -5,8 +5,8 @@ macro_rules! layout { $(layout!(@one $prim);)* }; (@one $prim:ty) => {{ - println!("const _: () = assert!(core::mem::size_of::<{}>() == {});", stringify!($prim), core::mem::size_of::<$prim>()); - println!("const _: () = assert!(core::mem::align_of::<{}>() == {});", stringify!($prim), core::mem::align_of::<$prim>()); + eprintln!("const _: () = assert!(core::mem::size_of::<{}>() == {});", stringify!($prim), core::mem::size_of::<$prim>()); + eprintln!("const _: () = assert!(core::mem::align_of::<{}>() == {});", stringify!($prim), core::mem::align_of::<$prim>()); }}; }