Files
craft-libs/Cargo.toml
T
Dylan M. Taylor 26b36b4f9e Add craft-fig: the .fig container, read and written (#905)
* Add craft-kiwi: the kiwi binary schema format, decoded and encoded

The generic kiwi decoder and encoder from FigCraft's .fig import and export
(crates/format/src/fig/kiwi.rs at 3b9bf8c9), moved as it is: binary schema
decode and encode, the compact text form of a schema, message decode into a
tree keyed by field name, and message encode checked against the schema.

The value budget that follows a .fig file's compressed size stays with the
.fig reader; here decode_message_within takes the budget and
DEFAULT_MAX_VALUES is the floor FigCraft used.

* Add craft-fig: the .fig container, read and written

The app-independent half of FigCraft's .fig import and export
(crates/format/src/fig at 3b9bf8c9): the ZIP archive with its image
budget, the chunked canvas (deflate, zlib and zstd chunks), the value
budget that follows the compressed canvas, images carried in the
message's blobs, and the vector network and geometry blob encodings.
The message stays a craft-kiwi tree read by field name; mapping it onto
a document stays in the app.

* craft-kiwi: no scan per field in schema decode; the text form keeps the limits

Schema::decode compared each message field id with every earlier one: 20
definitions of 10 000 fields, within every cap, took a billion
comparisons. A set per definition now.

Schema::parse applies the definition and field caps of the binary form,
looks type names up in an index instead of scanning the lines per field,
accepts a struct or message without fields, and refuses two fields of one
name and a message field id that is 0 (it ends a message) or repeated.
2026-11-11 18:08:28 -05:00

157 lines
7.6 KiB
TOML

[workspace]
resolver = "3"
members = ["crates/*"]
exclude = ["vendor/krilla", "vendor/hayro", "vendor/hayro-interpret", "vendor/hayro-syntax", "vendor/hayro-jbig2", "vendor/hayro-cmap", "vendor/hayro-postscript", "vendor/linesweeper"]
[workspace.package]
version = "0.1.0"
edition = "2024"
license = "MIT OR Apache-2.0"
rust-version = "1.95"
repository = "https://github.com/storytold/craft-libs"
[workspace.dependencies]
# internal: add each crate here as `craft-<name> = { path = "crates/<name>" }`
craft-platform = { path = "crates/platform" }
craft-aep = { path = "crates/aep" }
craft-affinity = { path = "crates/affinity" }
craft-ai-core = { path = "crates/ai-core" }
craft-pdf = { path = "crates/pdf", version = "=0.1.0" }
craft-plate-test = { path = "crates/plate-test" }
krilla = { version = "=0.8.2", default-features = false, features = ["raster-images"] }
hayro = { version = "=0.7.1", default-features = false }
hayro-interpret = { version = "=0.7.0", default-features = false, features = ["embed-fonts", "embed-cmaps"] }
hayro-syntax = { version = "=0.7.2", default-features = false, features = ["std"] }
bytemuck = "1"
kurbo = "0.13"
thiserror = "2"
craft-atomic = { path = "crates/atomic" }
craft-captions = { path = "crates/captions" }
craft-cfb = { path = "crates/cfb" }
craft-cms = { path = "crates/cms" }
craft-crw = { path = "crates/crw" }
craft-csv = { path = "crates/csv" }
craft-dialogs = { path = "crates/dialogs" }
craft-dxf = { path = "crates/dxf" }
craft-drawingml = { path = "crates/drawingml" }
craft-doc = { path = "crates/doc" }
craft-docpath = { path = "crates/docpath" }
craft-ecproj-format = { path = "crates/ecproj-format" }
craft-font-catalog = { path = "crates/font-catalog" }
craft-font-manager = { path = "crates/font-manager" }
craft-font-store = { path = "crates/font-store" }
craft-gainmap = { path = "crates/gainmap" }
craft-gcode = { path = "crates/gcode" }
craft-mesh = { path = "crates/mesh" }
craft-heif = { path = "crates/heif" }
craft-fig = { path = "crates/fig" }
craft-fonts-build = { path = "crates/fonts-build" }
craft-i18n = { path = "crates/i18n" }
craft-idml = { path = "crates/idml" }
craft-jpeg = { path = "crates/jpeg" }
craft-kiwi = { path = "crates/kiwi" }
craft-keymap = { path = "crates/keymap" }
craft-assuan = { path = "crates/assuan" }
craft-audio = { path = "crates/audio" }
# No default features, so craft-audio's `encode` builds craft-media without `isobmff`.
craft-media = { path = "crates/media", default-features = false }
craft-media-testkit = { path = "crates/media-testkit" }
craft-midi = { path = "crates/midi" }
craft-mime = { path = "crates/mime" }
craft-lottie = { path = "crates/lottie" }
craft-menu = { path = "crates/menu" }
craft-metafile = { path = "crates/metafile" }
craft-opc = { path = "crates/opc" }
craft-penpot = { path = "crates/penpot" }
craft-pcraft-format = { path = "crates/pcraft-format" }
craft-plotter = { path = "crates/plotter" }
craft-prepress = { path = "crates/prepress" }
craft-print = { path = "crates/print" }
craft-proof = { path = "crates/proof" }
craft-psd = { path = "crates/psd" }
craft-quit = { path = "crates/quit" }
craft-rtf = { path = "crates/rtf" }
craft-raw = { path = "crates/raw" }
craft-sketch = { path = "crates/sketch" }
craft-settings = { path = "crates/settings" }
craft-silhouette-studio = { path = "crates/silhouette-studio" }
craft-svg = { path = "crates/svg" }
craft-svg-paths = { path = "crates/svg-paths" }
craft-text = { path = "crates/text" }
craft-timeline = { path = "crates/timeline" }
craft-tiff = { path = "crates/tiff" }
craft-ui = { path = "crates/ui" }
craft-update = { path = "crates/update" }
craft-vectorcraft-format = { path = "crates/vectorcraft-format" }
craft-vectordrawable = { path = "crates/vectordrawable" }
craft-xls = { path = "crates/xls" }
craft-xml = { path = "crates/xml" }
craft-epub = { path = "crates/epub" }
craft-video = { path = "crates/video" }
craft-web-api = { path = "crates/web-api" }
craft-window = { path = "crates/window" }
craft-web-host = { path = "crates/web-host" }
egui = { version = "0.37", default-features = false }
md5 = { package = "md-5", version = "0.10", default-features = false }
rayon = "1"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
proptest = "1"
# Character sets of the WHATWG Encoding Standard (craft-mime). (Apache-2.0 OR MIT) AND BSD-3-Clause.
encoding_rs = "0.8"
# All date/time conversion goes through chrono (no hand-rolled calendar code beyond the 400-year range extension; AGENTS.md).
chrono = { version = "0.4.45", default-features = false, features = ["std"] }
[workspace.lints.rust]
unsafe_code = "forbid"
unexpected_cfgs = { level = "warn", check-cfg = ["cfg(craft_pdf_unicode_fixtures)"] }
[workspace.lints.clippy]
cognitive_complexity = "deny"
too_many_arguments = "deny"
wildcard_imports = "deny"
dbg_macro = "warn"
todo = "warn"
[patch.crates-io]
krilla = { path = "vendor/krilla" }
hayro = { path = "vendor/hayro" }
hayro-interpret = { path = "vendor/hayro-interpret" }
hayro-syntax = { path = "vendor/hayro-syntax" }
hayro-jbig2 = { path = "vendor/hayro-jbig2" }
hayro-cmap = { path = "vendor/hayro-cmap" }
hayro-postscript = { path = "vendor/hayro-postscript" }
linesweeper = { path = "vendor/linesweeper" }
ecolor = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
emath = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
epaint = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
epaint_default_fonts = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
egui = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
egui-winit = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
egui-wgpu = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
egui_glow = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
egui_extras = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
egui_kittest = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
egui_system_font_provider = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
eframe = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
egui_demo_lib = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
egui_inspection = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }
winit = { git = "https://github.com/storytold/winit.git", rev = "a517b3846ee8457d84ee4975110bfda6797c44dc" }
# symphonia's FLAC decoder restores LPC samples as `residual + (prediction as i32)`. In a valid
# 32-bit stream the prediction can leave the i32 range while the sum does not, so a debug build
# panics where a release build wraps to the right sample. Apps that decode 32-bit FLAC through
# craft-audio's `decode` need the same override in their own workspace.
[profile.dev.package.symphonia-bundle-flac]
overflow-checks = false
# Codec hot loops: the oracle and conformance tests of a debug build take minutes below opt-level 3.
[profile.dev.package.craft-video]
opt-level = 3
# The object-stream parser follows nesting 384 levels deep: unoptimised, its frames overflow the
# 2 MiB stack of a test thread. The apps this reader came from build their crates at this level.
[profile.dev.package.craft-affinity]
opt-level = 1