mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 04:55:42 +09:00
chore(repo): prune dead code and duplicate abstractions (#3413)
This commit is contained in:
1 parent
c17091768c
commit
c9fdf8fead
2937 files changed
+42233
-176793
No files matched your search
Generated
+3
-278
@@ -2,33 +2,6 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
||||
|
||||
[[package]]
|
||||
name = "bit-set"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3"
|
||||
dependencies = [
|
||||
"bit-vec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit-vec"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.20.3"
|
||||
@@ -53,46 +26,12 @@ version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223"
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e0f1c7c3a72c66fd80abe965175f7523475c0489a87d3ff9d6e8c87d87a9d2d"
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"r-efi 5.3.0",
|
||||
"wasip2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.4.3"
|
||||
@@ -101,7 +40,7 @@ checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"r-efi 6.0.0",
|
||||
"r-efi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -110,7 +49,7 @@ version = "0.1.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3"
|
||||
dependencies = [
|
||||
"getrandom 0.4.3",
|
||||
"getrandom",
|
||||
"libc",
|
||||
]
|
||||
|
||||
@@ -124,26 +63,10 @@ checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
|
||||
name = "libfluxcore"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"proptest",
|
||||
"wasm-bindgen",
|
||||
"zstd",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.4"
|
||||
@@ -156,15 +79,6 @@ version = "0.3.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||
dependencies = [
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.107"
|
||||
@@ -174,31 +88,6 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proptest"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744"
|
||||
dependencies = [
|
||||
"bit-set",
|
||||
"bit-vec",
|
||||
"bitflags",
|
||||
"num-traits",
|
||||
"rand",
|
||||
"rand_chacha",
|
||||
"rand_xorshift",
|
||||
"regex-syntax",
|
||||
"rusty-fork",
|
||||
"tempfile",
|
||||
"unarray",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-error"
|
||||
version = "1.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.47"
|
||||
@@ -208,110 +97,24 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r-efi"
|
||||
version = "5.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
||||
|
||||
[[package]]
|
||||
name = "r-efi"
|
||||
version = "6.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41"
|
||||
dependencies = [
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
|
||||
dependencies = [
|
||||
"getrandom 0.3.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_xorshift"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "1.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "891efababe418670775f199f0d233d84843c227a0949a883ce15b37c78d6629d"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"
|
||||
|
||||
[[package]]
|
||||
name = "rusty-fork"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc6bf79ff24e648f6da1f8d1f011e9cac26491b619e6b9280f2b47f1774e6ee2"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"quick-error",
|
||||
"tempfile",
|
||||
"wait-timeout",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.119"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "3.0.6"
|
||||
@@ -323,49 +126,12 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.27.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
|
||||
dependencies = [
|
||||
"fastrand",
|
||||
"getrandom 0.4.3",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unarray"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954"
|
||||
|
||||
[[package]]
|
||||
name = "wait-timeout"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasip2"
|
||||
version = "1.0.4+wasi-0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487"
|
||||
dependencies = [
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.128"
|
||||
@@ -398,7 +164,7 @@ dependencies = [
|
||||
"bumpalo",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.6",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@@ -411,47 +177,6 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen"
|
||||
version = "0.57.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d35102a9f36d089ccae9e4c6802bc118be4487b80aaffc0ab4e0cf5ce92d2873"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "146c01f5ab44258da43cf276c74a2763db2ff3969c9c652c3f2de07041d0b2bc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zstd"
|
||||
version = "0.14.0"
|
||||
|
||||
@@ -12,9 +12,6 @@ crate-type = ["cdylib", "rlib"]
|
||||
wasm-bindgen = "=0.2.128"
|
||||
zstd = {version = "0.14.0", default-features = false, features = ["no_asm", "thin", "wasm"]}
|
||||
|
||||
[dev-dependencies]
|
||||
proptest = "1.11.0"
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1
|
||||
lto = true
|
||||
|
||||
@@ -235,91 +235,14 @@ mod tests {
|
||||
out
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn detects_apng_animation_chunk() {
|
||||
let png = png_with_chunks(&[(b"acTL", &[0; 8])]);
|
||||
assert!(is_animated_image_bytes(&png));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn detects_webp_animation_chunk() {
|
||||
let mut webp = b"RIFF\x12\x00\x00\x00WEBPVP8X\x00\x00\x00\x00ANIM\x00\x00\x00\x00".to_vec();
|
||||
webp[4..8].copy_from_slice(&18u32.to_le_bytes());
|
||||
assert!(is_animated_image_bytes(&webp));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn detects_two_frame_gif() {
|
||||
let gif = [
|
||||
0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 1, 0, 1, 0, 0, 0, 0, 0x2c, 0, 0, 0, 0, 1, 0, 1, 0,
|
||||
0, 2, 0, 0x2c, 0, 0, 0, 0, 1, 0, 1, 0, 0, 2, 0, 0x3b,
|
||||
];
|
||||
assert!(is_animated_image_bytes(&gif));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn treats_single_frame_gif_as_static() {
|
||||
let gif = [
|
||||
0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 1, 0, 1, 0, 0, 0, 0, 0x2c, 0, 0, 0, 0, 1, 0, 1, 0,
|
||||
0, 2, 0, 0x3b,
|
||||
];
|
||||
assert!(!is_animated_image_bytes(&gif));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn detects_avif_sequence_brand() {
|
||||
let still = b"\x00\x00\x00\x18ftypavif\x00\x00\x00\x00mif1miaf";
|
||||
assert!(!is_animated_image_bytes(still));
|
||||
|
||||
let avis = b"\x00\x00\x00\x18ftypavis\x00\x00\x00\x00avif";
|
||||
assert!(is_animated_image_bytes(avis));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn detects_avis_among_compatible_brands() {
|
||||
let compat = b"\x00\x00\x00\x1cftypavif\x00\x00\x00\x00mif1avismsf1";
|
||||
assert!(is_animated_image_bytes(compat));
|
||||
|
||||
let outside_ftyp = b"\x00\x00\x00\x14ftypavif\x00\x00\x00\x00mif1avis";
|
||||
assert!(!is_animated_image_bytes(outside_ftyp));
|
||||
|
||||
let truncated = b"\x00\x00\x00\x40ftypavif\x00\x00\x00\x00mif1av";
|
||||
assert!(!is_animated_image_bytes(truncated));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sniffs_image_formats_from_magic_bytes() {
|
||||
assert_eq!(sniff_image_format_bytes(b""), 0);
|
||||
assert_eq!(sniff_image_format_bytes(b"<svg xmlns"), 0);
|
||||
assert_eq!(
|
||||
sniff_image_format_bytes(b"\x89PNG\r\n\x1a\n\0\0\0\rIHDR"),
|
||||
1
|
||||
);
|
||||
assert_eq!(sniff_image_format_bytes(b"GIF89a\x01\x00"), 2);
|
||||
assert_eq!(sniff_image_format_bytes(b"GIF87a\x01\x00"), 2);
|
||||
assert_eq!(sniff_image_format_bytes(b"RIFF\x04\0\0\0WEBPVP8 "), 3);
|
||||
assert_eq!(sniff_image_format_bytes(b"RIFF\x04\0\0\0WAVEfmt "), 0);
|
||||
assert_eq!(
|
||||
sniff_image_format_bytes(b"\x00\x00\x00\x18ftypavif\x00\x00\x00\x00"),
|
||||
4
|
||||
);
|
||||
assert_eq!(
|
||||
sniff_image_format_bytes(b"\x00\x00\x00\x18ftypavis\x00\x00\x00\x00"),
|
||||
4
|
||||
);
|
||||
assert_eq!(
|
||||
sniff_image_format_bytes(b"\x00\x00\x00\x18ftypheic\x00\x00\x00\x00"),
|
||||
0
|
||||
);
|
||||
assert_eq!(sniff_image_format_bytes(b"\xff\xd8\xff\xe0\x00\x10JFIF"), 5);
|
||||
assert_eq!(sniff_image_format_bytes(b"\xff\xd8"), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejects_truncated_chunks_without_panicking() {
|
||||
assert!(!is_animated_image_bytes(
|
||||
b"\x89PNG\r\n\x1a\n\xff\xff\xff\xffbad!"
|
||||
));
|
||||
let mut png = png_with_chunks(&[(b"bad!", &[0; 8])]);
|
||||
png[8..12].copy_from_slice(&u32::MAX.to_be_bytes());
|
||||
assert!(!is_animated_image_bytes(&png));
|
||||
assert!(!is_animated_image_bytes(b"RIFF\xff\xff\xff\xffWEBPbad!"));
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
mod formats;
|
||||
mod rgba;
|
||||
mod zstd_frame;
|
||||
mod zstd_stream;
|
||||
|
||||
use formats::{is_animated_image_bytes, sniff_image_format_bytes};
|
||||
@@ -42,11 +41,6 @@ pub fn crop_rotate_rgba_into_buffer(
|
||||
.map_err(|error| JsValue::from_str(error.message()))
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn decompress_zstd_frame(input: &[u8]) -> Result<Vec<u8>, JsValue> {
|
||||
zstd_frame::decompress(input).map_err(zstd_error_to_js)
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn create_zstd_stream_decoder() -> Result<u32, JsValue> {
|
||||
let decoder = zstd_stream::ZstdStreamDecoder::new().map_err(zstd_error_to_js)?;
|
||||
@@ -113,7 +107,7 @@ pub fn sniff_image_format(input: &[u8]) -> u8 {
|
||||
sniff_image_format_bytes(input)
|
||||
}
|
||||
|
||||
fn zstd_error_to_js(error: zstd_frame::ZstdError) -> JsValue {
|
||||
fn zstd_error_to_js(error: zstd_stream::ZstdError) -> JsValue {
|
||||
JsValue::from_str(error.message())
|
||||
}
|
||||
|
||||
|
||||
@@ -345,7 +345,6 @@ fn copy_pixel(input: &[u8], dst: &mut [u8], layout: PixelLayout, src: Point, tar
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use proptest::prelude::*;
|
||||
|
||||
fn request(src_width: u32, src_height: u32) -> TransformRequest {
|
||||
TransformRequest {
|
||||
@@ -378,44 +377,6 @@ mod tests {
|
||||
Ok(((geometry.target_width, geometry.target_height), output))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rotate_90_uses_clockwise_quarter_turns() {
|
||||
let mut transform = request(2, 3);
|
||||
transform.rotation_deg = 90;
|
||||
let (size, pixels) = transformed(&rgba(&[1, 2, 3, 4, 5, 6]), transform).unwrap();
|
||||
assert_eq!(size, (3, 2));
|
||||
assert_eq!(pixels, rgba(&[5, 3, 1, 6, 4, 2]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rotate_180_reverses_rows_and_columns() {
|
||||
let mut transform = request(2, 2);
|
||||
transform.rotation_deg = 180;
|
||||
let (size, pixels) = transformed(&rgba(&[1, 2, 3, 4]), transform).unwrap();
|
||||
assert_eq!(size, (2, 2));
|
||||
assert_eq!(pixels, rgba(&[4, 3, 2, 1]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rotate_270_uses_clockwise_quarter_turns() {
|
||||
let mut transform = request(2, 3);
|
||||
transform.rotation_deg = 270;
|
||||
let (size, pixels) = transformed(&rgba(&[1, 2, 3, 4, 5, 6]), transform).unwrap();
|
||||
assert_eq!(size, (3, 2));
|
||||
assert_eq!(pixels, rgba(&[2, 4, 6, 1, 3, 5]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn applies_nearest_resize_after_rotation() {
|
||||
let mut transform = request(4, 1);
|
||||
transform.x = 1;
|
||||
transform.width = 2;
|
||||
transform.resize_width = 4;
|
||||
let (size, pixels) = transformed(&rgba(&[1, 2, 3, 4]), transform).unwrap();
|
||||
assert_eq!(size, (4, 1));
|
||||
assert_eq!(pixels, rgba(&[2, 2, 3, 3]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clamps_crop_to_source_bounds() {
|
||||
let mut transform = request(3, 2);
|
||||
@@ -463,15 +424,4 @@ mod tests {
|
||||
TransformError::InvalidOutputLength
|
||||
);
|
||||
}
|
||||
|
||||
proptest! {
|
||||
#[test]
|
||||
fn identity_transform_preserves_pixels(width in 1u32..16, height in 1u32..16) {
|
||||
let pixel_count = (width * height) as usize;
|
||||
let input = rgba(&(0..pixel_count).map(|index| index as u8).collect::<Vec<_>>());
|
||||
let (size, pixels) = transformed(&input, request(width, height)).unwrap();
|
||||
prop_assert_eq!(size, (width, height));
|
||||
prop_assert_eq!(pixels, input);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
use std::io::Read;
|
||||
|
||||
pub(crate) const READ_BUFFER_BYTES: usize = 16 * 1024;
|
||||
pub(crate) const MAX_DECOMPRESSED_BYTES: usize = 64 * 1024 * 1024;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ZstdError {
|
||||
DecompressedSizeTooLarge,
|
||||
Decode,
|
||||
Encode,
|
||||
OutOfMemory,
|
||||
}
|
||||
|
||||
impl ZstdError {
|
||||
pub fn message(&self) -> &'static str {
|
||||
match self {
|
||||
Self::DecompressedSizeTooLarge => "zstd decompressed payload is too large",
|
||||
Self::Decode => "zstd decompression failed",
|
||||
Self::Encode => "zstd compression failed",
|
||||
Self::OutOfMemory => "out of memory",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decompress(input: &[u8]) -> Result<Vec<u8>, ZstdError> {
|
||||
if let Some(content_size) =
|
||||
zstd::zstd_safe::get_frame_content_size(input).map_err(|_| ZstdError::Decode)?
|
||||
{
|
||||
let content_size =
|
||||
usize::try_from(content_size).map_err(|_| ZstdError::DecompressedSizeTooLarge)?;
|
||||
if content_size > MAX_DECOMPRESSED_BYTES {
|
||||
return Err(ZstdError::DecompressedSizeTooLarge);
|
||||
}
|
||||
}
|
||||
|
||||
let mut decoder = zstd::stream::read::Decoder::new(input)
|
||||
.map_err(|_| ZstdError::Decode)?
|
||||
.single_frame();
|
||||
let mut output = Vec::new();
|
||||
let mut buffer = [0u8; READ_BUFFER_BYTES];
|
||||
|
||||
loop {
|
||||
let read = decoder.read(&mut buffer).map_err(|_| ZstdError::Decode)?;
|
||||
if read == 0 {
|
||||
return Ok(output);
|
||||
}
|
||||
let next_len = output
|
||||
.len()
|
||||
.checked_add(read)
|
||||
.ok_or(ZstdError::DecompressedSizeTooLarge)?;
|
||||
if next_len > MAX_DECOMPRESSED_BYTES {
|
||||
return Err(ZstdError::DecompressedSizeTooLarge);
|
||||
}
|
||||
output
|
||||
.try_reserve(read)
|
||||
.map_err(|_| ZstdError::OutOfMemory)?;
|
||||
output.extend_from_slice(&buffer[..read]);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn decompresses_a_zstd_frame() {
|
||||
let input = b"hello from fluxcore";
|
||||
let compressed = zstd::stream::encode_all(input.as_slice(), 1).unwrap();
|
||||
assert_eq!(decompress(&compressed).unwrap(), input);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejects_invalid_zstd() {
|
||||
assert!(matches!(decompress(b"not zstd"), Err(ZstdError::Decode)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejects_frames_over_the_decompressed_limit() {
|
||||
let input = vec![b'x'; MAX_DECOMPRESSED_BYTES + 1];
|
||||
let compressed = zstd::stream::encode_all(input.as_slice(), 1).unwrap();
|
||||
|
||||
assert!(matches!(
|
||||
decompress(&compressed),
|
||||
Err(ZstdError::DecompressedSizeTooLarge)
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,27 @@
|
||||
use zstd::zstd_safe::zstd_sys::ZSTD_EndDirective;
|
||||
use zstd::zstd_safe::{CCtx, CParameter, DCtx, InBuffer, OutBuffer};
|
||||
|
||||
use crate::zstd_frame::{MAX_DECOMPRESSED_BYTES, READ_BUFFER_BYTES, ZstdError};
|
||||
const READ_BUFFER_BYTES: usize = 16 * 1024;
|
||||
const MAX_DECOMPRESSED_BYTES: usize = 64 * 1024 * 1024;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ZstdError {
|
||||
DecompressedSizeTooLarge,
|
||||
Decode,
|
||||
Encode,
|
||||
OutOfMemory,
|
||||
}
|
||||
|
||||
impl ZstdError {
|
||||
pub fn message(&self) -> &'static str {
|
||||
match self {
|
||||
Self::DecompressedSizeTooLarge => "zstd decompressed payload is too large",
|
||||
Self::Decode => "zstd decompression failed",
|
||||
Self::Encode => "zstd compression failed",
|
||||
Self::OutOfMemory => "out of memory",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ZstdStreamEncoder {
|
||||
context: CCtx<'static>,
|
||||
@@ -114,48 +134,6 @@ fn append_output(output: &mut Vec<u8>, bytes: &[u8]) -> Result<(), ZstdError> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use zstd::stream::raw::{Encoder, InBuffer, Operation, OutBuffer};
|
||||
|
||||
fn compress_stream_chunk(encoder: &mut Encoder<'_>, input: &[u8]) -> Vec<u8> {
|
||||
let mut compressed = Vec::new();
|
||||
let mut input = InBuffer::around(input);
|
||||
let mut buffer = [0u8; READ_BUFFER_BYTES];
|
||||
|
||||
while input.pos() < input.src.len() {
|
||||
let written = {
|
||||
let mut output = OutBuffer::around(&mut buffer[..]);
|
||||
encoder.run(&mut input, &mut output).unwrap();
|
||||
output.pos()
|
||||
};
|
||||
compressed.extend_from_slice(&buffer[..written]);
|
||||
}
|
||||
|
||||
loop {
|
||||
let (remaining, written) = {
|
||||
let mut output = OutBuffer::around(&mut buffer[..]);
|
||||
let remaining = encoder.flush(&mut output).unwrap();
|
||||
(remaining, output.pos())
|
||||
};
|
||||
compressed.extend_from_slice(&buffer[..written]);
|
||||
if remaining == 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
compressed
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decodes_multiple_flushed_chunks_from_one_zstd_stream() {
|
||||
let mut encoder = Encoder::new(1).unwrap();
|
||||
let mut decoder = ZstdStreamDecoder::new().unwrap();
|
||||
|
||||
let first = compress_stream_chunk(&mut encoder, br#"{"op":10}"#);
|
||||
let second = compress_stream_chunk(&mut encoder, br#"{"op":11}"#);
|
||||
|
||||
assert_eq!(decoder.decompress_chunk(&first).unwrap(), br#"{"op":10}"#);
|
||||
assert_eq!(decoder.decompress_chunk(&second).unwrap(), br#"{"op":11}"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keeps_partial_frame_state_between_chunks() {
|
||||
@@ -169,23 +147,6 @@ mod tests {
|
||||
assert_eq!([first, second].concat(), b"hello stream");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encoder_and_decoder_roundtrip_ten_thousand_messages_bidirectionally() {
|
||||
let mut encoder = ZstdStreamEncoder::new(3).unwrap();
|
||||
let mut decoder = ZstdStreamDecoder::new().unwrap();
|
||||
|
||||
for seq in 1..=10_000 {
|
||||
let payload = format!(
|
||||
r#"{{"op":1,"d":{},"meta":"bidirectional zstd stream message {}"}}"#,
|
||||
seq, seq
|
||||
);
|
||||
let compressed = encoder.compress_chunk(payload.as_bytes()).unwrap();
|
||||
assert!(!compressed.is_empty());
|
||||
let decoded = decoder.decompress_chunk(&compressed).unwrap();
|
||||
assert_eq!(decoded, payload.as_bytes());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encoder_handles_a_payload_larger_than_the_buffer() {
|
||||
let mut encoder = ZstdStreamEncoder::new(3).unwrap();
|
||||
@@ -197,19 +158,30 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decodes_ten_thousand_flushed_gateway_json_chunks() {
|
||||
let mut encoder = Encoder::new(3).unwrap();
|
||||
fn rejects_invalid_zstd() {
|
||||
let mut decoder = ZstdStreamDecoder::new().unwrap();
|
||||
assert!(matches!(
|
||||
decoder.decompress_chunk(b"not zstd"),
|
||||
Err(ZstdError::Decode)
|
||||
));
|
||||
}
|
||||
|
||||
for seq in 1..=10_000 {
|
||||
let payload = format!(
|
||||
r#"{{"op":0,"t":"MESSAGE_CREATE","s":{},"d":{{"id":"{}","channel_id":"1497639278555484216","guild_id":"1427764661718740994","content":"gateway zstd stream stress payload {}"}}}}"#,
|
||||
seq, seq, seq
|
||||
);
|
||||
let compressed = compress_stream_chunk(&mut encoder, payload.as_bytes());
|
||||
let decoded = decoder.decompress_chunk(&compressed).unwrap();
|
||||
#[test]
|
||||
fn accepts_the_decompressed_limit() {
|
||||
let input = vec![b'x'; MAX_DECOMPRESSED_BYTES];
|
||||
let compressed = zstd::stream::encode_all(input.as_slice(), 1).unwrap();
|
||||
let mut decoder = ZstdStreamDecoder::new().unwrap();
|
||||
assert_eq!(decoder.decompress_chunk(&compressed).unwrap(), input);
|
||||
}
|
||||
|
||||
assert_eq!(decoded, payload.as_bytes());
|
||||
}
|
||||
#[test]
|
||||
fn rejects_frames_over_the_decompressed_limit() {
|
||||
let input = vec![b'x'; MAX_DECOMPRESSED_BYTES + 1];
|
||||
let compressed = zstd::stream::encode_all(input.as_slice(), 1).unwrap();
|
||||
let mut decoder = ZstdStreamDecoder::new().unwrap();
|
||||
assert!(matches!(
|
||||
decoder.decompress_chunk(&compressed),
|
||||
Err(ZstdError::DecompressedSizeTooLarge)
|
||||
));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user