mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-26 11:26:50 -06:00
fix(format): one kiwi value per compressed canvas byte
One value per two bytes of the compressed canvas was too tight for a public design system: a 39.5 MB canvas holding 29.7 million values got a budget of 19.7 million (reported in #701). Real files hold 0.37 to 0.75 values per compressed byte; the budget is now one per byte, at least the old 20 million and at most 128 million. A small file still gets main's 20 million, however far it unpacks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YQxjkNSUJhTkTfY74aNeki
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
0efddc3894
commit
7dcd7fd05b
@@ -11,11 +11,11 @@ use std::fmt;
|
||||
/// Deepest struct/message nesting decoded.
|
||||
const MAX_DEPTH: usize = 64;
|
||||
/// Most values decoded from one message (every scalar, array element and field counts): at least
|
||||
/// [`MIN_VALUES`], and one per [`PACKED_BYTES_PER_VALUE`] bytes of the file's compressed canvas,
|
||||
/// so a large real file decodes while a small one can't expand into a huge tree, however far its
|
||||
/// chunks inflate.
|
||||
/// [`MIN_VALUES`], and one per byte of the file's compressed canvas up to [`MAX_VALUES`], so a large
|
||||
/// real file decodes while a small one can't expand into a huge tree, however far its chunks
|
||||
/// inflate. Real files hold 0.37 to 0.75 values per compressed byte.
|
||||
const MIN_VALUES: usize = 20_000_000;
|
||||
const PACKED_BYTES_PER_VALUE: usize = 2;
|
||||
const MAX_VALUES: usize = 128 << 20;
|
||||
/// Most definitions in a schema, and fields in one definition.
|
||||
const MAX_DEFS: usize = 10_000;
|
||||
const MAX_FIELDS: usize = 10_000;
|
||||
@@ -302,7 +302,7 @@ impl Schema {
|
||||
|
||||
/// Most values decoded from a file whose compressed canvas is `packed` bytes.
|
||||
pub(crate) fn value_budget(packed: usize) -> usize {
|
||||
MIN_VALUES.max(packed / PACKED_BYTES_PER_VALUE)
|
||||
packed.clamp(MIN_VALUES, MAX_VALUES)
|
||||
}
|
||||
|
||||
struct Decoder<'s, 'b> {
|
||||
|
||||
@@ -629,8 +629,11 @@ fn large_files_get_a_larger_value_budget() {
|
||||
// A real 400 000-layer file: an 83.5 MB canvas whose message unpacks to 334 MB and holds
|
||||
// 30.5 million values was refused as "too many values".
|
||||
assert!(kiwi::value_budget(83_491_232) > 30_514_899);
|
||||
// Still bounded by the largest canvas read.
|
||||
assert!(kiwi::value_budget(MAX_CANVAS as usize) <= 128 << 20);
|
||||
// A public design system packs more densely: a 39.5 MB canvas holding 29.7 million values,
|
||||
// which one value per two compressed bytes refused.
|
||||
assert!(kiwi::value_budget(39_500_000) > 29_703_730);
|
||||
// Never more than the ceiling, however large the canvas.
|
||||
assert_eq!(kiwi::value_budget(MAX_CANVAS as usize), 128 << 20);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user