зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to inbound. a=merge CLOSED TREE
This commit is contained in:
Коммит
d4e8ffb875
|
@ -178,7 +178,7 @@ name = "base64"
|
|||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -187,7 +187,7 @@ name = "base64"
|
|||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -221,7 +221,7 @@ name = "bincode"
|
|||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -261,12 +261,17 @@ name = "bit-set"
|
|||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bit-vec 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit-vec"
|
||||
version = "0.5.0"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "bit_reverse"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
@ -339,7 +344,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
dependencies = [
|
||||
"block-padding 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -386,7 +391,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.2.7"
|
||||
version = "1.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
@ -394,7 +399,7 @@ name = "bytes"
|
|||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -431,7 +436,7 @@ name = "cert_storage"
|
|||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lmdb-rkv 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -439,6 +444,7 @@ dependencies = [
|
|||
"nserror 0.1.0",
|
||||
"nsstring 0.1.0",
|
||||
"rkv 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rust_cascade 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"style 0.0.1",
|
||||
"thin-vec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -842,7 +848,7 @@ version = "0.7.19"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1144,7 +1150,7 @@ name = "fxhash"
|
|||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1281,7 +1287,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gleam"
|
||||
version = "0.6.16"
|
||||
version = "0.6.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gl_generator 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1316,7 +1322,7 @@ name = "h2"
|
|||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1333,7 +1339,7 @@ name = "hashbrown"
|
|||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"scopeguard 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -1412,7 +1418,7 @@ name = "image"
|
|||
version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1881,7 +1887,7 @@ name = "mp4parse"
|
|||
version = "0.11.2"
|
||||
dependencies = [
|
||||
"bitreader 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mp4parse_fallible 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1895,7 +1901,7 @@ version = "0.1.0"
|
|||
name = "mp4parse_capi"
|
||||
version = "0.11.2"
|
||||
dependencies = [
|
||||
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mp4parse 0.11.2",
|
||||
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1915,6 +1921,11 @@ dependencies = [
|
|||
"winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "murmurhash3"
|
||||
version = "0.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "net2"
|
||||
version = "0.2.33"
|
||||
|
@ -2186,7 +2197,7 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2440,6 +2451,19 @@ name = "rust-ini"
|
|||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rust_cascade"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bit_reverse 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"murmurhash3 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.8"
|
||||
|
@ -2720,7 +2744,7 @@ dependencies = [
|
|||
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bindgen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.25.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -3327,7 +3351,7 @@ dependencies = [
|
|||
"base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -3336,7 +3360,7 @@ dependencies = [
|
|||
"dwrote 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"image 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -3366,7 +3390,7 @@ dependencies = [
|
|||
"app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -3391,7 +3415,7 @@ dependencies = [
|
|||
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nsstring 0.1.0",
|
||||
"num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -3475,7 +3499,7 @@ name = "ws"
|
|||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"httparse 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -3590,7 +3614,8 @@ dependencies = [
|
|||
"checksum bindgen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)" = "33e1b67a27bca31fd12a683b2a3618e275311117f48cfcc892e18403ff889026"
|
||||
"checksum binjs_meta 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "430239e4551e42b80fa5d92322ac80ea38c9dda56e5d5582e057e2288352b71a"
|
||||
"checksum bit-set 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6f1efcc46c18245a69c38fcc5cc650f16d3a59d034f3106e9ed63748f695730a"
|
||||
"checksum bit-vec 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4440d5cb623bb7390ae27fec0bb6c61111969860f8e3ae198bfa0663645e67cf"
|
||||
"checksum bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb"
|
||||
"checksum bit_reverse 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5e97e02db5a2899c0377f3d6031d5da8296ca2b47abef6ed699de51b9e40a28c"
|
||||
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
|
||||
"checksum bitreader 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "80b13e2ab064ff3aa0bdbf1eff533f9822dc37899821f5f98c67f263eab51707"
|
||||
"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400"
|
||||
|
@ -3599,7 +3624,7 @@ dependencies = [
|
|||
"checksum boxfnonce 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8380105befe91099e6f69206164072c05bc92427ff6aa8a5171388317346dd75"
|
||||
"checksum build_const 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e90dc84f5e62d2ebe7676b83c22d33b6db8bd27340fb6ffbff0a364efa0cb9c9"
|
||||
"checksum byte-tools 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "980479e6fde23246dfb54d47580d66b4e99202e7579c5eaa9fe10ecb5ebd2182"
|
||||
"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d"
|
||||
"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb"
|
||||
"checksum bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e178b8e0e239e844b083d5a0d4a156b2654e67f9f80144d48398fcd736a24fb8"
|
||||
"checksum bzip2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3eafc42c44e0d827de6b1c131175098fe7fb53b8ce8a47e65cb3ea94688be24"
|
||||
"checksum bzip2-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2c5162604199bbb17690ede847eaa6120a3f33d5ab4dcc8e7c25b16d849ae79b"
|
||||
|
@ -3682,7 +3707,7 @@ dependencies = [
|
|||
"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb"
|
||||
"checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592"
|
||||
"checksum gl_generator 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "39a23d5e872a275135d66895d954269cf5e8661d234eb1c2480f4ce0d586acbd"
|
||||
"checksum gleam 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "39bb69499005e11b7b7cc0af38404a1bc0f53d954bffa8adcdb6e8d5b14f75d5"
|
||||
"checksum gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7f46fd8874e043ffac0d638ed1567a2584f7814f6d72b4db37ab1689004a26c4"
|
||||
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
|
||||
"checksum goblin 0.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "5911d7df7b8f65ab676c5327b50acea29d3c6a1a4ad05e444cf5dce321b26db2"
|
||||
"checksum guid_win 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "87261686cc5e35b6584f4c2a430c2b153d8a92ab1ef820c16be34c1df8f5f58b"
|
||||
|
@ -3734,6 +3759,7 @@ dependencies = [
|
|||
"checksum moz_cbor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20c82a57087fd5990d7122dbff1607c3b20c3d2958e9d9ad9765aab415e2c91c"
|
||||
"checksum mp4parse_fallible 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6626c2aef76eb8f984eef02e475883d3fe9112e114720446c5810fc5f045cd30"
|
||||
"checksum msdos_time 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aad9dfe950c057b1bfe9c1f2aa51583a8468ef2a5baba2ebbe06d775efeb7729"
|
||||
"checksum murmurhash3 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a2983372caf4480544083767bf2d27defafe32af49ab4df3a0b7fc90793a3664"
|
||||
"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
|
||||
"checksum new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4"
|
||||
"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
|
||||
|
@ -3789,6 +3815,7 @@ dependencies = [
|
|||
"checksum ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "da06feaa07f69125ab9ddc769b11de29090122170b402547f64b86fe16ebc399"
|
||||
"checksum runloop 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d79b4b604167921892e84afbbaad9d5ad74e091bf6c511d9dbfb0593f09fabd"
|
||||
"checksum rust-ini 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8a654c5bda722c699be6b0fe4c0d90de218928da5b724c3e467fc48865c37263"
|
||||
"checksum rust_cascade 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f3fe4900d38dab1ad21a515e44687dd0711e6b0ec5b214a3b1aa8857343bcf3a"
|
||||
"checksum rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "76d7ba1feafada44f2d38eed812bd2489a03c0f5abb975799251518b68848649"
|
||||
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
"checksum ryu 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0568787116e13c652377b6846f5931454a363a8fdf8ae50463ee40935b278b"
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/* vim: set ts=2 sw=2 sts=2 et tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = ["SubframeCrashChild"];
|
||||
|
||||
let {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
class SubframeCrashChild extends JSWindowActorChild {
|
||||
receiveMessage(message) {
|
||||
if (message.name == "SubframeCrashed") {
|
||||
this.onSubframeCrashed(message.data.id);
|
||||
}
|
||||
}
|
||||
|
||||
onSubframeCrashed(browsingContextId) {
|
||||
let bc = BrowsingContext.get(browsingContextId);
|
||||
let iframe = bc.embedderElement;
|
||||
let uri = Services.io.newURI(iframe.src);
|
||||
iframe.removeAttribute("fission");
|
||||
iframe.removeAttribute("src");
|
||||
// Passing a null remoteType is currently how we tell the iframe to run
|
||||
// in the same process as the embedder.
|
||||
iframe.changeRemoteness({ remoteType: null });
|
||||
let docShell = iframe.frameLoader.docShell;
|
||||
docShell.displayLoadError(Cr.NS_ERROR_FRAME_CRASHED, uri, null);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
/* vim: set ts=2 sw=2 sts=2 et tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = ["SubframeCrashParent"];
|
||||
|
||||
class SubframeCrashParent extends JSWindowActorParent {
|
||||
}
|
|
@ -40,6 +40,8 @@ FINAL_TARGET_FILES.actors += [
|
|||
'PluginChild.jsm',
|
||||
'RFPHelperChild.jsm',
|
||||
'SearchTelemetryChild.jsm',
|
||||
'SubframeCrashChild.jsm',
|
||||
'SubframeCrashParent.jsm',
|
||||
'URIFixupChild.jsm',
|
||||
'WebRTCChild.jsm',
|
||||
]
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" media="all"
|
||||
href="chrome://global/skin/in-content/info-pages.css"/>
|
||||
<link rel="stylesheet" type="text/css" media="all"
|
||||
href="chrome://browser/skin/aboutFrameCrashed.css"/>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
|
@ -61,6 +61,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
|
|||
SimpleServiceDiscovery: "resource://gre/modules/SimpleServiceDiscovery.jsm",
|
||||
SiteDataManager: "resource:///modules/SiteDataManager.jsm",
|
||||
SitePermissions: "resource:///modules/SitePermissions.jsm",
|
||||
SubframeCrashHandler: "resource:///modules/ContentCrashHandlers.jsm",
|
||||
TabModalPrompt: "chrome://global/content/tabprompts.jsm",
|
||||
TabCrashHandler: "resource:///modules/ContentCrashHandlers.jsm",
|
||||
TelemetryEnvironment: "resource://gre/modules/TelemetryEnvironment.jsm",
|
||||
|
|
|
@ -4627,8 +4627,15 @@ window._gBrowser = {
|
|||
});
|
||||
|
||||
this.addEventListener("oop-browser-crashed", (event) => {
|
||||
if (!event.isTrusted)
|
||||
if (!event.isTrusted) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!event.isTopFrame) {
|
||||
let bc = BrowsingContext.get(event.browsingContextId);
|
||||
SubframeCrashHandler.onSubframeCrash(bc);
|
||||
return;
|
||||
}
|
||||
|
||||
let browser = event.originalTarget;
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ browser.jar:
|
|||
content/browser/aboutNetError.xhtml (content/aboutNetError.xhtml)
|
||||
content/browser/aboutNetError.js (content/aboutNetError.js)
|
||||
content/browser/aboutRobots-icon.png (content/aboutRobots-icon.png)
|
||||
content/browser/aboutFrameCrashed.html (content/aboutFrameCrashed.html)
|
||||
content/browser/aboutTabCrashed.css (content/aboutTabCrashed.css)
|
||||
content/browser/aboutTabCrashed.js (content/aboutTabCrashed.js)
|
||||
content/browser/aboutTabCrashed.xhtml (content/aboutTabCrashed.xhtml)
|
||||
|
|
|
@ -16,6 +16,20 @@ ChromeUtils.defineModuleGetter(this, "ActorManagerParent",
|
|||
const PREF_PDFJS_ENABLED_CACHE_STATE = "pdfjs.enabledCache.state";
|
||||
|
||||
let ACTORS = {
|
||||
SubframeCrash: {
|
||||
parent: {
|
||||
moduleURI: "resource:///actors/SubframeCrashParent.jsm",
|
||||
},
|
||||
|
||||
child: {
|
||||
moduleURI: "resource:///actors/SubframeCrashChild.jsm",
|
||||
},
|
||||
|
||||
allFrames: true,
|
||||
},
|
||||
};
|
||||
|
||||
let LEGACY_ACTORS = {
|
||||
AboutReader: {
|
||||
child: {
|
||||
module: "resource:///actors/AboutReaderChild.jsm",
|
||||
|
@ -942,6 +956,7 @@ BrowserGlue.prototype = {
|
|||
os.addObserver(this, "shield-init-complete");
|
||||
|
||||
ActorManagerParent.addActors(ACTORS);
|
||||
ActorManagerParent.addLegacyActors(LEGACY_ACTORS);
|
||||
ActorManagerParent.flush();
|
||||
|
||||
this._flashHangCount = 0;
|
||||
|
|
|
@ -53,6 +53,9 @@ static const RedirEntry kRedirMap[] = {
|
|||
nsIAboutModule::URI_CAN_LOAD_IN_CHILD | nsIAboutModule::ALLOW_SCRIPT |
|
||||
nsIAboutModule::HIDE_FROM_ABOUTABOUT},
|
||||
{"config", "chrome://browser/content/aboutconfig/aboutconfig.html", 0},
|
||||
{"framecrashed", "chrome://browser/content/aboutFrameCrashed.html",
|
||||
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
|
||||
nsIAboutModule::HIDE_FROM_ABOUTABOUT},
|
||||
{"tabcrashed", "chrome://browser/content/aboutTabCrashed.xhtml",
|
||||
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
|
||||
nsIAboutModule::ALLOW_SCRIPT | nsIAboutModule::HIDE_FROM_ABOUTABOUT},
|
||||
|
|
|
@ -8,6 +8,7 @@ pages = [
|
|||
'blocked',
|
||||
'certerror',
|
||||
'downloads',
|
||||
'framecrashed',
|
||||
'home',
|
||||
'library',
|
||||
'newinstall',
|
||||
|
|
|
@ -1044,7 +1044,9 @@ var SessionStoreInternal = {
|
|||
this.saveStateDelayed(win);
|
||||
break;
|
||||
case "oop-browser-crashed":
|
||||
this.onBrowserCrashed(target);
|
||||
if (aEvent.isTopFrame) {
|
||||
this.onBrowserCrashed(target);
|
||||
}
|
||||
break;
|
||||
case "XULFrameLoaderCreated":
|
||||
if (target.namespaceURI == NS_XUL &&
|
||||
|
|
|
@ -4,8 +4,9 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = [ "TabCrashHandler",
|
||||
"PluginCrashReporter",
|
||||
var EXPORTED_SYMBOLS = [ "PluginCrashReporter",
|
||||
"SubframeCrashHandler",
|
||||
"TabCrashHandler",
|
||||
"UnsubmittedCrashHandler" ];
|
||||
|
||||
const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
@ -585,6 +586,16 @@ var TabCrashHandler = {
|
|||
},
|
||||
};
|
||||
|
||||
var SubframeCrashHandler = {
|
||||
onSubframeCrash(browsingContext) {
|
||||
// A subframe has crashed. We have to inform the parent frame so that it
|
||||
// can show suitable UI.
|
||||
let parentWg = browsingContext.parent.currentWindowGlobal;
|
||||
let actor = parentWg.getActor("SubframeCrash");
|
||||
actor.sendAsyncMessage("SubframeCrashed", { id: browsingContext.id });
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* This component is responsible for scanning the pending
|
||||
* crash report directory for reports, and (if enabled), to
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
body {
|
||||
background-image: url("chrome://browser/skin/tab-crashed.svg");
|
||||
background-position: center, center;
|
||||
background-repeat: no-repeat;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-size: 1.6em;
|
||||
}
|
|
@ -13,6 +13,7 @@
|
|||
skin/classic/browser/aboutRestartRequired.css (../shared/aboutRestartRequired.css)
|
||||
* skin/classic/browser/aboutSessionRestore.css (../shared/aboutSessionRestore.css)
|
||||
skin/classic/browser/aboutLibrary.css (../shared/aboutLibrary.css)
|
||||
skin/classic/browser/aboutFrameCrashed.css (../shared/aboutFrameCrashed.css)
|
||||
skin/classic/browser/aboutTabCrashed.css (../shared/aboutTabCrashed.css)
|
||||
skin/classic/browser/aboutWelcomeBack.css (../shared/aboutWelcomeBack.css)
|
||||
skin/classic/browser/setDesktopBackground.css (../shared/setDesktopBackground.css)
|
||||
|
|
|
@ -4257,6 +4257,10 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
|
|||
if (messageStr.IsEmpty()) {
|
||||
messageStr.AssignLiteral(u" ");
|
||||
}
|
||||
} else if (NS_ERROR_FRAME_CRASHED == aError) {
|
||||
errorPage.AssignLiteral("framecrashed");
|
||||
error = "framecrashed";
|
||||
messageStr.AssignLiteral(u" ");
|
||||
} else if (NS_ERROR_BUILDID_MISMATCH == aError) {
|
||||
errorPage.AssignLiteral("restartrequired");
|
||||
error = "restartrequired";
|
||||
|
|
|
@ -485,11 +485,17 @@ void BrowserParent::ActorDestroy(ActorDestroyReason why) {
|
|||
// out-of-process iframe.
|
||||
RefPtr<nsFrameLoader> frameLoader = GetFrameLoader(true);
|
||||
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
||||
if (frameLoader && !mBrowserBridgeParent) {
|
||||
if (frameLoader) {
|
||||
nsCOMPtr<Element> frameElement(mFrameElement);
|
||||
ReceiveMessage(CHILD_PROCESS_SHUTDOWN_MESSAGE, false, nullptr, nullptr,
|
||||
nullptr);
|
||||
frameLoader->DestroyComplete();
|
||||
|
||||
if (!mBrowsingContext->GetParent()) {
|
||||
// If this is a top-level BrowsingContext, tell the frameloader it's time
|
||||
// to go away. Otherwise, this is a subframe crash, and we can keep the
|
||||
// frameloader around.
|
||||
frameLoader->DestroyComplete();
|
||||
}
|
||||
|
||||
if (why == AbnormalShutdown && os) {
|
||||
os->NotifyObservers(ToSupports(frameLoader), "oop-frameloader-crashed",
|
||||
|
@ -513,6 +519,7 @@ void BrowserParent::ActorDestroy(ActorDestroyReason why) {
|
|||
init.mBubbles = true;
|
||||
init.mCancelable = true;
|
||||
init.mBrowsingContextId = mBrowsingContext->Id();
|
||||
init.mIsTopFrame = !mBrowsingContext->GetParent();
|
||||
|
||||
RefPtr<dom::FrameCrashedEvent> event =
|
||||
dom::FrameCrashedEvent::Constructor(frameElement->OwnerDoc(),
|
||||
|
|
|
@ -11,9 +11,15 @@ interface FrameCrashedEvent : Event
|
|||
* The browsingContextId of the frame that crashed.
|
||||
*/
|
||||
readonly attribute unsigned long long browsingContextId;
|
||||
|
||||
/**
|
||||
* True if the top-most frame crashed.
|
||||
*/
|
||||
readonly attribute boolean isTopFrame;
|
||||
};
|
||||
|
||||
dictionary FrameCrashedEventInit : EventInit
|
||||
{
|
||||
unsigned long long browsingContextId = 0;
|
||||
boolean isTopFrame = false;
|
||||
};
|
||||
|
|
|
@ -143,7 +143,7 @@ name = "cgl"
|
|||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gleam 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -370,7 +370,7 @@ name = "direct-composition"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mozangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"webrender 0.60.0",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -569,7 +569,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gleam"
|
||||
version = "0.6.16"
|
||||
version = "0.6.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gl_generator 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1645,7 +1645,7 @@ dependencies = [
|
|||
"dwrote 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"image 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1682,7 +1682,7 @@ dependencies = [
|
|||
"app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glutin 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"webrender 0.60.0",
|
||||
|
@ -1799,7 +1799,7 @@ dependencies = [
|
|||
"env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"font-loader 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glutin 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"image 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1946,7 +1946,7 @@ dependencies = [
|
|||
"checksum gif 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff3414b424657317e708489d2857d9575f4403698428b040b609b9d1c1a84a2c"
|
||||
"checksum gl_generator 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "39a23d5e872a275135d66895d954269cf5e8661d234eb1c2480f4ce0d586acbd"
|
||||
"checksum gl_generator 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a795170cbd85b5a7baa58d6d7525cae6a03e486859860c220f7ebbbdd379d0a"
|
||||
"checksum gleam 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "39bb69499005e11b7b7cc0af38404a1bc0f53d954bffa8adcdb6e8d5b14f75d5"
|
||||
"checksum gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7f46fd8874e043ffac0d638ed1567a2584f7814f6d72b4db37ab1689004a26c4"
|
||||
"checksum glutin 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a70c5fe78efbd5a3b243a804ea1032053c584510f8822819f94cfb29b2100317"
|
||||
"checksum half 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d5c5f71a723d10dfc58927cbed37c3071a50afc7f073d86fd7d3e5727db890f"
|
||||
"checksum httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2f407128745b78abc95c0ffbe4e5d37427fdc0d45470710cfef8c44522a2e37"
|
||||
|
|
|
@ -30,7 +30,7 @@ byteorder = "1.0"
|
|||
cfg-if = "0.1.2"
|
||||
cstr = "0.1.2"
|
||||
fxhash = "0.2.1"
|
||||
gleam = "0.6.16"
|
||||
gleam = "0.6.17"
|
||||
image = { optional = true, version = "0.21", default-features = false, features = ["png_codec"] }
|
||||
lazy_static = "1"
|
||||
log = "0.4"
|
||||
|
|
|
@ -138,15 +138,17 @@ pub struct AlphaBatchList {
|
|||
pub item_rects: Vec<Vec<PictureRect>>,
|
||||
current_batch_index: usize,
|
||||
current_z_id: ZBufferId,
|
||||
break_advanced_blend_batches: bool,
|
||||
}
|
||||
|
||||
impl AlphaBatchList {
|
||||
fn new() -> Self {
|
||||
fn new(break_advanced_blend_batches: bool) -> Self {
|
||||
AlphaBatchList {
|
||||
batches: Vec::new(),
|
||||
item_rects: Vec::new(),
|
||||
current_z_id: ZBufferId::invalid(),
|
||||
current_batch_index: usize::MAX,
|
||||
break_advanced_blend_batches,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,6 +182,9 @@ impl AlphaBatchList {
|
|||
}
|
||||
}
|
||||
}
|
||||
BlendMode::Advanced(_) if self.break_advanced_blend_batches => {
|
||||
// don't try to find a batch
|
||||
}
|
||||
_ => {
|
||||
'outer_default: for (batch_index, batch) in self.batches.iter().enumerate().rev().take(10) {
|
||||
// For normal batches, we only need to check for overlaps for batches
|
||||
|
@ -301,13 +306,14 @@ impl BatchList {
|
|||
screen_size: DeviceIntSize,
|
||||
regions: Vec<DeviceIntRect>,
|
||||
tile_blits: Vec<TileBlit>,
|
||||
break_advanced_blend_batches: bool,
|
||||
) -> Self {
|
||||
// The threshold for creating a new batch is
|
||||
// one quarter the screen size.
|
||||
let batch_area_threshold = (screen_size.width * screen_size.height) as f32 / 4.0;
|
||||
|
||||
BatchList {
|
||||
alpha_batch_list: AlphaBatchList::new(),
|
||||
alpha_batch_list: AlphaBatchList::new(break_advanced_blend_batches),
|
||||
opaque_batch_list: OpaqueBatchList::new(batch_area_threshold),
|
||||
regions,
|
||||
tile_blits,
|
||||
|
@ -321,23 +327,8 @@ impl BatchList {
|
|||
z_id: ZBufferId,
|
||||
instance: PrimitiveInstanceData,
|
||||
) {
|
||||
match key.blend_mode {
|
||||
BlendMode::None => {
|
||||
self.opaque_batch_list
|
||||
.set_params_and_get_batch(key, bounding_rect)
|
||||
.push(instance);
|
||||
}
|
||||
BlendMode::Alpha |
|
||||
BlendMode::PremultipliedAlpha |
|
||||
BlendMode::PremultipliedDestOut |
|
||||
BlendMode::SubpixelConstantTextColor(..) |
|
||||
BlendMode::SubpixelWithBgColor |
|
||||
BlendMode::SubpixelDualSource => {
|
||||
self.alpha_batch_list
|
||||
.set_params_and_get_batch(key, bounding_rect, z_id)
|
||||
.push(instance);
|
||||
}
|
||||
}
|
||||
self.set_params_and_get_batch(key, bounding_rect, z_id)
|
||||
.push(instance);
|
||||
}
|
||||
|
||||
pub fn set_params_and_get_batch(
|
||||
|
@ -356,7 +347,8 @@ impl BatchList {
|
|||
BlendMode::PremultipliedDestOut |
|
||||
BlendMode::SubpixelConstantTextColor(..) |
|
||||
BlendMode::SubpixelWithBgColor |
|
||||
BlendMode::SubpixelDualSource => {
|
||||
BlendMode::SubpixelDualSource |
|
||||
BlendMode::Advanced(_) => {
|
||||
self.alpha_batch_list
|
||||
.set_params_and_get_batch(key, bounding_rect, z_id)
|
||||
}
|
||||
|
@ -475,18 +467,21 @@ pub struct AlphaBatchBuilder {
|
|||
screen_size: DeviceIntSize,
|
||||
task_scissor_rect: Option<DeviceIntRect>,
|
||||
glyph_fetch_buffer: Vec<GlyphFetchResult>,
|
||||
break_advanced_blend_batches: bool,
|
||||
}
|
||||
|
||||
impl AlphaBatchBuilder {
|
||||
pub fn new(
|
||||
screen_size: DeviceIntSize,
|
||||
task_scissor_rect: Option<DeviceIntRect>,
|
||||
break_advanced_blend_batches: bool,
|
||||
) -> Self {
|
||||
let batch_lists = vec![
|
||||
BatchList::new(
|
||||
screen_size,
|
||||
Vec::new(),
|
||||
Vec::new(),
|
||||
break_advanced_blend_batches,
|
||||
),
|
||||
];
|
||||
|
||||
|
@ -495,6 +490,7 @@ impl AlphaBatchBuilder {
|
|||
task_scissor_rect,
|
||||
screen_size,
|
||||
glyph_fetch_buffer: Vec::new(),
|
||||
break_advanced_blend_batches,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -507,6 +503,7 @@ impl AlphaBatchBuilder {
|
|||
self.screen_size,
|
||||
regions,
|
||||
tile_blits,
|
||||
self.break_advanced_blend_batches,
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -1102,6 +1099,10 @@ impl AlphaBatchBuilder {
|
|||
render_tasks,
|
||||
).unwrap_or(OPAQUE_TASK_ADDRESS);
|
||||
|
||||
let surface = ctx.surfaces[raster_config.surface_index.0]
|
||||
.surface
|
||||
.as_ref();
|
||||
|
||||
match raster_config.composite_mode {
|
||||
PictureCompositeMode::TileCache { .. } => {
|
||||
let tile_cache = picture.tile_cache.as_ref().unwrap();
|
||||
|
@ -1256,10 +1257,6 @@ impl AlphaBatchBuilder {
|
|||
}
|
||||
}
|
||||
PictureCompositeMode::Filter(ref filter) => {
|
||||
let surface = ctx.surfaces[raster_config.surface_index.0]
|
||||
.surface
|
||||
.as_ref()
|
||||
.expect("bug: surface must be allocated by now");
|
||||
assert!(filter.is_visible());
|
||||
match filter {
|
||||
FilterOp::Blur(..) => {
|
||||
|
@ -1267,6 +1264,7 @@ impl AlphaBatchBuilder {
|
|||
BrushBatchKind::Image(ImageBufferKind::Texture2DArray)
|
||||
);
|
||||
let (uv_rect_address, textures) = surface
|
||||
.expect("bug: surface must be allocated by now")
|
||||
.resolve(
|
||||
render_tasks,
|
||||
ctx.resource_cache,
|
||||
|
@ -1329,7 +1327,9 @@ impl AlphaBatchBuilder {
|
|||
let content_key = BatchKey::new(kind, non_segmented_blend_mode, content_textures);
|
||||
|
||||
// Retrieve the UV rect addresses for shadow/content.
|
||||
let cache_task_id = surface.resolve_render_task_id();
|
||||
let cache_task_id = surface
|
||||
.expect("bug: surface must be allocated by now")
|
||||
.resolve_render_task_id();
|
||||
let shadow_uv_rect_address = render_tasks[cache_task_id]
|
||||
.get_texture_address(gpu_cache)
|
||||
.as_int();
|
||||
|
@ -1443,6 +1443,7 @@ impl AlphaBatchBuilder {
|
|||
};
|
||||
|
||||
let (uv_rect_address, textures) = surface
|
||||
.expect("bug: surface must be allocated by now")
|
||||
.resolve(
|
||||
render_tasks,
|
||||
ctx.resource_cache,
|
||||
|
@ -1484,12 +1485,6 @@ impl AlphaBatchBuilder {
|
|||
// This is basically the same as the general filter case above
|
||||
// except we store a little more data in the filter mode and
|
||||
// a gpu cache handle in the user data.
|
||||
let surface = ctx.surfaces[raster_config.surface_index.0]
|
||||
.surface
|
||||
.as_ref()
|
||||
.expect("bug: surface must be allocated by now");
|
||||
|
||||
|
||||
let filter_data = &ctx.data_stores.filter_data[handle];
|
||||
let filter_mode : i32 = 13 |
|
||||
((filter_data.data.r_func.to_int() << 28 |
|
||||
|
@ -1500,6 +1495,7 @@ impl AlphaBatchBuilder {
|
|||
let user_data = filter_data.gpu_cache_handle.as_int(gpu_cache);
|
||||
|
||||
let (uv_rect_address, textures) = surface
|
||||
.expect("bug: surface must be allocated by now")
|
||||
.resolve(
|
||||
render_tasks,
|
||||
ctx.resource_cache,
|
||||
|
@ -1535,12 +1531,48 @@ impl AlphaBatchBuilder {
|
|||
PrimitiveInstanceData::from(instance),
|
||||
);
|
||||
}
|
||||
PictureCompositeMode::MixBlend(mode) if ctx.use_advanced_blending => {
|
||||
let (uv_rect_address, textures) = surface
|
||||
.expect("bug: surface must be allocated by now")
|
||||
.resolve(
|
||||
render_tasks,
|
||||
ctx.resource_cache,
|
||||
gpu_cache,
|
||||
);
|
||||
let key = BatchKey::new(
|
||||
BatchKind::Brush(
|
||||
BrushBatchKind::Image(ImageBufferKind::Texture2DArray),
|
||||
),
|
||||
BlendMode::Advanced(mode),
|
||||
textures,
|
||||
);
|
||||
let prim_header_index = prim_headers.push(&prim_header, z_id, [
|
||||
ShaderColorMode::Image as i32 | ((AlphaType::PremultipliedAlpha as i32) << 16),
|
||||
RasterizationSpace::Local as i32,
|
||||
get_shader_opacity(1.0),
|
||||
0,
|
||||
]);
|
||||
|
||||
let instance = BrushInstance {
|
||||
prim_header_index,
|
||||
clip_task_address,
|
||||
segment_index: INVALID_SEGMENT_INDEX,
|
||||
edge_flags: EdgeAaSegmentMask::empty(),
|
||||
brush_flags,
|
||||
user_data: uv_rect_address.as_int(),
|
||||
};
|
||||
|
||||
self.current_batch_list().push_single_instance(
|
||||
key,
|
||||
bounding_rect,
|
||||
z_id,
|
||||
PrimitiveInstanceData::from(instance),
|
||||
);
|
||||
}
|
||||
PictureCompositeMode::MixBlend(mode) => {
|
||||
let surface = ctx.surfaces[raster_config.surface_index.0]
|
||||
.surface
|
||||
.as_ref()
|
||||
.expect("bug: surface must be allocated by now");
|
||||
let cache_task_id = surface.resolve_render_task_id();
|
||||
let cache_task_id = surface
|
||||
.expect("bug: surface must be allocated by now")
|
||||
.resolve_render_task_id();
|
||||
let backdrop_id = picture.secondary_render_task_id.expect("no backdrop!?");
|
||||
|
||||
let key = BatchKey::new(
|
||||
|
@ -1580,11 +1612,9 @@ impl AlphaBatchBuilder {
|
|||
);
|
||||
}
|
||||
PictureCompositeMode::Blit(_) => {
|
||||
let surface = ctx.surfaces[raster_config.surface_index.0]
|
||||
.surface
|
||||
.as_ref()
|
||||
.expect("bug: surface must be allocated by now");
|
||||
let cache_task_id = surface.resolve_render_task_id();
|
||||
let cache_task_id = surface
|
||||
.expect("bug: surface must be allocated by now")
|
||||
.resolve_render_task_id();
|
||||
let uv_rect_address = render_tasks[cache_task_id]
|
||||
.get_texture_address(gpu_cache)
|
||||
.as_int();
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
use super::super::shader_source::SHADERS;
|
||||
use api::{ColorF, ImageDescriptor, ImageFormat, MemoryReport};
|
||||
use api::{TextureTarget, VoidPtrToSizeFn};
|
||||
use api::{MixBlendMode, TextureTarget, VoidPtrToSizeFn};
|
||||
use api::units::*;
|
||||
use euclid::Transform3D;
|
||||
use gleam::gl;
|
||||
|
@ -3052,6 +3052,31 @@ impl Device {
|
|||
self.gl.blend_equation(gl::FUNC_ADD);
|
||||
}
|
||||
|
||||
pub fn set_blend_mode_advanced(&self, mode: MixBlendMode) {
|
||||
self.gl.blend_equation(match mode {
|
||||
MixBlendMode::Normal => {
|
||||
// blend factor only make sense for the normal mode
|
||||
self.gl.blend_func_separate(gl::ZERO, gl::SRC_COLOR, gl::ZERO, gl::SRC_ALPHA);
|
||||
gl::FUNC_ADD
|
||||
},
|
||||
MixBlendMode::Multiply => gl::MULTIPLY_KHR,
|
||||
MixBlendMode::Screen => gl::SCREEN_KHR,
|
||||
MixBlendMode::Overlay => gl::OVERLAY_KHR,
|
||||
MixBlendMode::Darken => gl::DARKEN_KHR,
|
||||
MixBlendMode::Lighten => gl::LIGHTEN_KHR,
|
||||
MixBlendMode::ColorDodge => gl::COLORDODGE_KHR,
|
||||
MixBlendMode::ColorBurn => gl::COLORBURN_KHR,
|
||||
MixBlendMode::HardLight => gl::HARDLIGHT_KHR,
|
||||
MixBlendMode::SoftLight => gl::SOFTLIGHT_KHR,
|
||||
MixBlendMode::Difference => gl::DIFFERENCE_KHR,
|
||||
MixBlendMode::Exclusion => gl::EXCLUSION_KHR,
|
||||
MixBlendMode::Hue => gl::HSL_HUE_KHR,
|
||||
MixBlendMode::Saturation => gl::HSL_SATURATION_KHR,
|
||||
MixBlendMode::Color => gl::HSL_COLOR_KHR,
|
||||
MixBlendMode::Luminosity => gl::HSL_LUMINOSITY_KHR,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn supports_extension(&self, extension: &str) -> bool {
|
||||
supports_extension(&self.extensions, extension)
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ impl Default for ChasePrimitive {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub struct FrameBuilderConfig {
|
||||
|
@ -58,6 +58,8 @@ pub struct FrameBuilderConfig {
|
|||
/// True if we're running tests (i.e. via wrench).
|
||||
pub testing: bool,
|
||||
pub gpu_supports_fast_clears: bool,
|
||||
pub gpu_supports_advanced_blend: bool,
|
||||
pub advanced_blend_is_coherent: bool,
|
||||
}
|
||||
|
||||
/// A set of common / global resources that are retained between
|
||||
|
@ -130,6 +132,7 @@ pub struct FrameVisibilityState<'a> {
|
|||
pub retained_tiles: &'a mut RetainedTiles,
|
||||
pub data_stores: &'a mut DataStores,
|
||||
pub clip_chain_stack: ClipChainStack,
|
||||
pub render_tasks: &'a mut RenderTaskTree,
|
||||
}
|
||||
|
||||
pub struct FrameBuildingContext<'a> {
|
||||
|
@ -178,7 +181,6 @@ impl<'a> FrameBuildingState<'a> {
|
|||
pub struct PictureContext {
|
||||
pub pic_index: PictureIndex,
|
||||
pub apply_local_clip_rect: bool,
|
||||
pub allow_subpixel_aa: bool,
|
||||
pub is_passthrough: bool,
|
||||
pub is_composite: bool,
|
||||
pub raster_space: RasterSpace,
|
||||
|
@ -221,6 +223,8 @@ impl FrameBuilder {
|
|||
enable_picture_caching: false,
|
||||
testing: false,
|
||||
gpu_supports_fast_clears: false,
|
||||
gpu_supports_advanced_blend: false,
|
||||
advanced_blend_is_coherent: false,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -343,6 +347,7 @@ impl FrameBuilder {
|
|||
screen_world_rect,
|
||||
clip_scroll_tree,
|
||||
global_device_pixel_scale,
|
||||
true,
|
||||
);
|
||||
surfaces.push(root_surface);
|
||||
|
||||
|
@ -390,6 +395,7 @@ impl FrameBuilder {
|
|||
retained_tiles: &mut retained_tiles,
|
||||
data_stores,
|
||||
clip_chain_stack: ClipChainStack::new(),
|
||||
render_tasks,
|
||||
};
|
||||
|
||||
self.prim_store.update_visibility(
|
||||
|
@ -430,7 +436,6 @@ impl FrameBuilder {
|
|||
root_spatial_node_index,
|
||||
root_spatial_node_index,
|
||||
ROOT_SURFACE_INDEX,
|
||||
true,
|
||||
&mut frame_state,
|
||||
&frame_context,
|
||||
)
|
||||
|
@ -583,6 +588,8 @@ impl FrameBuilder {
|
|||
prim_store: &self.prim_store,
|
||||
resource_cache,
|
||||
use_dual_source_blending,
|
||||
use_advanced_blending: self.config.gpu_supports_advanced_blend,
|
||||
break_advanced_blend_batches: !self.config.advanced_blend_is_coherent,
|
||||
clip_scroll_tree,
|
||||
data_stores,
|
||||
surfaces: &surfaces,
|
||||
|
|
|
@ -1801,6 +1801,8 @@ pub struct SurfaceInfo {
|
|||
pub inflation_factor: f32,
|
||||
/// The device pixel ratio specific to this surface.
|
||||
pub device_pixel_scale: DevicePixelScale,
|
||||
/// If true, subpixel AA rendering can be used on this surface.
|
||||
pub allow_subpixel_aa: bool,
|
||||
}
|
||||
|
||||
impl SurfaceInfo {
|
||||
|
@ -1811,6 +1813,7 @@ impl SurfaceInfo {
|
|||
world_rect: WorldRect,
|
||||
clip_scroll_tree: &ClipScrollTree,
|
||||
device_pixel_scale: DevicePixelScale,
|
||||
allow_subpixel_aa: bool,
|
||||
) -> Self {
|
||||
let map_surface_to_world = SpaceMapper::new_with_target(
|
||||
ROOT_SPATIAL_NODE_INDEX,
|
||||
|
@ -1837,6 +1840,7 @@ impl SurfaceInfo {
|
|||
tasks: Vec::new(),
|
||||
inflation_factor,
|
||||
device_pixel_scale,
|
||||
allow_subpixel_aa,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2345,7 +2349,6 @@ impl PicturePrimitive {
|
|||
surface_spatial_node_index: SpatialNodeIndex,
|
||||
raster_spatial_node_index: SpatialNodeIndex,
|
||||
surface_index: SurfaceIndex,
|
||||
parent_allows_subpixel_aa: bool,
|
||||
frame_state: &mut FrameBuildingState,
|
||||
frame_context: &FrameBuildingContext,
|
||||
) -> Option<(PictureContext, PictureState, PrimitiveList)> {
|
||||
|
@ -2420,23 +2423,17 @@ impl PicturePrimitive {
|
|||
plane_splitter,
|
||||
};
|
||||
|
||||
// Disallow subpixel AA if an intermediate surface is needed.
|
||||
// TODO(lsalzman): allow overriding parent if intermediate surface is opaque
|
||||
let (allow_subpixel_aa, is_composite, is_passthrough) = match self.raster_config {
|
||||
Some(RasterConfig { composite_mode: PictureCompositeMode::TileCache { clear_color, .. }, .. }) => {
|
||||
// If the tile cache has an opaque background, then it's fine to use
|
||||
// subpixel rendering (this is the common case).
|
||||
(clear_color.a >= 1.0, false, false)
|
||||
let (is_composite, is_passthrough) = match self.raster_config {
|
||||
Some(RasterConfig { composite_mode: PictureCompositeMode::TileCache { .. }, .. }) => {
|
||||
(false, false)
|
||||
},
|
||||
Some(_) => {
|
||||
(false, true, false)
|
||||
(true, false)
|
||||
}
|
||||
None => {
|
||||
(true, false, true)
|
||||
(false, true)
|
||||
}
|
||||
};
|
||||
// Still disable subpixel AA if parent forbids it
|
||||
let allow_subpixel_aa = parent_allows_subpixel_aa && allow_subpixel_aa;
|
||||
|
||||
let mut dirty_region_count = 0;
|
||||
|
||||
|
@ -2460,7 +2457,6 @@ impl PicturePrimitive {
|
|||
let context = PictureContext {
|
||||
pic_index,
|
||||
apply_local_clip_rect: self.apply_local_clip_rect,
|
||||
allow_subpixel_aa,
|
||||
is_composite,
|
||||
is_passthrough,
|
||||
raster_space: self.requested_raster_space,
|
||||
|
@ -2685,7 +2681,10 @@ impl PicturePrimitive {
|
|||
|
||||
if let Some(composite_mode) = actual_composite_mode {
|
||||
// Retrieve the positioning node information for the parent surface.
|
||||
let parent_raster_node_index = state.current_surface().raster_spatial_node_index;
|
||||
let (parent_raster_node_index, parent_allows_subpixel_aa)= {
|
||||
let parent_surface = state.current_surface();
|
||||
(parent_surface.raster_spatial_node_index, parent_surface.allow_subpixel_aa)
|
||||
};
|
||||
let surface_spatial_node_index = self.spatial_node_index;
|
||||
|
||||
// This inflation factor is to be applied to all primitives within the surface.
|
||||
|
@ -2712,6 +2711,24 @@ impl PicturePrimitive {
|
|||
.get_relative_transform(surface_spatial_node_index, parent_raster_node_index)
|
||||
.is_perspective;
|
||||
|
||||
// Disallow subpixel AA if an intermediate surface is needed.
|
||||
// TODO(lsalzman): allow overriding parent if intermediate surface is opaque
|
||||
let allow_subpixel_aa = match composite_mode {
|
||||
PictureCompositeMode::TileCache { clear_color, .. } => {
|
||||
// If the tile cache has an opaque background, then it's fine to use
|
||||
// subpixel rendering (this is the common case).
|
||||
clear_color.a >= 1.0
|
||||
}
|
||||
PictureCompositeMode::Blit(..) |
|
||||
PictureCompositeMode::ComponentTransferFilter(..) |
|
||||
PictureCompositeMode::Filter(..) |
|
||||
PictureCompositeMode::MixBlend(..) => {
|
||||
false
|
||||
}
|
||||
};
|
||||
// Still disable subpixel AA if parent forbids it
|
||||
let allow_subpixel_aa = parent_allows_subpixel_aa && allow_subpixel_aa;
|
||||
|
||||
let surface = SurfaceInfo::new(
|
||||
surface_spatial_node_index,
|
||||
if establishes_raster_root {
|
||||
|
@ -2723,6 +2740,7 @@ impl PicturePrimitive {
|
|||
frame_context.screen_world_rect,
|
||||
&frame_context.clip_scroll_tree,
|
||||
frame_context.global_device_pixel_scale,
|
||||
allow_subpixel_aa,
|
||||
);
|
||||
|
||||
self.raster_config = Some(RasterConfig {
|
||||
|
@ -3085,7 +3103,7 @@ impl PicturePrimitive {
|
|||
|
||||
PictureSurface::RenderTask(render_task_id)
|
||||
}
|
||||
PictureCompositeMode::MixBlend(..) => {
|
||||
PictureCompositeMode::MixBlend(..) if !frame_context.fb_config.gpu_supports_advanced_blend => {
|
||||
let uv_rect_kind = calculate_uv_rect_kind(
|
||||
&pic_rect,
|
||||
&transform,
|
||||
|
@ -3175,6 +3193,7 @@ impl PicturePrimitive {
|
|||
frame_state.surfaces[surface_index.0].tasks.push(render_task_id);
|
||||
PictureSurface::RenderTask(render_task_id)
|
||||
}
|
||||
PictureCompositeMode::MixBlend(..) |
|
||||
PictureCompositeMode::Blit(_) => {
|
||||
// The SplitComposite shader used for 3d contexts doesn't snap
|
||||
// to pixels, so we shouldn't snap our uv coordinates either.
|
||||
|
|
|
@ -6,7 +6,7 @@ use api::{BorderRadius, ClipMode, ColorF};
|
|||
use api::{FilterOp, ImageRendering, RepeatMode};
|
||||
use api::{PremultipliedColorF, PropertyBinding, Shadow, GradientStop};
|
||||
use api::{BoxShadowClipMode, LineStyle, LineOrientation};
|
||||
use api::PrimitiveKeyKind;
|
||||
use api::{PrimitiveKeyKind, RasterSpace};
|
||||
use api::units::*;
|
||||
use border::{get_max_scale_for_border, build_border_instances};
|
||||
use border::BorderSegmentCacheKey;
|
||||
|
@ -26,7 +26,7 @@ use gpu_types::{BrushFlags, SnapOffsets};
|
|||
use image::{Repetition};
|
||||
use intern;
|
||||
use malloc_size_of::MallocSizeOf;
|
||||
use picture::{PictureCompositeMode, PicturePrimitive};
|
||||
use picture::{PictureCompositeMode, PicturePrimitive, SurfaceInfo};
|
||||
use picture::{ClusterIndex, PrimitiveList, RecordedDirtyRegion, SurfaceIndex, RetainedTiles, RasterConfig};
|
||||
use prim_store::borders::{ImageBorderDataHandle, NormalBorderDataHandle};
|
||||
use prim_store::gradient::{GRADIENT_FP_STOPS, GradientCacheKey, GradientStopKey};
|
||||
|
@ -1723,7 +1723,7 @@ impl PrimitiveStore {
|
|||
frame_context: &FrameVisibilityContext,
|
||||
frame_state: &mut FrameVisibilityState,
|
||||
) {
|
||||
let (mut prim_list, surface_index, apply_local_clip_rect) = {
|
||||
let (mut prim_list, surface_index, apply_local_clip_rect, raster_space) = {
|
||||
let pic = &mut self.pictures[pic_index.0];
|
||||
|
||||
let prim_list = mem::replace(&mut pic.prim_list, PrimitiveList::empty());
|
||||
|
@ -1748,7 +1748,7 @@ impl PrimitiveStore {
|
|||
frame_state.tile_cache = Some(tile_cache);
|
||||
}
|
||||
|
||||
(prim_list, surface_index, pic.apply_local_clip_rect)
|
||||
(prim_list, surface_index, pic.apply_local_clip_rect, pic.requested_raster_space)
|
||||
};
|
||||
|
||||
let surface = &frame_context.surfaces[surface_index.0 as usize];
|
||||
|
@ -2009,6 +2009,14 @@ impl PrimitiveStore {
|
|||
}
|
||||
);
|
||||
|
||||
self.request_resources_for_prim(
|
||||
prim_instance,
|
||||
surface,
|
||||
raster_space,
|
||||
frame_context,
|
||||
frame_state,
|
||||
);
|
||||
|
||||
prim_instance.visibility_info = vis_index;
|
||||
}
|
||||
|
||||
|
@ -2033,6 +2041,45 @@ impl PrimitiveStore {
|
|||
pic.prim_list = prim_list;
|
||||
}
|
||||
|
||||
fn request_resources_for_prim(
|
||||
&mut self,
|
||||
prim_instance: &PrimitiveInstance,
|
||||
surface: &SurfaceInfo,
|
||||
raster_space: RasterSpace,
|
||||
frame_context: &FrameVisibilityContext,
|
||||
frame_state: &mut FrameVisibilityState,
|
||||
) {
|
||||
match prim_instance.kind {
|
||||
PrimitiveInstanceKind::TextRun { data_handle, run_index, .. } => {
|
||||
let prim_data = &mut frame_state.data_stores.text_run[data_handle];
|
||||
let run = &mut self.text_runs[run_index];
|
||||
|
||||
// The transform only makes sense for screen space rasterization
|
||||
let relative_transform = frame_context
|
||||
.clip_scroll_tree
|
||||
.get_relative_transform(
|
||||
prim_instance.spatial_node_index,
|
||||
ROOT_SPATIAL_NODE_INDEX,
|
||||
);
|
||||
let prim_offset = prim_instance.prim_origin.to_vector() - run.reference_frame_relative_offset;
|
||||
|
||||
run.request_resources(
|
||||
prim_offset,
|
||||
&prim_data.font,
|
||||
&prim_data.glyphs,
|
||||
&relative_transform.flattened.with_destination::<WorldPixel>(),
|
||||
surface,
|
||||
raster_space,
|
||||
frame_state.resource_cache,
|
||||
frame_state.gpu_cache,
|
||||
frame_state.render_tasks,
|
||||
frame_state.scratch,
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_opacity_binding(
|
||||
&self,
|
||||
opacity_binding_index: OpacityBindingIndex,
|
||||
|
@ -2184,7 +2231,6 @@ impl PrimitiveStore {
|
|||
pic_context.surface_spatial_node_index,
|
||||
pic_context.raster_spatial_node_index,
|
||||
pic_context.surface_index,
|
||||
pic_context.allow_subpixel_aa,
|
||||
frame_state,
|
||||
frame_context,
|
||||
) {
|
||||
|
@ -2507,39 +2553,12 @@ impl PrimitiveStore {
|
|||
));
|
||||
}
|
||||
}
|
||||
PrimitiveInstanceKind::TextRun { data_handle, run_index, .. } => {
|
||||
PrimitiveInstanceKind::TextRun { data_handle, .. } => {
|
||||
let prim_data = &mut data_stores.text_run[*data_handle];
|
||||
let run = &mut self.text_runs[*run_index];
|
||||
|
||||
// Update the template this instane references, which may refresh the GPU
|
||||
// cache with any shared template data.
|
||||
prim_data.update(frame_state);
|
||||
|
||||
// The transform only makes sense for screen space rasterization
|
||||
let relative_transform = frame_context
|
||||
.clip_scroll_tree
|
||||
.get_relative_transform(
|
||||
prim_instance.spatial_node_index,
|
||||
ROOT_SPATIAL_NODE_INDEX,
|
||||
);
|
||||
let prim_offset = prim_instance.prim_origin.to_vector() - run.reference_frame_relative_offset;
|
||||
|
||||
// TODO(gw): This match is a bit untidy, but it should disappear completely
|
||||
// once the prepare_prims and batching are unified. When that
|
||||
// happens, we can use the cache handle immediately, and not need
|
||||
// to temporarily store it in the primitive instance.
|
||||
run.prepare_for_render(
|
||||
prim_offset,
|
||||
&prim_data.font,
|
||||
&prim_data.glyphs,
|
||||
device_pixel_scale,
|
||||
&relative_transform.flattened.with_destination::<WorldPixel>(),
|
||||
pic_context,
|
||||
frame_state.resource_cache,
|
||||
frame_state.gpu_cache,
|
||||
frame_state.render_tasks,
|
||||
scratch,
|
||||
);
|
||||
}
|
||||
PrimitiveInstanceKind::Clear { data_handle, .. } => {
|
||||
let prim_data = &mut data_stores.prim[*data_handle];
|
||||
|
|
|
@ -5,11 +5,12 @@
|
|||
use api::{ColorF, GlyphInstance, RasterSpace, Shadow};
|
||||
use api::units::{DevicePixelScale, LayoutToWorldTransform, LayoutVector2D};
|
||||
use display_list_flattener::{CreateShadow, IsVisible};
|
||||
use frame_builder::{FrameBuildingState, PictureContext};
|
||||
use frame_builder::FrameBuildingState;
|
||||
use glyph_rasterizer::{FontInstance, FontTransform, GlyphKey, FONT_SIZE_LIMIT};
|
||||
use gpu_cache::GpuCache;
|
||||
use intern;
|
||||
use internal_types::LayoutPrimitiveInfo;
|
||||
use picture::SurfaceInfo;
|
||||
use prim_store::{PrimitiveOpacity, PrimitiveSceneData, PrimitiveScratchBuffer};
|
||||
use prim_store::{PrimitiveStore, PrimKeyCommonData, PrimTemplateCommonData};
|
||||
use render_task::{RenderTaskTree};
|
||||
|
@ -193,7 +194,7 @@ impl CreateShadow for TextRun {
|
|||
TextRun {
|
||||
font,
|
||||
glyphs: self.glyphs.clone(),
|
||||
shadow: true
|
||||
shadow: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -282,25 +283,27 @@ impl TextRunPrimitive {
|
|||
cache_dirty
|
||||
}
|
||||
|
||||
pub fn prepare_for_render(
|
||||
pub fn request_resources(
|
||||
&mut self,
|
||||
prim_offset: LayoutVector2D,
|
||||
specified_font: &FontInstance,
|
||||
glyphs: &[GlyphInstance],
|
||||
device_pixel_scale: DevicePixelScale,
|
||||
transform: &LayoutToWorldTransform,
|
||||
pic_context: &PictureContext,
|
||||
surface: &SurfaceInfo,
|
||||
raster_space: RasterSpace,
|
||||
resource_cache: &mut ResourceCache,
|
||||
gpu_cache: &mut GpuCache,
|
||||
render_tasks: &mut RenderTaskTree,
|
||||
scratch: &mut PrimitiveScratchBuffer,
|
||||
) {
|
||||
let device_pixel_scale = surface.device_pixel_scale;
|
||||
|
||||
let cache_dirty = self.update_font_instance(
|
||||
specified_font,
|
||||
device_pixel_scale,
|
||||
transform,
|
||||
pic_context.allow_subpixel_aa,
|
||||
pic_context.raster_space,
|
||||
surface.allow_subpixel_aa,
|
||||
raster_space,
|
||||
);
|
||||
|
||||
if self.glyph_keys_range.is_empty() || cache_dirty {
|
||||
|
|
|
@ -267,12 +267,6 @@ impl RenderTaskTree {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn prepare_for_render(&mut self) {
|
||||
for task in &mut self.tasks {
|
||||
task.prepare_for_render();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_task_address(&self, id: RenderTaskId) -> RenderTaskAddress {
|
||||
#[cfg(debug_assertions)]
|
||||
debug_assert_eq!(self.frame_id, id.frame_id);
|
||||
|
@ -1210,13 +1204,6 @@ impl RenderTask {
|
|||
}
|
||||
}
|
||||
|
||||
// Optionally, prepare the render task for drawing. This is executed
|
||||
// after all resource cache items (textures and glyphs) have been
|
||||
// resolved and can be queried. It also allows certain render tasks
|
||||
// to defer calculating an exact size until now, if desired.
|
||||
pub fn prepare_for_render(&mut self) {
|
||||
}
|
||||
|
||||
pub fn write_gpu_blocks(
|
||||
&mut self,
|
||||
gpu_cache: &mut GpuCache,
|
||||
|
@ -1357,7 +1344,6 @@ pub struct RenderTaskCacheKey {
|
|||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub struct RenderTaskCacheEntry {
|
||||
pending_render_task_id: Option<RenderTaskId>,
|
||||
user_data: Option<[f32; 3]>,
|
||||
is_opaque: bool,
|
||||
pub handle: TextureCacheHandle,
|
||||
|
@ -1423,82 +1409,74 @@ impl RenderTaskCache {
|
|||
});
|
||||
}
|
||||
|
||||
pub fn update(
|
||||
&mut self,
|
||||
fn alloc_render_task(
|
||||
entry: &mut RenderTaskCacheEntry,
|
||||
render_task_id: RenderTaskId,
|
||||
gpu_cache: &mut GpuCache,
|
||||
texture_cache: &mut TextureCache,
|
||||
render_tasks: &mut RenderTaskTree,
|
||||
) {
|
||||
// Iterate the list of render task cache entries,
|
||||
// and allocate / update the texture cache location
|
||||
// if the entry has been evicted or not yet allocated.
|
||||
for (_, handle) in &self.map {
|
||||
let entry = self.cache_entries.get_mut(handle);
|
||||
let render_task = &mut render_tasks[render_task_id];
|
||||
let target_kind = render_task.target_kind();
|
||||
|
||||
if let Some(pending_render_task_id) = entry.pending_render_task_id.take() {
|
||||
let render_task = &mut render_tasks[pending_render_task_id];
|
||||
let target_kind = render_task.target_kind();
|
||||
|
||||
// Find out what size to alloc in the texture cache.
|
||||
let size = match render_task.location {
|
||||
RenderTaskLocation::Fixed(..) |
|
||||
RenderTaskLocation::TextureCache { .. } => {
|
||||
panic!("BUG: dynamic task was expected");
|
||||
}
|
||||
RenderTaskLocation::Dynamic(_, size) => size,
|
||||
};
|
||||
|
||||
// Select the right texture page to allocate from.
|
||||
let image_format = match target_kind {
|
||||
RenderTargetKind::Color => ImageFormat::BGRA8,
|
||||
RenderTargetKind::Alpha => ImageFormat::R8,
|
||||
};
|
||||
|
||||
let descriptor = ImageDescriptor::new(
|
||||
size.width,
|
||||
size.height,
|
||||
image_format,
|
||||
entry.is_opaque,
|
||||
false,
|
||||
);
|
||||
|
||||
// Allocate space in the texture cache, but don't supply
|
||||
// and CPU-side data to be uploaded.
|
||||
//
|
||||
// Note that we currently use Eager eviction for cached render
|
||||
// tasks, which means that any cached item not used in the last
|
||||
// frame is discarded. There's room to be a lot smarter here,
|
||||
// especially by considering the relative costs of re-rendering
|
||||
// each type of item (box shadow blurs are an order of magnitude
|
||||
// more expensive than borders, for example). Telemetry could
|
||||
// inform our decisions here as well.
|
||||
texture_cache.update(
|
||||
&mut entry.handle,
|
||||
descriptor,
|
||||
TextureFilter::Linear,
|
||||
None,
|
||||
entry.user_data.unwrap_or([0.0; 3]),
|
||||
DirtyRect::All,
|
||||
gpu_cache,
|
||||
None,
|
||||
render_task.uv_rect_kind(),
|
||||
Eviction::Eager,
|
||||
);
|
||||
|
||||
// Get the allocation details in the texture cache, and store
|
||||
// this in the render task. The renderer will draw this
|
||||
// task into the appropriate layer and rect of the texture
|
||||
// cache on this frame.
|
||||
let (texture_id, texture_layer, uv_rect, _) =
|
||||
texture_cache.get_cache_location(&entry.handle);
|
||||
|
||||
render_task.location = RenderTaskLocation::TextureCache {
|
||||
texture: texture_id,
|
||||
layer: texture_layer,
|
||||
rect: uv_rect.to_i32(),
|
||||
};
|
||||
// Find out what size to alloc in the texture cache.
|
||||
let size = match render_task.location {
|
||||
RenderTaskLocation::Fixed(..) |
|
||||
RenderTaskLocation::TextureCache { .. } => {
|
||||
panic!("BUG: dynamic task was expected");
|
||||
}
|
||||
}
|
||||
RenderTaskLocation::Dynamic(_, size) => size,
|
||||
};
|
||||
|
||||
// Select the right texture page to allocate from.
|
||||
let image_format = match target_kind {
|
||||
RenderTargetKind::Color => ImageFormat::BGRA8,
|
||||
RenderTargetKind::Alpha => ImageFormat::R8,
|
||||
};
|
||||
|
||||
let descriptor = ImageDescriptor::new(
|
||||
size.width,
|
||||
size.height,
|
||||
image_format,
|
||||
entry.is_opaque,
|
||||
false,
|
||||
);
|
||||
|
||||
// Allocate space in the texture cache, but don't supply
|
||||
// and CPU-side data to be uploaded.
|
||||
//
|
||||
// Note that we currently use Eager eviction for cached render
|
||||
// tasks, which means that any cached item not used in the last
|
||||
// frame is discarded. There's room to be a lot smarter here,
|
||||
// especially by considering the relative costs of re-rendering
|
||||
// each type of item (box shadow blurs are an order of magnitude
|
||||
// more expensive than borders, for example). Telemetry could
|
||||
// inform our decisions here as well.
|
||||
texture_cache.update(
|
||||
&mut entry.handle,
|
||||
descriptor,
|
||||
TextureFilter::Linear,
|
||||
None,
|
||||
entry.user_data.unwrap_or([0.0; 3]),
|
||||
DirtyRect::All,
|
||||
gpu_cache,
|
||||
None,
|
||||
render_task.uv_rect_kind(),
|
||||
Eviction::Eager,
|
||||
);
|
||||
|
||||
// Get the allocation details in the texture cache, and store
|
||||
// this in the render task. The renderer will draw this
|
||||
// task into the appropriate layer and rect of the texture
|
||||
// cache on this frame.
|
||||
let (texture_id, texture_layer, uv_rect, _) =
|
||||
texture_cache.get_cache_location(&entry.handle);
|
||||
|
||||
render_task.location = RenderTaskLocation::TextureCache {
|
||||
texture: texture_id,
|
||||
layer: texture_layer,
|
||||
rect: uv_rect.to_i32(),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn request_render_task<F>(
|
||||
|
@ -1520,7 +1498,6 @@ impl RenderTaskCache {
|
|||
let entry_handle = self.map.entry(key).or_insert_with(|| {
|
||||
let entry = RenderTaskCacheEntry {
|
||||
handle: TextureCacheHandle::invalid(),
|
||||
pending_render_task_id: None,
|
||||
user_data,
|
||||
is_opaque,
|
||||
};
|
||||
|
@ -1528,18 +1505,23 @@ impl RenderTaskCache {
|
|||
});
|
||||
let cache_entry = cache_entries.get_mut(entry_handle);
|
||||
|
||||
if cache_entry.pending_render_task_id.is_none() {
|
||||
// Check if this texture cache handle is valid.
|
||||
if texture_cache.request(&cache_entry.handle, gpu_cache) {
|
||||
// Invoke user closure to get render task chain
|
||||
// to draw this into the texture cache.
|
||||
let render_task_id = f(render_tasks)?;
|
||||
render_tasks.cacheable_render_tasks.push(render_task_id);
|
||||
// Check if this texture cache handle is valid.
|
||||
if texture_cache.request(&cache_entry.handle, gpu_cache) {
|
||||
// Invoke user closure to get render task chain
|
||||
// to draw this into the texture cache.
|
||||
let render_task_id = f(render_tasks)?;
|
||||
render_tasks.cacheable_render_tasks.push(render_task_id);
|
||||
|
||||
cache_entry.pending_render_task_id = Some(render_task_id);
|
||||
cache_entry.user_data = user_data;
|
||||
cache_entry.is_opaque = is_opaque;
|
||||
}
|
||||
cache_entry.user_data = user_data;
|
||||
cache_entry.is_opaque = is_opaque;
|
||||
|
||||
RenderTaskCache::alloc_render_task(
|
||||
cache_entry,
|
||||
render_task_id,
|
||||
gpu_cache,
|
||||
texture_cache,
|
||||
render_tasks,
|
||||
);
|
||||
}
|
||||
|
||||
Ok(entry_handle.weak())
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
//! up the scissor, are accepting already transformed coordinates, which we can get by
|
||||
//! calling `DrawTarget::to_framebuffer_rect`
|
||||
|
||||
use api::{ApiMsg, BlobImageHandler, ColorF, ColorU};
|
||||
use api::{ApiMsg, BlobImageHandler, ColorF, ColorU, MixBlendMode};
|
||||
use api::{DocumentId, Epoch, ExternalImageId};
|
||||
use api::{ExternalImageType, FontRenderMode, FrameMsg, ImageFormat, PipelineId};
|
||||
use api::{ImageRendering, Checkpoint, NotificationRequest};
|
||||
|
@ -1114,6 +1114,7 @@ pub enum BlendMode {
|
|||
SubpixelDualSource,
|
||||
SubpixelConstantTextColor(ColorF),
|
||||
SubpixelWithBgColor,
|
||||
Advanced(MixBlendMode),
|
||||
}
|
||||
|
||||
/// Tracks the state of each row in the GPU cache texture.
|
||||
|
@ -1864,6 +1865,8 @@ pub struct Renderer {
|
|||
|
||||
clear_color: Option<ColorF>,
|
||||
enable_clear_scissor: bool,
|
||||
enable_advanced_blend_barriers: bool,
|
||||
|
||||
debug: LazyInitializedDebugRenderer,
|
||||
debug_flags: DebugFlags,
|
||||
backend_profile_counters: BackendProfileCounters,
|
||||
|
@ -2022,10 +2025,15 @@ impl Renderer {
|
|||
};
|
||||
let use_dual_source_blending =
|
||||
supports_dual_source_blending &&
|
||||
!options.disable_dual_source_blending &&
|
||||
options.allow_dual_source_blending &&
|
||||
// If using pixel local storage, subpixel AA isn't supported (we disable it on all
|
||||
// mobile devices explicitly anyway).
|
||||
!device.get_capabilities().supports_pixel_local_storage;
|
||||
let ext_blend_equation_advanced =
|
||||
options.allow_advanced_blend_equation &&
|
||||
device.supports_extension("GL_KHR_blend_equation_advanced");
|
||||
let ext_blend_equation_advanced_coherent =
|
||||
device.supports_extension("GL_KHR_blend_equation_advanced_coherent");
|
||||
|
||||
// 512 is the minimum that the texture cache can work with.
|
||||
const MIN_TEXTURE_SIZE: i32 = 512;
|
||||
|
@ -2201,7 +2209,10 @@ impl Renderer {
|
|||
enable_picture_caching: options.enable_picture_caching,
|
||||
testing: options.testing,
|
||||
gpu_supports_fast_clears: options.gpu_supports_fast_clears,
|
||||
gpu_supports_advanced_blend: ext_blend_equation_advanced,
|
||||
advanced_blend_is_coherent: ext_blend_equation_advanced_coherent,
|
||||
};
|
||||
info!("WR {:?}", config);
|
||||
|
||||
let device_pixel_ratio = options.device_pixel_ratio;
|
||||
let debug_flags = options.debug_flags;
|
||||
|
@ -2377,6 +2388,7 @@ impl Renderer {
|
|||
max_recorded_profiles: options.max_recorded_profiles,
|
||||
clear_color: options.clear_color,
|
||||
enable_clear_scissor: options.enable_clear_scissor,
|
||||
enable_advanced_blend_barriers: !ext_blend_equation_advanced_coherent,
|
||||
last_time: 0,
|
||||
gpu_profile,
|
||||
gpu_glyph_renderer,
|
||||
|
@ -3899,6 +3911,12 @@ impl Renderer {
|
|||
self.device.set_blend_mode_subpixel_with_bg_color_pass0();
|
||||
self.device.switch_mode(ShaderColorMode::SubpixelWithBgColorPass0 as _);
|
||||
}
|
||||
BlendMode::Advanced(mode) => {
|
||||
if self.enable_advanced_blend_barriers {
|
||||
self.device.gl().blend_barrier_khr();
|
||||
}
|
||||
self.device.set_blend_mode_advanced(mode);
|
||||
}
|
||||
}
|
||||
prev_blend_mode = batch.key.blend_mode;
|
||||
}
|
||||
|
@ -5602,7 +5620,6 @@ pub struct RendererOptions {
|
|||
pub cached_programs: Option<Rc<ProgramCache>>,
|
||||
pub debug_flags: DebugFlags,
|
||||
pub renderer_id: Option<u64>,
|
||||
pub disable_dual_source_blending: bool,
|
||||
pub scene_builder_hooks: Option<Box<SceneBuilderHooks + Send>>,
|
||||
pub sampler: Option<Box<AsyncPropertySampler + Send>>,
|
||||
pub chase_primitive: ChasePrimitive,
|
||||
|
@ -5615,6 +5632,8 @@ pub struct RendererOptions {
|
|||
/// it is a performance win. The default is false, which tends to be best
|
||||
/// performance on lower end / integrated GPUs.
|
||||
pub gpu_supports_fast_clears: bool,
|
||||
pub allow_dual_source_blending: bool,
|
||||
pub allow_advanced_blend_equation: bool,
|
||||
/// If true, allow WR to use pixel local storage if the device supports it.
|
||||
/// For now, this defaults to false since the code is still experimental
|
||||
/// and not complete. This option will probably be removed once support is
|
||||
|
@ -5652,7 +5671,6 @@ impl Default for RendererOptions {
|
|||
enclosing_size_of_op: None,
|
||||
renderer_id: None,
|
||||
cached_programs: None,
|
||||
disable_dual_source_blending: false,
|
||||
scene_builder_hooks: None,
|
||||
sampler: None,
|
||||
chase_primitive: ChasePrimitive::Nothing,
|
||||
|
@ -5661,6 +5679,8 @@ impl Default for RendererOptions {
|
|||
enable_picture_caching: false,
|
||||
testing: false,
|
||||
gpu_supports_fast_clears: false,
|
||||
allow_dual_source_blending: false,
|
||||
allow_advanced_blend_equation: false,
|
||||
allow_pixel_local_storage_support: false,
|
||||
// For backwards compatibility we set this to true by default, so
|
||||
// that if the debugger feature is enabled, the debug server will
|
||||
|
|
|
@ -1614,12 +1614,6 @@ impl ResourceCache {
|
|||
|
||||
// Apply any updates of new / updated images (incl. blobs) to the texture cache.
|
||||
self.update_texture_cache(gpu_cache);
|
||||
render_tasks.prepare_for_render();
|
||||
self.cached_render_tasks.update(
|
||||
gpu_cache,
|
||||
&mut self.texture_cache,
|
||||
render_tasks,
|
||||
);
|
||||
}
|
||||
|
||||
fn rasterize_missing_blob_images(&mut self) {
|
||||
|
|
|
@ -341,7 +341,8 @@ impl BrushShader {
|
|||
BlendMode::PremultipliedAlpha |
|
||||
BlendMode::PremultipliedDestOut |
|
||||
BlendMode::SubpixelConstantTextColor(..) |
|
||||
BlendMode::SubpixelWithBgColor => &mut self.alpha,
|
||||
BlendMode::SubpixelWithBgColor |
|
||||
BlendMode::Advanced(_) => &mut self.alpha,
|
||||
BlendMode::SubpixelDualSource => {
|
||||
self.dual_source
|
||||
.as_mut()
|
||||
|
@ -681,10 +682,10 @@ impl Shaders {
|
|||
options.precache_flags,
|
||||
)?;
|
||||
|
||||
let dual_source_precache_flags = if options.disable_dual_source_blending {
|
||||
ShaderPrecacheFlags::empty()
|
||||
} else {
|
||||
let dual_source_precache_flags = if options.allow_dual_source_blending {
|
||||
options.precache_flags
|
||||
} else {
|
||||
ShaderPrecacheFlags::empty()
|
||||
};
|
||||
|
||||
let ps_text_run_dual_source = TextShader::new("ps_text_run",
|
||||
|
@ -719,7 +720,7 @@ impl Shaders {
|
|||
device,
|
||||
&image_features,
|
||||
options.precache_flags,
|
||||
!options.disable_dual_source_blending,
|
||||
options.allow_dual_source_blending,
|
||||
use_pixel_local_storage,
|
||||
)?);
|
||||
}
|
||||
|
|
|
@ -56,6 +56,8 @@ pub struct RenderTargetContext<'a, 'rc> {
|
|||
pub prim_store: &'a PrimitiveStore,
|
||||
pub resource_cache: &'rc mut ResourceCache,
|
||||
pub use_dual_source_blending: bool,
|
||||
pub use_advanced_blending: bool,
|
||||
pub break_advanced_blend_batches: bool,
|
||||
pub clip_scroll_tree: &'a ClipScrollTree,
|
||||
pub data_stores: &'a DataStores,
|
||||
pub surfaces: &'a [SurfaceInfo],
|
||||
|
@ -432,6 +434,7 @@ impl RenderTarget for ColorRenderTarget {
|
|||
let mut batch_builder = AlphaBatchBuilder::new(
|
||||
self.screen_size,
|
||||
scisor_rect,
|
||||
ctx.break_advanced_blend_batches,
|
||||
);
|
||||
|
||||
batch_builder.add_pic_to_batch(
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
== multiply-2.yaml multiply-2-ref.yaml
|
||||
== color_targets(3) alpha_targets(0) multiply-3.yaml multiply-2-ref.yaml
|
||||
== difference.yaml difference-ref.yaml
|
||||
fuzzy(1,10000) == difference-transparent.yaml difference-transparent-ref.yaml
|
||||
fuzzy(1,30000) == difference-transparent.yaml difference-transparent-ref.yaml
|
||||
== darken.yaml darken-ref.yaml
|
||||
== lighten.yaml lighten-ref.yaml
|
||||
|
||||
|
|
Двоичные данные
gfx/wr/wrench/reftests/border/border-suite-2.png
Двоичные данные
gfx/wr/wrench/reftests/border/border-suite-2.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 48 KiB После Ширина: | Высота: | Размер: 48 KiB |
Двоичные данные
gfx/wr/wrench/reftests/boxshadow/box-shadow-cache.png
Двоичные данные
gfx/wr/wrench/reftests/boxshadow/box-shadow-cache.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 35 KiB После Ширина: | Высота: | Размер: 35 KiB |
|
@ -218,11 +218,12 @@ impl Wrench {
|
|||
max_recorded_profiles: 16,
|
||||
precache_flags,
|
||||
blob_image_handler: Some(Box::new(blob::CheckerboardRenderer::new(callbacks.clone()))),
|
||||
disable_dual_source_blending,
|
||||
chase_primitive,
|
||||
enable_picture_caching: true,
|
||||
testing: true,
|
||||
max_texture_size: Some(8196), // Needed for rawtest::test_resize_image.
|
||||
allow_dual_source_blending: !disable_dual_source_blending,
|
||||
allow_advanced_blend_equation: true,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
|
@ -286,11 +287,13 @@ impl Wrench {
|
|||
}
|
||||
|
||||
pub fn set_page_zoom(&mut self, zoom_factor: ZoomFactor) {
|
||||
self.page_zoom_factor = zoom_factor;
|
||||
let mut txn = Transaction::new();
|
||||
txn.set_page_zoom(self.page_zoom_factor);
|
||||
self.api.send_transaction(self.document_id, txn);
|
||||
self.set_title("");
|
||||
if self.page_zoom_factor.get() != zoom_factor.get() {
|
||||
self.page_zoom_factor = zoom_factor;
|
||||
let mut txn = Transaction::new();
|
||||
txn.set_page_zoom(self.page_zoom_factor);
|
||||
self.api.send_transaction(self.document_id, txn);
|
||||
self.set_title("");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn layout_simple_ascii(
|
||||
|
|
|
@ -221,6 +221,7 @@ XPC_MSG_DEF(NS_ERROR_GFX_PRINTER_DOC_IS_BUSY , "Cannot print this docum
|
|||
|
||||
/* Codes related to content */
|
||||
XPC_MSG_DEF(NS_ERROR_CONTENT_CRASHED , "The process that hosted this content has crashed.")
|
||||
XPC_MSG_DEF(NS_ERROR_FRAME_CRASHED , "The process that hosted this frame has crashed.")
|
||||
XPC_MSG_DEF(NS_ERROR_BUILDID_MISMATCH , "The process that hosted this content did not have the same buildID as the parent.")
|
||||
|
||||
/* Codes for the JS-implemented Push DOM API. These can be removed as part of bug 1252660. */
|
||||
|
|
|
@ -130,7 +130,7 @@ bool RetainedDisplayListBuilder::PreProcessDisplayList(
|
|||
// list build if we hit them.
|
||||
static const uint32_t kMaxEdgeRatio = 5;
|
||||
const bool initializeDAG = !aList->mDAG.Length();
|
||||
if (!initializeDAG && aList->mDAG.mDirectPredecessorList.Length() >
|
||||
if (!aKeepLinked && !initializeDAG && aList->mDAG.mDirectPredecessorList.Length() >
|
||||
(aList->mDAG.mNodesInfo.Length() * kMaxEdgeRatio)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -227,6 +227,7 @@ bool RetainedDisplayListBuilder::PreProcessDisplayList(
|
|||
if (!PreProcessDisplayList(
|
||||
item->GetChildren(), SelectAGRForFrame(f, aAGR), aUpdated,
|
||||
item->GetPerFrameKey(), aNestingDepth + 1, keepLinked)) {
|
||||
MOZ_RELEASE_ASSERT(!aKeepLinked, "Can't early return since we need to move the out list back");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
== mouse-click-open-second-summary.html open-multiple-summary.html
|
||||
== mouse-click-overflow-hidden-details.html overflow-hidden-open-details.html
|
||||
== mouse-click-twice-overflow-hidden-details.html overflow-hidden-details.html
|
||||
fuzzy-if(gtkWidget||OSX,0-1,0-20) == mouse-click-overflow-auto-details.html overflow-auto-open-details.html #Bug 1294278
|
||||
fuzzy-if(gtkWidget||OSX,0-1,0-20) fuzzy-if(webrender,0-1,0-172) == mouse-click-overflow-auto-details.html overflow-auto-open-details.html #Bug 1294278
|
||||
== mouse-click-twice-overflow-auto-details.html overflow-auto-details.html
|
||||
== mouse-click-display-none-details.html open-single-summary.html
|
||||
== mouse-click-change-details-to-display-none.html open-single-summary.html
|
||||
|
|
|
@ -13,6 +13,7 @@ moz_task = { path = "../../../../xpcom/rust/moz_task" }
|
|||
nserror = { path = "../../../../xpcom/rust/nserror" }
|
||||
nsstring = { path = "../../../../xpcom/rust/nsstring" }
|
||||
rkv = "^0.9"
|
||||
rust_cascade = "0.3.4"
|
||||
sha2 = "^0.8"
|
||||
style = { path = "../../../../servo/components/style" }
|
||||
thin-vec = { version = "0.1.0", features = ["gecko-ffi"] }
|
||||
|
|
|
@ -206,10 +206,10 @@ scriptworker:
|
|||
# See additional configuration in taskcluster/taskgraph/util/scriptworker.py
|
||||
scope-prefix: 'project:releng'
|
||||
worker-types:
|
||||
'scriptworker-prov-v1/signing-linux-v1':
|
||||
'linux-signing':
|
||||
- 'project:releng:signing:cert:release-signing'
|
||||
- 'project:releng:signing:cert:nightly-signing'
|
||||
'scriptworker-prov-v1/depsigning':
|
||||
'linux-depsigning':
|
||||
- 'project:releng:signing:cert:dep-signing'
|
||||
'scriptworker-prov-v1/beetmoverworker-v1':
|
||||
- 'project:releng:beetmover:bucket:release'
|
||||
|
@ -288,6 +288,16 @@ workers:
|
|||
implementation: docker-worker
|
||||
os: linux
|
||||
worker-type: 'gecko-{level}-{alias}'
|
||||
linux-depsigning:
|
||||
provisioner: scriptworker-prov-v1
|
||||
implementation: scriptworker-signing
|
||||
os: linux
|
||||
worker-type: depsigning
|
||||
linux-signing:
|
||||
provisioner: scriptworker-prov-v1
|
||||
implementation: scriptworker-signing
|
||||
os: linux
|
||||
worker-type: signing-linux-v1
|
||||
t-ap.*:
|
||||
provisioner: proj-autophone
|
||||
implementation: script-engine-autophone
|
||||
|
|
|
@ -272,3 +272,39 @@ raptor-wasm-godot-chromium:
|
|||
extra-options:
|
||||
- --test=raptor-wasm-godot
|
||||
- --app=chromium
|
||||
|
||||
raptor-tp6-1-chromium-cold:
|
||||
description: "Raptor tp6-1 cold page-load on Chromium"
|
||||
try-name: raptor-tp6-1-chromium-cold
|
||||
treeherder-symbol: Rap-Cr(tp6-c-1)
|
||||
mozharness:
|
||||
extra-options:
|
||||
- --test=raptor-tp6-cold-1
|
||||
- --app=chromium
|
||||
|
||||
raptor-tp6-2-chromium-cold:
|
||||
description: "Raptor tp6-2 cold page-load on Chromium"
|
||||
try-name: raptor-tp6-2-chromium-cold
|
||||
treeherder-symbol: Rap-Cr(tp6-c-2)
|
||||
mozharness:
|
||||
extra-options:
|
||||
- --test=raptor-tp6-cold-2
|
||||
- --app=chromium
|
||||
|
||||
raptor-tp6-3-chromium-cold:
|
||||
description: "Raptor tp6-3 cold page-load on Chromium"
|
||||
try-name: raptor-tp6-3-chromium-cold
|
||||
treeherder-symbol: Rap-Cr(tp6-c-3)
|
||||
mozharness:
|
||||
extra-options:
|
||||
- --test=raptor-tp6-cold-3
|
||||
- --app=chromium
|
||||
|
||||
raptor-tp6-4-chromium-cold:
|
||||
description: "Raptor tp6-4 cold page-load on Chromium"
|
||||
try-name: raptor-tp6-4-chromium-cold
|
||||
treeherder-symbol: Rap-Cr(tp6-c-4)
|
||||
mozharness:
|
||||
extra-options:
|
||||
- --test=raptor-tp6-cold-4
|
||||
- --app=chromium
|
||||
|
|
|
@ -1471,3 +1471,39 @@ raptor-wasm-godot-ion-firefox-profiling:
|
|||
extra-options:
|
||||
- --test=raptor-wasm-godot-ion
|
||||
- --gecko-profile
|
||||
|
||||
raptor-tp6-1-firefox-cold:
|
||||
description: "Raptor tp6-1 cold page-load on Firefox"
|
||||
try-name: raptor-tp6-1-firefox-cold
|
||||
treeherder-symbol: Rap(tp6-c-1)
|
||||
tier: 2
|
||||
mozharness:
|
||||
extra-options:
|
||||
- --test=raptor-tp6-cold-1
|
||||
|
||||
raptor-tp6-2-firefox-cold:
|
||||
description: "Raptor tp6-2 cold page-load on Firefox"
|
||||
try-name: raptor-tp6-2-firefox-cold
|
||||
treeherder-symbol: Rap(tp6-c-2)
|
||||
tier: 2
|
||||
mozharness:
|
||||
extra-options:
|
||||
- --test=raptor-tp6-cold-2
|
||||
|
||||
raptor-tp6-3-firefox-cold:
|
||||
description: "Raptor tp6-3 cold page-load on Firefox"
|
||||
try-name: raptor-tp6-3-firefox-cold
|
||||
treeherder-symbol: Rap(tp6-c-3)
|
||||
tier: 2
|
||||
mozharness:
|
||||
extra-options:
|
||||
- --test=raptor-tp6-cold-3
|
||||
|
||||
raptor-tp6-4-firefox-cold:
|
||||
description: "Raptor tp6-4 cold page-load on Firefox"
|
||||
try-name: raptor-tp6-4-firefox-cold
|
||||
treeherder-symbol: Rap(tp6-c-4)
|
||||
tier: 2
|
||||
mozharness:
|
||||
extra-options:
|
||||
- --test=raptor-tp6-cold-4
|
||||
|
|
|
@ -96,6 +96,10 @@ raptor-firefox:
|
|||
- raptor-webaudio-firefox
|
||||
- raptor-sunspider-firefox
|
||||
- raptor-wasm-godot-firefox
|
||||
- raptor-tp6-1-firefox-cold
|
||||
- raptor-tp6-2-firefox-cold
|
||||
- raptor-tp6-3-firefox-cold
|
||||
- raptor-tp6-4-firefox-cold
|
||||
|
||||
raptor-profiling:
|
||||
- raptor-tp6-1-firefox-profiling
|
||||
|
@ -134,6 +138,10 @@ raptor-chromium:
|
|||
- raptor-webaudio-chromium
|
||||
- raptor-sunspider-chromium
|
||||
- raptor-wasm-godot-chromium
|
||||
- raptor-tp6-1-chromium-cold
|
||||
- raptor-tp6-2-chromium-cold
|
||||
- raptor-tp6-3-chromium-cold
|
||||
- raptor-tp6-4-chromium-cold
|
||||
|
||||
# Fetch tasks are only supported on Linux for now,
|
||||
# so these need to be separate sets.
|
||||
|
|
|
@ -90,6 +90,7 @@ def make_task_description(config, jobs):
|
|||
|
||||
is_nightly = dep_job.attributes.get(
|
||||
'nightly', dep_job.attributes.get('shippable', False))
|
||||
build_platform = dep_job.attributes.get('build_platform')
|
||||
treeherder = None
|
||||
if 'partner' not in config.kind and 'eme-free' not in config.kind:
|
||||
treeherder = job.get('treeherder', {})
|
||||
|
@ -97,7 +98,6 @@ def make_task_description(config, jobs):
|
|||
dep_th_platform = dep_job.task.get('extra', {}).get(
|
||||
'treeherder', {}).get('machine', {}).get('platform', '')
|
||||
build_type = dep_job.attributes.get('build_type')
|
||||
build_platform = dep_job.attributes.get('build_platform')
|
||||
treeherder.setdefault('platform', _generate_treeherder_platform(
|
||||
dep_th_platform, build_platform, build_type
|
||||
))
|
||||
|
@ -118,7 +118,7 @@ def make_task_description(config, jobs):
|
|||
"Initial Signing for locale '{locale}' for build '"
|
||||
"{build_platform}/{build_type}'".format(
|
||||
locale=attributes.get('locale', 'en-US'),
|
||||
build_platform=attributes.get('build_platform'),
|
||||
build_platform=build_platform,
|
||||
build_type=attributes.get('build_type')
|
||||
)
|
||||
)
|
||||
|
@ -131,13 +131,14 @@ def make_task_description(config, jobs):
|
|||
attributes['chunk_locales'] = dep_job.attributes.get('chunk_locales')
|
||||
|
||||
signing_cert_scope = get_signing_cert_scope_per_platform(
|
||||
dep_job.attributes.get('build_platform'), is_nightly, config
|
||||
build_platform, is_nightly, config
|
||||
)
|
||||
worker_type = get_worker_type_for_scope(config, signing_cert_scope)
|
||||
|
||||
task = {
|
||||
'label': label,
|
||||
'description': description,
|
||||
'worker-type': get_worker_type_for_scope(config, signing_cert_scope),
|
||||
'worker-type': worker_type,
|
||||
'worker': {'implementation': 'scriptworker-signing',
|
||||
'upstream-artifacts': job['upstream-artifacts'],
|
||||
'max-run-time': job.get('max-run-time', 3600)},
|
||||
|
|
|
@ -431,7 +431,7 @@ class MitmproxyAndroid(Mitmproxy):
|
|||
|
||||
# the production bitbar container host is always linux
|
||||
self.certutil = glob.glob(
|
||||
os.path.join(self.mozproxy_dir, "host-utils*[!z]")
|
||||
os.path.join(self.mozproxy_dir, "host-utils*[!z|checksum]")
|
||||
)[0]
|
||||
|
||||
# must add hostutils/certutil to the path
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# raptor pageload tests desktop
|
||||
# raptor warm pageload tests desktop
|
||||
[include:tests/raptor-tp6-1.ini]
|
||||
[include:tests/raptor-tp6-2.ini]
|
||||
[include:tests/raptor-tp6-3.ini]
|
||||
|
@ -10,6 +10,12 @@
|
|||
[include:tests/raptor-tp6-9.ini]
|
||||
[include:tests/raptor-tp6-10.ini]
|
||||
|
||||
# raptor cold pageload tests desktop
|
||||
[include:tests/raptor-tp6-cold-1.ini]
|
||||
[include:tests/raptor-tp6-cold-2.ini]
|
||||
[include:tests/raptor-tp6-cold-3.ini]
|
||||
[include:tests/raptor-tp6-cold-4.ini]
|
||||
|
||||
# raptor pageload binast tests desktop
|
||||
[include:tests/raptor-tp6-binast-1.ini]
|
||||
|
||||
|
|
|
@ -436,6 +436,69 @@ class RaptorDesktop(Raptor):
|
|||
self.control_server.browser_proc = proc
|
||||
|
||||
def run_test(self, test, timeout=None):
|
||||
# tests will be run warm (i.e. NO browser restart between page-cycles)
|
||||
# unless otheriwse specified in the test INI by using 'cold = true'
|
||||
if test.get('cold', False) is True:
|
||||
self.run_test_cold(test, timeout)
|
||||
else:
|
||||
self.run_test_warm(test, timeout)
|
||||
|
||||
def run_test_cold(self, test, timeout=None):
|
||||
'''
|
||||
Run the Raptor test but restart the entire browser app between page-cycles.
|
||||
|
||||
Note: For page-load tests, playback will only be started once - at the beginning of all
|
||||
browser cycles, and then stopped after all cycles are finished. That includes the import
|
||||
of the mozproxy ssl cert and turning on the browser proxy.
|
||||
|
||||
Since we're running in cold-mode, before this point (in manifest.py) the
|
||||
'expected-browser-cycles' value was already set to the initial 'page-cycles' value;
|
||||
and the 'page-cycles' value was set to 1 as we want to perform one page-cycle per
|
||||
browser restart.
|
||||
|
||||
The 'browser-cycle' value is the current overall browser start iteration. The control
|
||||
server will receive the current 'browser-cycle' and the 'expected-browser-cycles' in
|
||||
each results set received; and will pass that on as part of the results so that the
|
||||
results processing will know results for multiple browser cycles are being received.
|
||||
|
||||
The default will be to run in warm mode; unless 'cold = true' is set in the test INI.
|
||||
'''
|
||||
self.log.info("test %s is running in cold mode; browser WILL be restarted between "
|
||||
"page cycles" % test['name'])
|
||||
|
||||
for test['browser_cycle'] in range(1, test['expected_browser_cycles'] + 1):
|
||||
|
||||
self.log.info("begin browser cycle %d of %d for test %s"
|
||||
% (test['browser_cycle'], test['expected_browser_cycles'], test['name']))
|
||||
|
||||
self.run_test_setup(test)
|
||||
|
||||
if test['browser_cycle'] == 1:
|
||||
|
||||
if test.get('playback') is not None:
|
||||
self.start_playback(test)
|
||||
|
||||
if self.config['host'] not in ('localhost', '127.0.0.1'):
|
||||
self.delete_proxy_settings_from_profile()
|
||||
|
||||
else:
|
||||
# initial browser profile was already created before run_test was called;
|
||||
# now additional browser cycles we want to create a new one each time
|
||||
self.create_browser_profile()
|
||||
|
||||
self.run_test_setup(test)
|
||||
|
||||
# now start the browser/app under test
|
||||
self.launch_desktop_browser(test)
|
||||
|
||||
# set our control server flag to indicate we are running the browser/app
|
||||
self.control_server._finished = False
|
||||
|
||||
self.wait_for_test_finish(test, timeout)
|
||||
|
||||
self.run_test_teardown()
|
||||
|
||||
def run_test_warm(self, test, timeout=None):
|
||||
self.run_test_setup(test)
|
||||
|
||||
try:
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
# raptor tp6-cold-1
|
||||
|
||||
[DEFAULT]
|
||||
type = pageload
|
||||
playback = mitmproxy
|
||||
playback_version = 4.0.4
|
||||
playback_binary_manifest = mitmproxy-rel-bin-4.0.4-{platform}.manifest
|
||||
playback_pageset_manifest = mitmproxy-recordings-raptor-tp6-1.manifest
|
||||
browser_cycles = 25
|
||||
unit = ms
|
||||
lower_is_better = true
|
||||
alert_threshold = 2.0
|
||||
page_timeout = 60000
|
||||
gecko_profile_interval = 1
|
||||
gecko_profile_entries = 14000000
|
||||
alert_on = fcp, loadtime
|
||||
cold = true
|
||||
|
||||
[raptor-tp6-amazon-firefox-cold]
|
||||
apps = firefox
|
||||
test_url = https://www.amazon.com/s/url=search-alias%3Daps&field-keywords=laptop
|
||||
playback_recordings = amazon.mp
|
||||
measure = fnbpaint, fcp, dcf, loadtime
|
||||
|
||||
[raptor-tp6-amazon-chromium-cold]
|
||||
apps = chromium
|
||||
test_url = https://www.amazon.com/s/url=search-alias%3Daps&field-keywords=laptop
|
||||
playback_recordings = amazon.mp
|
||||
measure = fcp, loadtime
|
||||
|
||||
[raptor-tp6-amazon-chrome-cold]
|
||||
apps = chrome
|
||||
test_url = https://www.amazon.com/s/url=search-alias%3Daps&field-keywords=laptop
|
||||
playback_recordings = amazon.mp
|
||||
measure = fcp, loadtime
|
|
@ -0,0 +1,39 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
# raptor tp6-cold-2
|
||||
|
||||
[DEFAULT]
|
||||
type = pageload
|
||||
playback = mitmproxy
|
||||
playback_version = 4.0.4
|
||||
playback_binary_manifest = mitmproxy-rel-bin-4.0.4-{platform}.manifest
|
||||
playback_pageset_manifest = mitmproxy-recordings-raptor-tp6-1.manifest
|
||||
browser_cycles = 25
|
||||
unit = ms
|
||||
lower_is_better = true
|
||||
alert_threshold = 2.0
|
||||
page_timeout = 60000
|
||||
gecko_profile_interval = 1
|
||||
gecko_profile_entries = 14000000
|
||||
alert_on = fcp, loadtime
|
||||
cold = true
|
||||
|
||||
[raptor-tp6-facebook-firefox-cold]
|
||||
apps = firefox
|
||||
test_url = https://www.facebook.com
|
||||
playback_recordings = facebook.mp
|
||||
measure = fnbpaint, fcp, dcf, loadtime
|
||||
|
||||
[raptor-tp6-facebook-chromium-cold]
|
||||
apps = chromium
|
||||
test_url = https://www.facebook.com
|
||||
playback_recordings = facebook.mp
|
||||
measure = fcp, loadtime
|
||||
|
||||
[raptor-tp6-facebook-chrome-cold]
|
||||
apps = chrome
|
||||
test_url = https://www.facebook.com
|
||||
playback_recordings = facebook.mp
|
||||
measure = fcp, loadtime
|
|
@ -0,0 +1,42 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
# raptor tp6-cold-3
|
||||
|
||||
[DEFAULT]
|
||||
type = pageload
|
||||
playback = mitmproxy
|
||||
playback_version = 4.0.4
|
||||
playback_binary_manifest = mitmproxy-rel-bin-4.0.4-{platform}.manifest
|
||||
playback_pageset_manifest = mitmproxy-recordings-raptor-tp6-1.manifest
|
||||
browser_cycles = 25
|
||||
unit = ms
|
||||
lower_is_better = true
|
||||
alert_threshold = 2.0
|
||||
page_timeout = 60000
|
||||
gecko_profile_interval = 1
|
||||
gecko_profile_entries = 14000000
|
||||
alert_on = fcp, loadtime
|
||||
cold = true
|
||||
|
||||
[raptor-tp6-google-firefox-cold]
|
||||
apps = firefox
|
||||
# note: use the full url as the first part (without '&cad=h') redirects
|
||||
# to the url + '&cad=h'; that redirection causes measure.js content
|
||||
# to be loaded into that page also; resulting in 2 fnbpaint values etc.
|
||||
test_url = https://www.google.com/search?hl=en&q=barack+obama&cad=h
|
||||
playback_recordings = google-search.mp
|
||||
measure = fnbpaint, fcp, dcf, loadtime
|
||||
|
||||
[raptor-tp6-google-chromium-cold]
|
||||
apps = chromium
|
||||
test_url = https://www.google.com/#hl=en&q=barack+obama
|
||||
playback_recordings = google-search.mp
|
||||
measure = fcp, loadtime
|
||||
|
||||
[raptor-tp6-google-chrome-cold]
|
||||
apps = chrome
|
||||
test_url = https://www.google.com/#hl=en&q=barack+obama
|
||||
playback_recordings = google-search.mp
|
||||
measure = fcp, loadtime
|
|
@ -0,0 +1,39 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
# raptor tp6-cold-4
|
||||
|
||||
[DEFAULT]
|
||||
type = pageload
|
||||
playback = mitmproxy
|
||||
playback_version = 4.0.4
|
||||
playback_binary_manifest = mitmproxy-rel-bin-4.0.4-{platform}.manifest
|
||||
playback_pageset_manifest = mitmproxy-recordings-raptor-tp6-1.manifest
|
||||
browser_cycles = 25
|
||||
unit = ms
|
||||
lower_is_better = true
|
||||
alert_threshold = 2.0
|
||||
page_timeout = 60000
|
||||
gecko_profile_interval = 1
|
||||
gecko_profile_entries = 14000000
|
||||
alert_on = fcp, loadtime
|
||||
cold = true
|
||||
|
||||
[raptor-tp6-youtube-firefox-cold]
|
||||
apps = firefox
|
||||
test_url = https://www.youtube.com
|
||||
playback_recordings = youtube.mp
|
||||
measure = fnbpaint, fcp, dcf, loadtime
|
||||
|
||||
[raptor-tp6-youtube-chromium-cold]
|
||||
apps = chromium
|
||||
test_url = https://www.youtube.com
|
||||
playback_recordings = youtube.mp
|
||||
measure = fcp, loadtime
|
||||
|
||||
[raptor-tp6-youtube-chrome-cold]
|
||||
apps = chrome
|
||||
test_url = https://www.youtube.com
|
||||
playback_recordings = youtube.mp
|
||||
measure = fcp, loadtime
|
|
@ -1,4 +1,6 @@
|
|||
[track-cue-rendering-empty-cue.html]
|
||||
disabled:
|
||||
if os == "linux": https://bugzilla.mozilla.org/show_bug.cgi?id=1535847
|
||||
if os == "win": https://bugzilla.mozilla.org/show_bug.cgi?id=1535847
|
||||
if os == "android": https://bugzilla.mozilla.org/show_bug.cgi?id=1535847
|
||||
if (os == "win") and (processor == "aarch64"): https://bugzilla.mozilla.org/show_bug.cgi?id=1548066
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"0c1d447fdcff050a2c1f9e3267bdf5b2d3373e080603a5f9127167f31a169b7d","LICENSE-APACHE":"8173d5c29b4f956d532781d2b86e4e30f83e6b7878dce18c919451d6ba707c90","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"c9d3313c3cc0d55496d8c17bf950b96accd751fc67342e3b3dd3ce7756605092","benches/extern.rs":"30152d15cc55493d06396baf9eebb90c8f32b314f0dc77398ac8a121bd5ff917","crusader.sh":"e656dcb62d5122a64d55f837992e63cfd3beee37cf74c5ab6ff178a3c7ef943e","deploy-docs.sh":"7b66111b124c1c7e59cb84cf110d98b5cb783bd35a676e970d9b3035e55f7dfd","src/bench.rs":"a24345464fdbc70b5b877d13fa1b9da809ba4917e592d5de69f01b8b1340e8bb","src/lib.rs":"5162fc2658cce4d388453e73740eb1d74fbb64b0a5d714c8e7bc9a29671bbfa5"},"package":"4440d5cb623bb7390ae27fec0bb6c61111969860f8e3ae198bfa0663645e67cf"}
|
||||
{"files":{"Cargo.toml":"a5befdf41208ca596759c4a5fa6fc35afdd172fb615c9b7a9e15497f60b2b739","LICENSE-APACHE":"8173d5c29b4f956d532781d2b86e4e30f83e6b7878dce18c919451d6ba707c90","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"c9d3313c3cc0d55496d8c17bf950b96accd751fc67342e3b3dd3ce7756605092","benches/extern.rs":"30152d15cc55493d06396baf9eebb90c8f32b314f0dc77398ac8a121bd5ff917","crusader.sh":"e656dcb62d5122a64d55f837992e63cfd3beee37cf74c5ab6ff178a3c7ef943e","deploy-docs.sh":"7b66111b124c1c7e59cb84cf110d98b5cb783bd35a676e970d9b3035e55f7dfd","src/bench.rs":"a24345464fdbc70b5b877d13fa1b9da809ba4917e592d5de69f01b8b1340e8bb","src/lib.rs":"59489789fb538a592720bb6250a26c18c7624681972295f19a5c9ed866e8e944"},"package":"f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb"}
|
|
@ -3,7 +3,7 @@
|
|||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g. crates.io) dependencies
|
||||
# to registry (e.g., crates.io) dependencies
|
||||
#
|
||||
# If you believe there's an error in this file please file an
|
||||
# issue against the rust-lang/cargo repository. If you're
|
||||
|
@ -12,7 +12,7 @@
|
|||
|
||||
[package]
|
||||
name = "bit-vec"
|
||||
version = "0.5.0"
|
||||
version = "0.5.1"
|
||||
authors = ["Alexis Beingessner <a.beingessner@gmail.com>"]
|
||||
description = "A vector of bits"
|
||||
homepage = "https://github.com/contain-rs/bit-vec"
|
||||
|
|
|
@ -100,19 +100,20 @@ use std::vec::Vec;
|
|||
#[macro_use]
|
||||
extern crate alloc;
|
||||
#[cfg(not(feature="std"))]
|
||||
use alloc::Vec;
|
||||
use alloc::prelude::Vec;
|
||||
|
||||
use core::cmp::Ordering;
|
||||
use core::cmp;
|
||||
#[cfg(feature="std")]
|
||||
use core::fmt;
|
||||
use core::hash;
|
||||
use core::iter::{Chain, Enumerate, Repeat, Skip, Take, repeat};
|
||||
use core::iter::FromIterator;
|
||||
use core::slice;
|
||||
use core::{u8, usize};
|
||||
use core::iter::repeat;
|
||||
|
||||
type MutBlocks<'a, B> = slice::IterMut<'a, B>;
|
||||
type MatchWords<'a, B> = Chain<Enumerate<Blocks<'a, B>>, Skip<Take<Enumerate<Repeat<B>>>>>;
|
||||
//type MatchWords<'a, B> = Chain<Enumerate<Blocks<'a, B>>, Skip<Take<Enumerate<Repeat<B>>>>>;
|
||||
|
||||
use core::ops::*;
|
||||
|
||||
|
@ -148,12 +149,12 @@ pub trait BitBlock:
|
|||
}
|
||||
|
||||
macro_rules! bit_block_impl {
|
||||
($(($t: ty, $size: expr)),*) => ($(
|
||||
($(($t: ident, $size: expr)),*) => ($(
|
||||
impl BitBlock for $t {
|
||||
#[inline]
|
||||
fn bits() -> usize { $size }
|
||||
#[inline]
|
||||
fn from_byte(byte: u8) -> Self { byte as $t }
|
||||
fn from_byte(byte: u8) -> Self { $t::from(byte) }
|
||||
#[inline]
|
||||
fn count_ones(self) -> usize { self.count_ones() as usize }
|
||||
#[inline]
|
||||
|
@ -176,7 +177,7 @@ bit_block_impl!{
|
|||
fn reverse_bits(byte: u8) -> u8 {
|
||||
let mut result = 0;
|
||||
for i in 0..u8::bits() {
|
||||
result = result | ((byte >> i) & 1) << (u8::bits() - 1 - i);
|
||||
result |= ((byte >> i) & 1) << (u8::bits() - 1 - i);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
@ -291,7 +292,7 @@ impl BitVec<u32> {
|
|||
let nblocks = blocks_for_bits::<B>(nbits);
|
||||
let mut bit_vec = BitVec {
|
||||
storage: vec![if bit { !B::zero() } else { B::zero() }; nblocks],
|
||||
nbits: nbits
|
||||
nbits,
|
||||
};
|
||||
bit_vec.fix_last_block();
|
||||
bit_vec
|
||||
|
@ -338,8 +339,8 @@ impl BitVec<u32> {
|
|||
for i in 0..complete_words {
|
||||
let mut accumulator = B::zero();
|
||||
for idx in 0..B::bytes() {
|
||||
accumulator = accumulator |
|
||||
(B::from_byte(reverse_bits(bytes[i * B::bytes() + idx])) << (idx * 8))
|
||||
accumulator |=
|
||||
B::from_byte(reverse_bits(bytes[i * B::bytes() + idx])) << (idx * 8)
|
||||
}
|
||||
bit_vec.storage.push(accumulator);
|
||||
}
|
||||
|
@ -347,8 +348,8 @@ impl BitVec<u32> {
|
|||
if extra_bytes > 0 {
|
||||
let mut last_word = B::zero();
|
||||
for (i, &byte) in bytes[complete_words * B::bytes()..].iter().enumerate() {
|
||||
last_word = last_word |
|
||||
(B::from_byte(reverse_bits(byte)) << (i * 8));
|
||||
last_word |=
|
||||
B::from_byte(reverse_bits(byte)) << (i * 8);
|
||||
}
|
||||
bit_vec.storage.push(last_word);
|
||||
}
|
||||
|
@ -1183,6 +1184,7 @@ impl<B: BitBlock> Ord for BitVec<B> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="std")]
|
||||
impl<B: BitBlock> fmt::Debug for BitVec<B> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
for bit in self {
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
{"files":{"Cargo.toml":"c582a8c45f7e3ba8d3407a8856282109e45e1f6f78ecd1bc975ff07002e67bdf","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6a5dfb0adf37850239f4b2388a79355c77b625d6c5542dea7743ac5033efaba2","README.md":"a17879576762e075a1c7f93988b1280cbfc5cfdff50b5b01081c19dfca678c71","appveyor.yml":"e8faff584d19fb4410f35a4c1ae8718dddf4c8f2754171d5a0b109d9967affe2","benches/primitives.rs":"7eb2f1e2d3fa2c980604995e753a8da9297039eee033c0e5ce5ae2d755828589","examples/u8_reverse.rs":"081c633632762077a07cbe1ea3ddf580ba79d28816ab86aec6ccdf26ee9c5add","src/bitwise.rs":"2930b5bb24c18c6d18922def97498fad3e01a88be6487ee234a030c81e31e4eb","src/lib.rs":"57f60bcead2f2a13df19c4799eed484754e879588e25a87202354648426932ac","src/lookup.rs":"a392cecececde1a0c5d3cd2a7e73b3f53e8cad094c0023ce33761c66f949dd6a","src/macros.rs":"9a1e106bdacf520dc8586090d90570176d50e237628cc1eb70f979830f7e6eac","src/parallel.rs":"fda4a8f7719097f46c8dea6cc408a59ff0488fdc733b0d763aa074794b76befc"},"package":"5e97e02db5a2899c0377f3d6031d5da8296ca2b47abef6ed699de51b9e40a28c"}
|
|
@ -0,0 +1,32 @@
|
|||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g. crates.io) dependencies
|
||||
#
|
||||
# If you believe there's an error in this file please file an
|
||||
# issue against the rust-lang/cargo repository. If you're
|
||||
# editing this file be aware that the upstream Cargo.toml
|
||||
# will likely look very different (and much more reasonable)
|
||||
|
||||
[package]
|
||||
name = "bit_reverse"
|
||||
version = "0.1.7"
|
||||
authors = ["Eugene Gonzalez <eugene.gonzalez44@gmail.com>"]
|
||||
description = "Computes the bit reversal of primitive integers."
|
||||
documentation = "https://docs.rs/bit_reverse"
|
||||
readme = "README.md"
|
||||
keywords = ["bit", "swap", "reverse"]
|
||||
categories = ["no-std"]
|
||||
license = "MIT/Apache-2.0"
|
||||
repository = "https://github.com/EugeneGonzalez/bit_reverse"
|
||||
|
||||
[features]
|
||||
default = ["use_std"]
|
||||
use_std = []
|
||||
[badges.travis-ci]
|
||||
repository = "EugeneGonzalez/bit_reverse"
|
||||
|
||||
[badges.appveyor]
|
||||
repository = "EugeneGonzalez/bit_reverse"
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014-2016 Ning Sun and tojson_macros contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,37 @@
|
|||
# bit_reverse
|
||||
[![Crates Shield](https://img.shields.io/crates/v/bit_reverse.svg "Crates.io")](https://crates.io/crates/bit_reverse) [![Build Shield](https://travis-ci.org/EugeneGonzalez/bit_reverse.svg?branch=master "TravisCI")](https://travis-ci.org/EugeneGonzalez/bit_reverse) [![Build status](https://ci.appveyor.com/api/projects/status/hkj3312s9v7rhw3p/branch/master?svg=true)](https://ci.appveyor.com/project/EugeneGonzalez/bit-reverse/branch/master)
|
||||
|
||||
|
||||
### Library Objective
|
||||
This library provides a number of ways to compute the bit reversal of all primitive integers.
|
||||
There are currently 3 different algorithms implemented: Bitwise, Parallel, and Lookup reversal.
|
||||
|
||||
### Example
|
||||
```rust
|
||||
use bit_reverse::ParallelReverse;
|
||||
|
||||
assert_eq!(0xA0u8.swap_bits(), 0x05u8);
|
||||
```
|
||||
This library is very simple to uses just import the crate and the algorithm you want to use.
|
||||
Then you can call `swap_bits`() on any primitive integer. If you want to try a different
|
||||
algorithm just change the use statement and now your program will use the algorithm instead.
|
||||
|
||||
### YMMV Performance Comparison
|
||||
I wouldn't use `BitwiseReverse` as it is mainly there for completeness and is strictly inferior
|
||||
to `ParallelReverse`, which is a Bitwise Parallel Reverse and thus an order of magnitude faster.
|
||||
For small sizes, <= 16 bits, `LookupReverse` is the fastest but it doesn't scale as well as
|
||||
`ParallelReverse` this is because `ParallelReverse` does a constant number of operations for
|
||||
every size (assuming your cpu has a hardware byte swap instruction). `LookupReverse` needs more
|
||||
lookups, ANDs, and ORs for each size increase. Thus `ParallelReverse` performs a little better
|
||||
at 32 bits and much better at 64 bits. These runtime characteristics are based on a Intel(R)
|
||||
Core(TM) i7-4770K CPU @ 3.50GHz.
|
||||
|
||||
### Memory Consumption
|
||||
`BitwiseReverse` and `ParallelReverse` both only use a couple of stack variables for their
|
||||
computations. `LookupReverse` on the other hand statically allocates 256 u8s or 256 bytes to
|
||||
do its computations. `LookupReverse`'s memory cost is shared by all of the types
|
||||
'LookupReverse` supports.
|
||||
|
||||
### no_std Compatible
|
||||
To link to core instead of STD, disable default features for this library in your Cargo.toml.
|
||||
[Cargo choosing features](http://doc.crates.io/specifying-dependencies.html#choosing-features)
|
|
@ -0,0 +1,121 @@
|
|||
# Appveyor configuration template for Rust using rustup for Rust installation
|
||||
# https://github.com/starkat99/appveyor-rust
|
||||
|
||||
## Operating System (VM environment) ##
|
||||
|
||||
# Rust needs at least Visual Studio 2013 Appveyor OS for MSVC targets.
|
||||
os: Visual Studio 2015
|
||||
|
||||
## Build Matrix ##
|
||||
|
||||
# This configuration will setup a build for each channel & target combination (12 windows
|
||||
# combinations in all).
|
||||
#
|
||||
# There are 3 channels: stable, beta, and nightly.
|
||||
#
|
||||
# Alternatively, the full version may be specified for the channel to build using that specific
|
||||
# version (e.g. channel: 1.5.0)
|
||||
#
|
||||
# The values for target are the set of windows Rust build targets. Each value is of the form
|
||||
#
|
||||
# ARCH-pc-windows-TOOLCHAIN
|
||||
#
|
||||
# Where ARCH is the target architecture, either x86_64 or i686, and TOOLCHAIN is the linker
|
||||
# toolchain to use, either msvc or gnu. See https://www.rust-lang.org/downloads.html#win-foot for
|
||||
# a description of the toolchain differences.
|
||||
# See https://github.com/rust-lang-nursery/rustup.rs/#toolchain-specification for description of
|
||||
# toolchains and host triples.
|
||||
#
|
||||
# Comment out channel/target combos you do not wish to build in CI.
|
||||
#
|
||||
# You may use the `cargoflags` and `RUSTFLAGS` variables to set additional flags for cargo commands
|
||||
# and rustc, respectively. For instance, you can uncomment the cargoflags lines in the nightly
|
||||
# channels to enable unstable features when building for nightly. Or you could add additional
|
||||
# matrix entries to test different combinations of features.
|
||||
environment:
|
||||
matrix:
|
||||
|
||||
### MSVC Toolchains ###
|
||||
|
||||
# Stable 64-bit MSVC
|
||||
- channel: stable
|
||||
target: x86_64-pc-windows-msvc
|
||||
# Stable 32-bit MSVC
|
||||
- channel: stable
|
||||
target: i686-pc-windows-msvc
|
||||
# Beta 64-bit MSVC
|
||||
- channel: beta
|
||||
target: x86_64-pc-windows-msvc
|
||||
# Beta 32-bit MSVC
|
||||
- channel: beta
|
||||
target: i686-pc-windows-msvc
|
||||
# Nightly 64-bit MSVC
|
||||
- channel: nightly
|
||||
target: x86_64-pc-windows-msvc
|
||||
#cargoflags: --features "unstable"
|
||||
# Nightly 32-bit MSVC
|
||||
- channel: nightly
|
||||
target: i686-pc-windows-msvc
|
||||
#cargoflags: --features "unstable"
|
||||
|
||||
### GNU Toolchains ###
|
||||
|
||||
# Stable 64-bit GNU
|
||||
- channel: stable
|
||||
target: x86_64-pc-windows-gnu
|
||||
# Stable 32-bit GNU
|
||||
- channel: stable
|
||||
target: i686-pc-windows-gnu
|
||||
# Beta 64-bit GNU
|
||||
- channel: beta
|
||||
target: x86_64-pc-windows-gnu
|
||||
# Beta 32-bit GNU
|
||||
- channel: beta
|
||||
target: i686-pc-windows-gnu
|
||||
# Nightly 64-bit GNU
|
||||
- channel: nightly
|
||||
target: x86_64-pc-windows-gnu
|
||||
#cargoflags: --features "unstable"
|
||||
# Nightly 32-bit GNU
|
||||
- channel: nightly
|
||||
target: i686-pc-windows-gnu
|
||||
#cargoflags: --features "unstable"
|
||||
|
||||
### Allowed failures ###
|
||||
|
||||
# See Appveyor documentation for specific details. In short, place any channel or targets you wish
|
||||
# to allow build failures on (usually nightly at least is a wise choice). This will prevent a build
|
||||
# or test failure in the matching channels/targets from failing the entire build.
|
||||
matrix:
|
||||
allow_failures:
|
||||
- channel: nightly
|
||||
|
||||
# If you only care about stable channel build failures, uncomment the following line:
|
||||
#- channel: beta
|
||||
|
||||
## Install Script ##
|
||||
|
||||
# This is the most important part of the Appveyor configuration. This installs the version of Rust
|
||||
# specified by the 'channel' and 'target' environment variables from the build matrix. This uses
|
||||
# rustup to install Rust.
|
||||
#
|
||||
# For simple configurations, instead of using the build matrix, you can simply set the
|
||||
# default-toolchain and default-host manually here.
|
||||
install:
|
||||
- appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe
|
||||
- rustup-init -yv --default-toolchain %channel% --default-host %target%
|
||||
- set PATH=%PATH%;%USERPROFILE%\.cargo\bin
|
||||
- rustc -vV
|
||||
- cargo -vV
|
||||
|
||||
## Build Script ##
|
||||
|
||||
# 'cargo test' takes care of building for us, so disable Appveyor's build stage. This prevents
|
||||
# the "directory does not contain a project or solution file" error.
|
||||
build: false
|
||||
|
||||
# Uses 'cargo test' to run tests and build. Alternatively, the project may call compiled programs
|
||||
#directly or perform other testing commands. Rust will automatically be placed in the PATH
|
||||
# environment variable.
|
||||
test_script:
|
||||
- cargo test --verbose %cargoflags%
|
|
@ -0,0 +1,167 @@
|
|||
#![allow(overflowing_literals)]
|
||||
#![feature(test)]
|
||||
|
||||
extern crate bit_reverse;
|
||||
extern crate test;
|
||||
|
||||
|
||||
static SEED: u64 = 0x0123456789ABCDEF;
|
||||
static NUM_ITERS: usize = 1024;
|
||||
|
||||
macro_rules! benchmark_suite {
|
||||
($name:ident, $algo:ident) => (
|
||||
#[cfg(test)]
|
||||
mod $name {
|
||||
use bit_reverse::$algo;
|
||||
use super::test::Bencher;
|
||||
use std::mem::size_of;
|
||||
|
||||
use SEED;
|
||||
use NUM_ITERS;
|
||||
|
||||
#[bench]
|
||||
fn reverse_u8(b: &mut Bencher) {
|
||||
let mut num = SEED as u8;
|
||||
|
||||
b.bytes = (NUM_ITERS * size_of::<u8>()) as u64;
|
||||
b.iter(|| {
|
||||
for _ in 0..NUM_ITERS {
|
||||
num = num.swap_bits();
|
||||
}
|
||||
|
||||
num
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn reverse_u16(b: &mut Bencher) {
|
||||
let mut num = SEED as u16;
|
||||
|
||||
b.bytes = (NUM_ITERS * size_of::<u16>()) as u64;
|
||||
b.iter(|| {
|
||||
for _ in 0..NUM_ITERS {
|
||||
num = num.swap_bits();
|
||||
}
|
||||
|
||||
num
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn reverse_u32(b: &mut Bencher) {
|
||||
let mut num = SEED as u32;
|
||||
|
||||
b.bytes = (NUM_ITERS * size_of::<u32>()) as u64;
|
||||
b.iter(|| {
|
||||
for _ in 0..NUM_ITERS {
|
||||
num = num.swap_bits();
|
||||
}
|
||||
|
||||
num
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn reverse_u64(b: &mut Bencher) {
|
||||
let mut num = SEED as u64;
|
||||
|
||||
b.bytes = (NUM_ITERS * size_of::<u64>()) as u64;
|
||||
b.iter(|| {
|
||||
for _ in 0..NUM_ITERS {
|
||||
num = num.swap_bits();
|
||||
}
|
||||
|
||||
num
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn reverse_usize(b: &mut Bencher) {
|
||||
let mut num = SEED as usize;
|
||||
|
||||
b.bytes = (NUM_ITERS * size_of::<usize>()) as u64;
|
||||
b.iter(|| {
|
||||
for _ in 0..NUM_ITERS {
|
||||
num = num.swap_bits();
|
||||
}
|
||||
|
||||
num
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn reverse_i8(b: &mut Bencher) {
|
||||
let mut num = SEED as i8;
|
||||
|
||||
b.bytes = (NUM_ITERS * size_of::<i8>()) as u64;
|
||||
b.iter(|| {
|
||||
for _ in 0..NUM_ITERS {
|
||||
num = num.swap_bits();
|
||||
}
|
||||
|
||||
num
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn reverse_i16(b: &mut Bencher) {
|
||||
let mut num = SEED as i16;
|
||||
|
||||
b.bytes = (NUM_ITERS * size_of::<i16>()) as u64;
|
||||
b.iter(|| {
|
||||
for _ in 0..NUM_ITERS {
|
||||
num = num.swap_bits();
|
||||
}
|
||||
|
||||
num
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn reverse_i32(b: &mut Bencher) {
|
||||
let mut num = SEED as i32;
|
||||
|
||||
b.bytes = (NUM_ITERS * size_of::<i32>()) as u64;
|
||||
b.iter(|| {
|
||||
for _ in 0..NUM_ITERS {
|
||||
num = num.swap_bits();
|
||||
}
|
||||
|
||||
num
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn reverse_i64(b: &mut Bencher) {
|
||||
let mut num = SEED as i64;
|
||||
|
||||
b.bytes = (NUM_ITERS * size_of::<i64>()) as u64;
|
||||
b.iter(|| {
|
||||
for _ in 0..NUM_ITERS {
|
||||
num = num.swap_bits();
|
||||
}
|
||||
|
||||
num
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn reverse_isize(b: &mut Bencher) {
|
||||
let mut num = SEED as isize;
|
||||
|
||||
b.bytes = (NUM_ITERS * size_of::<isize>()) as u64;
|
||||
b.iter(|| {
|
||||
for _ in 0..NUM_ITERS {
|
||||
num = num.swap_bits();
|
||||
}
|
||||
|
||||
num
|
||||
});
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
benchmark_suite!(parallel, ParallelReverse);
|
||||
benchmark_suite!(lookup, LookupReverse);
|
||||
benchmark_suite!(bitwise, BitwiseReverse);
|
|
@ -0,0 +1,15 @@
|
|||
// Load the bit_reverse external crate
|
||||
extern crate bit_reverse;
|
||||
|
||||
// Imports the Parallel Bit reversal algorithm to bit reverse numbers.
|
||||
use bit_reverse::ParallelReverse;
|
||||
|
||||
// Uncomment one of these if you want to use a different algorithm.
|
||||
// use bit_reverse::BitwiseReverse;
|
||||
// use bit_reverse::LookupReverse;
|
||||
|
||||
fn main() {
|
||||
// Calculate the bit reversal of all u8 numbers and print them out.
|
||||
let reverse: Vec<u8> = (0..).take(256).map(|x| (x as u8).swap_bits()).collect();
|
||||
println!("{:?}", reverse);
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
use super::core;
|
||||
|
||||
/// Computes bit reversal by going bit by bit and setting the reverse position bit for the output.
|
||||
pub trait BitwiseReverse<T> {
|
||||
/// Swaps the bits such that bit i is now bit N-i, where N is the length of the T in bits.
|
||||
fn swap_bits(self) -> T;
|
||||
}
|
||||
|
||||
macro_rules! doit_bitwise { ($($ty:ty),*) => ($(
|
||||
impl BitwiseReverse<$ty> for $ty {
|
||||
// This algorithm uses the reverse variable as a like a stack to reverse the value.
|
||||
// The lesser significant bits are pushed onto the reverse variable and then the variable
|
||||
// is shifted down to make room for more significant bits. This algorithm has a shortcut,
|
||||
// that if there aren't anymore 1s to push onto the reverse variable the algorithm ends
|
||||
// early and shift the reverse to the correct position.
|
||||
#[inline]
|
||||
fn swap_bits(self) -> $ty {
|
||||
let mut v = self;
|
||||
|
||||
// By initializing the reversal to value, we have already loaded the largest
|
||||
// significant bit into the correct location.
|
||||
let mut r = self;
|
||||
|
||||
// Compute how many bits are left to shift at the end of the algorithm.
|
||||
let mut s = 8 * core::mem::size_of::<$ty>() - 1;
|
||||
|
||||
v >>= 1;
|
||||
while v != 0 { // Quit early if there are no more 1s to shift in
|
||||
r <<= 1; // Make room for the next significant bit
|
||||
r |= v & 1; // Add the bit to the reverse variable
|
||||
v >>= 1; // Go to the next significant bit
|
||||
s -= 1; // Decrement the leftover bit count
|
||||
}
|
||||
|
||||
// Shift the reversal to the correct position and return the reversal
|
||||
return r << s;
|
||||
}
|
||||
})*)
|
||||
}
|
||||
|
||||
doit_bitwise!(u8, u16, u32, u64, usize);
|
||||
doit_signed!(BitwiseReverse);
|
||||
test_suite!();
|
|
@ -0,0 +1,52 @@
|
|||
//! ## Library Objective
|
||||
//! This library provides a number of ways to compute the bit reversal of all primitive integers.
|
||||
//! There are currently 3 different algorithms implemented: Bitwise, Parallel, and Lookup reversal.
|
||||
//!
|
||||
//! ## Example
|
||||
//! ```
|
||||
//! use bit_reverse::ParallelReverse;
|
||||
//!
|
||||
//! assert_eq!(0xA0u8.swap_bits(), 0x05u8);
|
||||
//! ```
|
||||
//! This library is very simple to uses just import the crate and the algorithm you want to use.
|
||||
//! Then you can call `swap_bits`() on any primitive integer. If you want to try a different
|
||||
//! algorithm just change the use statement and now your program will use the algorithm instead.
|
||||
//!
|
||||
//! ## YMMV Performance Comparison
|
||||
//! I wouldn't use `BitwiseReverse` as it is mainly there for completeness and is strictly inferior
|
||||
//! to `ParallelReverse`, which is a Bitwise Parallel Reverse and thus an order of magnitude faster.
|
||||
//! For small sizes, <= 16 bits, `LookupReverse` is the fastest but it doesn't scale as well as
|
||||
//! `ParallelReverse` this is because `ParallelReverse` does a constant number of operations for
|
||||
//! every size (assuming your cpu has a hardware byte swap instruction). `LookupReverse` needs more
|
||||
//! lookups, ANDs, and ORs for each size increase. Thus `ParallelReverse` performs a little better
|
||||
//! at 32 bits and much better at 64 bits. These runtime characteristics are based on a Intel(R)
|
||||
//! Core(TM) i7-4770K CPU @ 3.50GHz.
|
||||
//!
|
||||
//! ## Memory Consumption
|
||||
//! `BitwiseReverse` and `ParallelReverse` both only use a couple of stack variables for their
|
||||
//! computations. `LookupReverse` on the other hand statically allocates 256 u8s or 256 bytes to
|
||||
//! do its computations. `LookupReverse`'s memory cost is shared by all of the types
|
||||
//! 'LookupReverse` supports.
|
||||
//!
|
||||
//! ## no_std Compatible
|
||||
//! To link to core instead of STD, disable default features for this library in your Cargo.toml.
|
||||
//! [Cargo choosing features](http://doc.crates.io/specifying-dependencies.html#choosing-features)
|
||||
|
||||
// This library abuse overflowing literals to be able to use macros to reduce duplicate code.
|
||||
#![allow(overflowing_literals)]
|
||||
|
||||
#![cfg_attr(not(feature = "use_std"), no_std)]
|
||||
|
||||
#[cfg(feature = "use_std")]
|
||||
extern crate std as core;
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
mod bitwise;
|
||||
mod parallel;
|
||||
mod lookup;
|
||||
|
||||
pub use bitwise::BitwiseReverse;
|
||||
pub use parallel::ParallelReverse;
|
||||
pub use lookup::LookupReverse;
|
|
@ -0,0 +1,103 @@
|
|||
|
||||
/// Computes bit reversal by using lookup table to translate a single byte into its reverse.
|
||||
/// For multi-byte types, the byte order is swapped to complete the reversal.
|
||||
pub trait LookupReverse<T> {
|
||||
/// Swaps the bits such that bit i is now bit N-i, where N is the length of the T in bits.
|
||||
fn swap_bits(self) -> T;
|
||||
}
|
||||
|
||||
const REVERSE_LOOKUP: [u8; 256] = [
|
||||
0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
|
||||
8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
|
||||
4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
|
||||
12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
|
||||
2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
|
||||
10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
|
||||
6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
|
||||
14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
|
||||
1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
|
||||
9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
|
||||
5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
|
||||
13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
|
||||
3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
|
||||
11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
|
||||
7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
|
||||
15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255
|
||||
];
|
||||
|
||||
impl LookupReverse<u8> for u8 {
|
||||
#[inline]
|
||||
fn swap_bits(self) -> u8 {
|
||||
unsafe { *REVERSE_LOOKUP.get_unchecked(self as usize) }
|
||||
}
|
||||
}
|
||||
|
||||
impl LookupReverse<u16> for u16 {
|
||||
#[inline]
|
||||
fn swap_bits(self) -> u16 {
|
||||
unsafe {
|
||||
(*REVERSE_LOOKUP.get_unchecked((self & 0xFF) as usize) as u16) << 8 |
|
||||
(*REVERSE_LOOKUP.get_unchecked(((self >> 8) & 0xFF) as usize) as u16)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LookupReverse<u32> for u32 {
|
||||
#[inline]
|
||||
fn swap_bits(self) -> u32 {
|
||||
unsafe {
|
||||
(*REVERSE_LOOKUP.get_unchecked((self & 0xFF) as usize) as u32) << 24 |
|
||||
(*REVERSE_LOOKUP.get_unchecked(((self >> 8) & 0xFF) as usize) as u32) << 16 |
|
||||
(*REVERSE_LOOKUP.get_unchecked(((self >> 16) & 0xFF) as usize) as u32) << 8 |
|
||||
(*REVERSE_LOOKUP.get_unchecked(((self >> 24) & 0xFF) as usize) as u32)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LookupReverse<u64> for u64 {
|
||||
#[inline]
|
||||
fn swap_bits(self) -> u64 {
|
||||
unsafe {
|
||||
(*REVERSE_LOOKUP.get_unchecked((self & 0xFF) as usize) as u64) << 56 |
|
||||
(*REVERSE_LOOKUP.get_unchecked(((self >> 8) & 0xFF) as usize) as u64) << 48 |
|
||||
(*REVERSE_LOOKUP.get_unchecked(((self >> 16) & 0xFF) as usize) as u64) << 40 |
|
||||
(*REVERSE_LOOKUP.get_unchecked(((self >> 24) & 0xFF) as usize) as u64) << 32 |
|
||||
(*REVERSE_LOOKUP.get_unchecked(((self >> 32) & 0xFF) as usize) as u64) << 24 |
|
||||
(*REVERSE_LOOKUP.get_unchecked(((self >> 40) & 0xFF) as usize) as u64) << 16 |
|
||||
(*REVERSE_LOOKUP.get_unchecked(((self >> 48) & 0xFF) as usize) as u64) << 8 |
|
||||
(*REVERSE_LOOKUP.get_unchecked(((self >> 56) & 0xFF) as usize) as u64)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LookupReverse<usize> for usize {
|
||||
#[inline]
|
||||
#[cfg(target_pointer_width = "8")]
|
||||
fn swap_bits(self) -> usize {
|
||||
use LookupReverse;
|
||||
LookupReverse::swap_bits(self as u8) as usize
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(target_pointer_width = "16")]
|
||||
fn swap_bits(self) -> usize {
|
||||
use LookupReverse;
|
||||
LookupReverse::swap_bits(self as u16) as usize
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
fn swap_bits(self) -> usize {
|
||||
use LookupReverse;
|
||||
LookupReverse::swap_bits(self as u32) as usize
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
fn swap_bits(self) -> usize {
|
||||
LookupReverse::swap_bits(self as u64) as usize
|
||||
}
|
||||
}
|
||||
|
||||
doit_signed!(LookupReverse);
|
||||
test_suite!();
|
|
@ -0,0 +1,92 @@
|
|||
macro_rules! doit_signed {
|
||||
($($Algo:ident),*) => ($(
|
||||
impl $Algo<i8> for i8 {
|
||||
#[inline]
|
||||
fn swap_bits(self) -> i8 {
|
||||
$Algo::swap_bits(self as u8) as i8
|
||||
}
|
||||
}
|
||||
|
||||
impl $Algo<i16> for i16 {
|
||||
#[inline]
|
||||
fn swap_bits(self) -> i16 {
|
||||
$Algo::swap_bits(self as u16) as i16
|
||||
}
|
||||
}
|
||||
|
||||
impl $Algo<i32> for i32 {
|
||||
#[inline]
|
||||
fn swap_bits(self) -> i32 {
|
||||
$Algo::swap_bits(self as u32) as i32
|
||||
}
|
||||
}
|
||||
|
||||
impl $Algo<i64> for i64 {
|
||||
#[inline]
|
||||
fn swap_bits(self) -> i64 {
|
||||
$Algo::swap_bits(self as u64) as i64
|
||||
}
|
||||
}
|
||||
|
||||
impl $Algo<isize> for isize {
|
||||
#[inline]
|
||||
fn swap_bits(self) -> isize {
|
||||
$Algo::swap_bits(self as usize) as isize
|
||||
}
|
||||
}
|
||||
)*)
|
||||
}
|
||||
|
||||
macro_rules! test_suite {
|
||||
() => (
|
||||
#[test]
|
||||
fn reverse_u8() {
|
||||
assert_eq!(0xABu8.swap_bits(), 0xD5u8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reverse_u16() {
|
||||
assert_eq!(0xABCDu16.swap_bits(), 0xB3D5u16);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reverse_u32() {
|
||||
assert_eq!(0xABCD2345u32.swap_bits(), 0xA2C4B3D5u32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reverse_u64() {
|
||||
assert_eq!(0x0123456789ABCDEFu64.swap_bits(), 0xF7B3D591E6A2C480u64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reverse_usize() {
|
||||
assert_eq!(0xFFusize.swap_bits(), 0xFFusize.swap_bytes());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reverse_i8() {
|
||||
assert_eq!(0xABi8.swap_bits(), 0xD5i8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reverse_i16() {
|
||||
assert_eq!(0xABCDi16.swap_bits(), 0xB3D5i16);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reverse_i32() {
|
||||
assert_eq!(0xABCD2345i32.swap_bits(), 0xA2C4B3D5i32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reverse_i64() {
|
||||
assert_eq!(0x0123456789ABCDEFi64.swap_bits(), 0xF7B3D591E6A2C480i64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reverse_isize() {
|
||||
assert_eq!(0xFFisize.swap_bits(), 0xFFisize.swap_bytes());
|
||||
}
|
||||
)
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/// Computes bit reversal by using a divide and conquer approach. Pairs of bits are swapped.
|
||||
/// Then neighboring bit pairs are swapped. Each time swapping the next largest group of bits.
|
||||
/// This is done until the entire data has been bit reversed.
|
||||
pub trait ParallelReverse<T> {
|
||||
/// Swaps the bits such that bit i is now bit N-i, where N is the length of the T in bits.
|
||||
fn swap_bits(self) -> T;
|
||||
}
|
||||
|
||||
macro_rules! doit_parallel { ($($ty:ty),*) => ($(
|
||||
impl ParallelReverse<$ty> for $ty {
|
||||
#[inline]
|
||||
fn swap_bits(self) -> $ty {
|
||||
let mut v = self;
|
||||
// Swap odd and even bits
|
||||
v = ((v >> 1) & (0x5555555555555555 as $ty)) | ((v & (0x5555555555555555 as $ty)) << 1);
|
||||
// Swap consecutive pairs
|
||||
v = ((v >> 2) & (0x3333333333333333 as $ty)) | ((v & (0x3333333333333333 as $ty)) << 2);
|
||||
// Swap nibbles
|
||||
v = ((v >> 4) & (0x0F0F0F0F0F0F0F0F as $ty)) | ((v & (0x0F0F0F0F0F0F0F0F as $ty)) << 4);
|
||||
|
||||
return v.swap_bytes();
|
||||
}
|
||||
})*)
|
||||
}
|
||||
|
||||
doit_parallel!(u8, u16, u32, u64, usize);
|
||||
doit_signed!(ParallelReverse);
|
||||
test_suite!();
|
|
@ -1 +1 @@
|
|||
{"files":{"CHANGELOG.md":"dc0a497d6932b874a32c1a457e344bdcd27a1767a174d163f19d66b837477a08","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"9f119d940ff1131bb71fb7c2b10c36ae91b45dbcf010975ccc555268a5b79165","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"97c01a66dbff4615acd49a8c3a85d137bf29cc113fa514910195bb11aef445bc","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","benches/bench.rs":"5dbfb724aa137efdff2cf0faeb728a3d302eda097ba5189de2d82314ce500654","src/io.rs":"d9759a25c625aa341b23bdb489144b1e9554db11bc2fa799a2a6ecfbc442ea5e","src/lib.rs":"fd18e7969a80314537ba41b3c460284975c0d4df4b72f27527506cb5bd889ae8"},"package":"94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d"}
|
||||
{"files":{"CHANGELOG.md":"51f0eb3b6139fc1a908d41a7b3cba7d58d684700986b3518f82e5af254c39e8e","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"362a05ecca14c0934f211fba28eeeca2a72e4665e4c8303bc44321aedfa1ab1c","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"97c01a66dbff4615acd49a8c3a85d137bf29cc113fa514910195bb11aef445bc","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","benches/bench.rs":"80e43e07f34bc6d3ebe4f37cea79ba02cafce6cf30b737a1db65de55f2c38ca5","build.rs":"088c35c11be1e443c4462c7fe2863bcf885805e7b0f3dc7d83e6091ff197e779","src/io.rs":"dce98946ebc14cc37e8f5632a26979494cdd995adceeb9c22c591aef9010c7ad","src/lib.rs":"23fd0baba674e534dee99f9f082db2f7a51b075b1ed7c3510bc49ebd011033bc"},"package":"a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb"}
|
|
@ -1,3 +1,46 @@
|
|||
1.3.0
|
||||
=====
|
||||
This new minor release now enables `i128` support automatically on Rust
|
||||
compilers that support 128-bit integers. The `i128` feature is now a no-op, but
|
||||
continues to exist for backward compatibility purposes. The crate continues to
|
||||
maintain compatibility with Rust 1.12.0.
|
||||
|
||||
This release also deprecates the `ByteOrder` trait methods
|
||||
`read_f32_into_unchecked` and `read_f64_into_unchecked` in favor of
|
||||
`read_f32_into` and `read_f64_into`. This was an oversight from the 1.2 release
|
||||
where the corresponding methods on `ReadBytesExt` were deprecated.
|
||||
|
||||
`quickcheck` and `rand` were bumped to `0.8` and `0.6`, respectively.
|
||||
|
||||
A few small documentation related bugs have been fixed.
|
||||
|
||||
|
||||
1.2.7
|
||||
=====
|
||||
This patch release excludes some CI files from the crate release and updates
|
||||
the license field to use `OR` instead of `/`.
|
||||
|
||||
|
||||
1.2.6
|
||||
=====
|
||||
This patch release fixes some test compilation errors introduced by an
|
||||
over-eager release of 1.2.5.
|
||||
|
||||
|
||||
1.2.5
|
||||
=====
|
||||
This patch release fixes some typos in the docs, adds doc tests to methods on
|
||||
`WriteByteExt` and bumps the quickcheck dependency to `0.7`.
|
||||
|
||||
|
||||
1.2.4
|
||||
=====
|
||||
This patch release adds support for 48-bit integers by adding the following
|
||||
methods to the `ByteOrder` trait: `read_u48`, `read_i48`, `write_u48` and
|
||||
`write_i48`. Corresponding methods have been added to the `ReadBytesExt` and
|
||||
`WriteBytesExt` traits as well.
|
||||
|
||||
|
||||
1.2.3
|
||||
=====
|
||||
This patch release removes the use of `feature(i128_type)` from byteorder,
|
||||
|
|
|
@ -12,8 +12,9 @@
|
|||
|
||||
[package]
|
||||
name = "byteorder"
|
||||
version = "1.2.7"
|
||||
version = "1.3.1"
|
||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||
build = "build.rs"
|
||||
exclude = ["/ci/*"]
|
||||
description = "Library for reading/writing numbers in big-endian and little-endian."
|
||||
homepage = "https://github.com/BurntSushi/byteorder"
|
||||
|
@ -30,11 +31,11 @@ opt-level = 3
|
|||
name = "byteorder"
|
||||
bench = false
|
||||
[dev-dependencies.quickcheck]
|
||||
version = "0.7"
|
||||
version = "0.8"
|
||||
default-features = false
|
||||
|
||||
[dev-dependencies.rand]
|
||||
version = "0.5"
|
||||
version = "0.6"
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
|
|
|
@ -148,108 +148,108 @@ bench_num!(int_6, read_int, 6, [1, 2, 3, 4, 5, 6]);
|
|||
bench_num!(int_7, read_int, 7, [1, 2, 3, 4, 5, 6, 7]);
|
||||
bench_num!(int_8, read_int, 8, [1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(u128, MAX, read_u128, write_u128,
|
||||
16, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(i128, MAX, read_i128, write_i128,
|
||||
16, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(uint128_1, read_uint128,
|
||||
1, [1]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(uint128_2, read_uint128,
|
||||
2, [1, 2]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(uint128_3, read_uint128,
|
||||
3, [1, 2, 3]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(uint128_4, read_uint128,
|
||||
4, [1, 2, 3, 4]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(uint128_5, read_uint128,
|
||||
5, [1, 2, 3, 4, 5]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(uint128_6, read_uint128,
|
||||
6, [1, 2, 3, 4, 5, 6]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(uint128_7, read_uint128,
|
||||
7, [1, 2, 3, 4, 5, 6, 7]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(uint128_8, read_uint128,
|
||||
8, [1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(uint128_9, read_uint128,
|
||||
9, [1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(uint128_10, read_uint128,
|
||||
10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(uint128_11, read_uint128,
|
||||
11, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(uint128_12, read_uint128,
|
||||
12, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(uint128_13, read_uint128,
|
||||
13, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(uint128_14, read_uint128,
|
||||
14, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(uint128_15, read_uint128,
|
||||
15, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(uint128_16, read_uint128,
|
||||
16, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(int128_1, read_int128,
|
||||
1, [1]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(int128_2, read_int128,
|
||||
2, [1, 2]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(int128_3, read_int128,
|
||||
3, [1, 2, 3]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(int128_4, read_int128,
|
||||
4, [1, 2, 3, 4]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(int128_5, read_int128,
|
||||
5, [1, 2, 3, 4, 5]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(int128_6, read_int128,
|
||||
6, [1, 2, 3, 4, 5, 6]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(int128_7, read_int128,
|
||||
7, [1, 2, 3, 4, 5, 6, 7]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(int128_8, read_int128,
|
||||
8, [1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(int128_9, read_int128,
|
||||
9, [1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(int128_10, read_int128,
|
||||
10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(int128_11, read_int128,
|
||||
11, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(int128_12, read_int128,
|
||||
12, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(int128_13, read_int128,
|
||||
13, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(int128_14, read_int128,
|
||||
14, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(int128_15, read_int128,
|
||||
15, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
bench_num!(int128_16, read_int128,
|
||||
16, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
|
||||
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
use std::io::{self, Write};
|
||||
use std::process::Command;
|
||||
|
||||
fn main() {
|
||||
let version = match Version::read() {
|
||||
Ok(version) => version,
|
||||
Err(err) => {
|
||||
writeln!(
|
||||
&mut io::stderr(),
|
||||
"failed to parse `rustc --version`: {}",
|
||||
err
|
||||
).unwrap();
|
||||
return;
|
||||
}
|
||||
};
|
||||
enable_i128(version);
|
||||
}
|
||||
|
||||
fn enable_i128(version: Version) {
|
||||
if version < (Version { major: 1, minor: 26, patch: 0 }) {
|
||||
return;
|
||||
}
|
||||
|
||||
println!("cargo:rustc-cfg=byteorder_i128");
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||
struct Version {
|
||||
major: u32,
|
||||
minor: u32,
|
||||
patch: u32,
|
||||
}
|
||||
|
||||
impl Version {
|
||||
fn read() -> Result<Version, String> {
|
||||
let rustc = env::var_os("RUSTC").unwrap_or(OsString::from("rustc"));
|
||||
let output = Command::new(&rustc)
|
||||
.arg("--version")
|
||||
.output()
|
||||
.unwrap()
|
||||
.stdout;
|
||||
Version::parse(&String::from_utf8(output).unwrap())
|
||||
}
|
||||
|
||||
fn parse(mut s: &str) -> Result<Version, String> {
|
||||
if !s.starts_with("rustc ") {
|
||||
return Err(format!("unrecognized version string: {}", s));
|
||||
}
|
||||
s = &s["rustc ".len()..];
|
||||
|
||||
let parts: Vec<&str> = s.split(".").collect();
|
||||
if parts.len() < 3 {
|
||||
return Err(format!("not enough version parts: {:?}", parts));
|
||||
}
|
||||
|
||||
let mut num = String::new();
|
||||
for c in parts[0].chars() {
|
||||
if !c.is_digit(10) {
|
||||
break;
|
||||
}
|
||||
num.push(c);
|
||||
}
|
||||
let major = try!(num.parse::<u32>().map_err(|e| e.to_string()));
|
||||
|
||||
num.clear();
|
||||
for c in parts[1].chars() {
|
||||
if !c.is_digit(10) {
|
||||
break;
|
||||
}
|
||||
num.push(c);
|
||||
}
|
||||
let minor = try!(num.parse::<u32>().map_err(|e| e.to_string()));
|
||||
|
||||
num.clear();
|
||||
for c in parts[2].chars() {
|
||||
if !c.is_digit(10) {
|
||||
break;
|
||||
}
|
||||
num.push(c);
|
||||
}
|
||||
let patch = try!(num.parse::<u32>().map_err(|e| e.to_string()));
|
||||
|
||||
Ok(Version { major: major, minor: minor, patch: patch })
|
||||
}
|
||||
}
|
|
@ -370,7 +370,7 @@ pub trait ReadBytesExt: io::Read {
|
|||
/// ]);
|
||||
/// assert_eq!(16947640962301618749969007319746179, rdr.read_u128::<BigEndian>().unwrap());
|
||||
/// ```
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn read_u128<T: ByteOrder>(&mut self) -> Result<u128> {
|
||||
let mut buf = [0; 16];
|
||||
|
@ -391,14 +391,13 @@ pub trait ReadBytesExt: io::Read {
|
|||
/// Read a signed 128 bit big-endian integer from a `Read`:
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(i128_type)]
|
||||
/// use std::io::Cursor;
|
||||
/// use byteorder::{BigEndian, ReadBytesExt};
|
||||
///
|
||||
/// let mut rdr = Cursor::new(vec![0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
/// assert_eq!(i128::min_value(), rdr.read_i128::<BigEndian>().unwrap());
|
||||
/// ```
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn read_i128<T: ByteOrder>(&mut self) -> Result<i128> {
|
||||
let mut buf = [0; 16];
|
||||
|
@ -457,7 +456,7 @@ pub trait ReadBytesExt: io::Read {
|
|||
}
|
||||
|
||||
/// Reads an unsigned n-bytes integer from the underlying reader.
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn read_uint128<T: ByteOrder>(&mut self, nbytes: usize) -> Result<u128> {
|
||||
let mut buf = [0; 16];
|
||||
|
@ -466,7 +465,7 @@ pub trait ReadBytesExt: io::Read {
|
|||
}
|
||||
|
||||
/// Reads a signed n-bytes integer from the underlying reader.
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn read_int128<T: ByteOrder>(&mut self, nbytes: usize) -> Result<i128> {
|
||||
let mut buf = [0; 16];
|
||||
|
@ -672,7 +671,7 @@ pub trait ReadBytesExt: io::Read {
|
|||
/// rdr.read_u128_into::<BigEndian>(&mut dst).unwrap();
|
||||
/// assert_eq!([517, 768], dst);
|
||||
/// ```
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn read_u128_into<T: ByteOrder>(
|
||||
&mut self,
|
||||
|
@ -822,7 +821,7 @@ pub trait ReadBytesExt: io::Read {
|
|||
/// rdr.read_i128_into::<BigEndian>(&mut dst).unwrap();
|
||||
/// assert_eq!([517, 768], dst);
|
||||
/// ```
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn read_i128_into<T: ByteOrder>(
|
||||
&mut self,
|
||||
|
@ -1373,7 +1372,7 @@ pub trait WriteBytesExt: io::Write {
|
|||
}
|
||||
|
||||
/// Writes an unsigned 128 bit integer to the underlying writer.
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn write_u128<T: ByteOrder>(&mut self, n: u128) -> Result<()> {
|
||||
let mut buf = [0; 16];
|
||||
|
@ -1382,7 +1381,7 @@ pub trait WriteBytesExt: io::Write {
|
|||
}
|
||||
|
||||
/// Writes a signed 128 bit integer to the underlying writer.
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn write_i128<T: ByteOrder>(&mut self, n: i128) -> Result<()> {
|
||||
let mut buf = [0; 16];
|
||||
|
@ -1466,7 +1465,7 @@ pub trait WriteBytesExt: io::Write {
|
|||
///
|
||||
/// If the given integer is not representable in the given number of bytes,
|
||||
/// this method panics. If `nbytes > 16`, this method panics.
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn write_uint128<T: ByteOrder>(
|
||||
&mut self,
|
||||
|
@ -1482,7 +1481,7 @@ pub trait WriteBytesExt: io::Write {
|
|||
///
|
||||
/// If the given integer is not representable in the given number of bytes,
|
||||
/// this method panics. If `nbytes > 16`, this method panics.
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn write_int128<T: ByteOrder>(
|
||||
&mut self,
|
||||
|
|
|
@ -84,7 +84,7 @@ fn extend_sign(val: u64, nbytes: usize) -> i64 {
|
|||
(val << shift) as i64 >> shift
|
||||
}
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn extend_sign128(val: u128, nbytes: usize) -> i128 {
|
||||
let shift = (16 - nbytes) * 8;
|
||||
|
@ -97,7 +97,7 @@ fn unextend_sign(val: i64, nbytes: usize) -> u64 {
|
|||
(val << shift) as u64 >> shift
|
||||
}
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn unextend_sign128(val: i128, nbytes: usize) -> u128 {
|
||||
let shift = (16 - nbytes) * 8;
|
||||
|
@ -125,7 +125,7 @@ fn pack_size(n: u64) -> usize {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn pack_size128(n: u128) -> usize {
|
||||
if n < 1 << 8 {
|
||||
|
@ -314,7 +314,7 @@ pub trait ByteOrder
|
|||
/// LittleEndian::write_u128(&mut buf, 1_000_000);
|
||||
/// assert_eq!(1_000_000, LittleEndian::read_u128(&buf));
|
||||
/// ```
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
fn read_u128(buf: &[u8]) -> u128;
|
||||
|
||||
/// Reads an unsigned n-bytes integer from `buf`.
|
||||
|
@ -355,7 +355,7 @@ pub trait ByteOrder
|
|||
/// LittleEndian::write_uint128(&mut buf, 1_000_000, 3);
|
||||
/// assert_eq!(1_000_000, LittleEndian::read_uint128(&buf, 3));
|
||||
/// ```
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
fn read_uint128(buf: &[u8], nbytes: usize) -> u128;
|
||||
|
||||
/// Writes an unsigned 16 bit integer `n` to `buf`.
|
||||
|
@ -474,7 +474,7 @@ pub trait ByteOrder
|
|||
/// LittleEndian::write_u128(&mut buf, 1_000_000);
|
||||
/// assert_eq!(1_000_000, LittleEndian::read_u128(&buf));
|
||||
/// ```
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
fn write_u128(buf: &mut [u8], n: u128);
|
||||
|
||||
/// Writes an unsigned integer `n` to `buf` using only `nbytes`.
|
||||
|
@ -515,7 +515,7 @@ pub trait ByteOrder
|
|||
/// LittleEndian::write_uint128(&mut buf, 1_000_000, 3);
|
||||
/// assert_eq!(1_000_000, LittleEndian::read_uint128(&buf, 3));
|
||||
/// ```
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
fn write_uint128(buf: &mut [u8], n: u128, nbytes: usize);
|
||||
|
||||
/// Reads a signed 16 bit integer from `buf`.
|
||||
|
@ -645,7 +645,7 @@ pub trait ByteOrder
|
|||
/// LittleEndian::write_i128(&mut buf, -1_000_000_000);
|
||||
/// assert_eq!(-1_000_000_000, LittleEndian::read_i128(&buf));
|
||||
/// ```
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn read_i128(buf: &[u8]) -> i128 {
|
||||
Self::read_u128(buf) as i128
|
||||
|
@ -692,7 +692,7 @@ pub trait ByteOrder
|
|||
/// LittleEndian::write_int128(&mut buf, -1_000, 3);
|
||||
/// assert_eq!(-1_000, LittleEndian::read_int128(&buf, 3));
|
||||
/// ```
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn read_int128(buf: &[u8], nbytes: usize) -> i128 {
|
||||
extend_sign128(Self::read_uint128(buf, nbytes), nbytes)
|
||||
|
@ -871,7 +871,7 @@ pub trait ByteOrder
|
|||
/// LittleEndian::write_i128(&mut buf, -1_000_000_000);
|
||||
/// assert_eq!(-1_000_000_000, LittleEndian::read_i128(&buf));
|
||||
/// ```
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn write_i128(buf: &mut [u8], n: i128) {
|
||||
Self::write_u128(buf, n as u128)
|
||||
|
@ -918,7 +918,7 @@ pub trait ByteOrder
|
|||
/// LittleEndian::write_int128(&mut buf, -1_000, 3);
|
||||
/// assert_eq!(-1_000, LittleEndian::read_int128(&buf, 3));
|
||||
/// ```
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn write_int128(buf: &mut [u8], n: i128, nbytes: usize) {
|
||||
Self::write_uint128(buf, unextend_sign128(n, nbytes), nbytes)
|
||||
|
@ -1062,7 +1062,7 @@ pub trait ByteOrder
|
|||
/// LittleEndian::read_u128_into(&bytes, &mut numbers_got);
|
||||
/// assert_eq!(numbers_given, numbers_got);
|
||||
/// ```
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
fn read_u128_into(src: &[u8], dst: &mut [u128]);
|
||||
|
||||
/// Reads signed 16 bit integers from `src` to `dst`.
|
||||
|
@ -1173,7 +1173,7 @@ pub trait ByteOrder
|
|||
/// LittleEndian::read_i128_into(&bytes, &mut numbers_got);
|
||||
/// assert_eq!(numbers_given, numbers_got);
|
||||
/// ```
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn read_i128_into(src: &[u8], dst: &mut [i128]) {
|
||||
let dst = unsafe {
|
||||
|
@ -1197,7 +1197,40 @@ pub trait ByteOrder
|
|||
/// use byteorder::{ByteOrder, LittleEndian};
|
||||
///
|
||||
/// let mut bytes = [0; 16];
|
||||
/// let numbers_given = [1.0, 2.0, 31.312e311, -11.32e91];
|
||||
/// let numbers_given = [1.0, 2.0, 31.312e31, -11.32e19];
|
||||
/// LittleEndian::write_f32_into(&numbers_given, &mut bytes);
|
||||
///
|
||||
/// let mut numbers_got = [0.0; 4];
|
||||
/// LittleEndian::read_f32_into(&bytes, &mut numbers_got);
|
||||
/// assert_eq!(numbers_given, numbers_got);
|
||||
/// ```
|
||||
#[inline]
|
||||
fn read_f32_into(src: &[u8], dst: &mut [f32]) {
|
||||
let dst = unsafe {
|
||||
slice::from_raw_parts_mut(dst.as_mut_ptr() as *mut u32, dst.len())
|
||||
};
|
||||
Self::read_u32_into(src, dst);
|
||||
}
|
||||
|
||||
/// **DEPRECATED**.
|
||||
///
|
||||
/// This method is deprecated. Use `read_f32_into` instead.
|
||||
/// Reads IEEE754 single-precision (4 bytes) floating point numbers from
|
||||
/// `src` into `dst`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics when `src.len() != 4*dst.len()`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Write and read `f32` numbers in little endian order:
|
||||
///
|
||||
/// ```rust
|
||||
/// use byteorder::{ByteOrder, LittleEndian};
|
||||
///
|
||||
/// let mut bytes = [0; 16];
|
||||
/// let numbers_given = [1.0, 2.0, 31.312e31, -11.32e19];
|
||||
/// LittleEndian::write_f32_into(&numbers_given, &mut bytes);
|
||||
///
|
||||
/// let mut numbers_got = [0.0; 4];
|
||||
|
@ -1205,13 +1238,45 @@ pub trait ByteOrder
|
|||
/// assert_eq!(numbers_given, numbers_got);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[deprecated(since="1.3.0", note="please use `read_f32_into` instead")]
|
||||
fn read_f32_into_unchecked(src: &[u8], dst: &mut [f32]) {
|
||||
let dst = unsafe {
|
||||
slice::from_raw_parts_mut(dst.as_mut_ptr() as *mut u32, dst.len())
|
||||
};
|
||||
Self::read_u32_into(src, dst);
|
||||
Self::read_f32_into(src, dst);
|
||||
}
|
||||
|
||||
/// Reads IEEE754 single-precision (4 bytes) floating point numbers from
|
||||
/// `src` into `dst`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics when `src.len() != 8*dst.len()`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Write and read `f64` numbers in little endian order:
|
||||
///
|
||||
/// ```rust
|
||||
/// use byteorder::{ByteOrder, LittleEndian};
|
||||
///
|
||||
/// let mut bytes = [0; 32];
|
||||
/// let numbers_given = [1.0, 2.0, 31.312e311, -11.32e91];
|
||||
/// LittleEndian::write_f64_into(&numbers_given, &mut bytes);
|
||||
///
|
||||
/// let mut numbers_got = [0.0; 4];
|
||||
/// LittleEndian::read_f64_into(&bytes, &mut numbers_got);
|
||||
/// assert_eq!(numbers_given, numbers_got);
|
||||
/// ```
|
||||
#[inline]
|
||||
fn read_f64_into(src: &[u8], dst: &mut [f64]) {
|
||||
let dst = unsafe {
|
||||
slice::from_raw_parts_mut(dst.as_mut_ptr() as *mut u64, dst.len())
|
||||
};
|
||||
Self::read_u64_into(src, dst);
|
||||
}
|
||||
|
||||
/// **DEPRECATED**.
|
||||
///
|
||||
/// This method is deprecated. Use `read_f64_into` instead.
|
||||
///
|
||||
/// Reads IEEE754 single-precision (4 bytes) floating point numbers from
|
||||
/// `src` into `dst`.
|
||||
///
|
||||
|
@ -1235,11 +1300,9 @@ pub trait ByteOrder
|
|||
/// assert_eq!(numbers_given, numbers_got);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[deprecated(since="1.3.0", note="please use `read_f64_into` instead")]
|
||||
fn read_f64_into_unchecked(src: &[u8], dst: &mut [f64]) {
|
||||
let dst = unsafe {
|
||||
slice::from_raw_parts_mut(dst.as_mut_ptr() as *mut u64, dst.len())
|
||||
};
|
||||
Self::read_u64_into(src, dst);
|
||||
Self::read_f64_into(src, dst);
|
||||
}
|
||||
|
||||
/// Writes unsigned 16 bit integers from `src` into `dst`.
|
||||
|
@ -1332,7 +1395,7 @@ pub trait ByteOrder
|
|||
/// LittleEndian::read_u128_into(&bytes, &mut numbers_got);
|
||||
/// assert_eq!(numbers_given, numbers_got);
|
||||
/// ```
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
fn write_u128_into(src: &[u128], dst: &mut [u8]);
|
||||
|
||||
/// Writes signed 16 bit integers from `src` into `dst`.
|
||||
|
@ -1440,7 +1503,7 @@ pub trait ByteOrder
|
|||
/// LittleEndian::read_i128_into(&bytes, &mut numbers_got);
|
||||
/// assert_eq!(numbers_given, numbers_got);
|
||||
/// ```
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
fn write_i128_into(src: &[i128], dst: &mut [u8]) {
|
||||
let src = unsafe {
|
||||
slice::from_raw_parts(src.as_ptr() as *const u128, src.len())
|
||||
|
@ -1463,12 +1526,12 @@ pub trait ByteOrder
|
|||
/// use byteorder::{ByteOrder, LittleEndian};
|
||||
///
|
||||
/// let mut bytes = [0; 16];
|
||||
/// let numbers_given = [1.0, 2.0, 31.312e311, -11.32e91];
|
||||
/// let numbers_given = [1.0, 2.0, 31.312e31, -11.32e19];
|
||||
/// LittleEndian::write_f32_into(&numbers_given, &mut bytes);
|
||||
///
|
||||
/// let mut numbers_got = [0.0; 4];
|
||||
/// unsafe {
|
||||
/// LittleEndian::read_f32_into_unchecked(&bytes, &mut numbers_got);
|
||||
/// LittleEndian::read_f32_into(&bytes, &mut numbers_got);
|
||||
/// }
|
||||
/// assert_eq!(numbers_given, numbers_got);
|
||||
/// ```
|
||||
|
@ -1499,7 +1562,7 @@ pub trait ByteOrder
|
|||
///
|
||||
/// let mut numbers_got = [0.0; 4];
|
||||
/// unsafe {
|
||||
/// LittleEndian::read_f64_into_unchecked(&bytes, &mut numbers_got);
|
||||
/// LittleEndian::read_f64_into(&bytes, &mut numbers_got);
|
||||
/// }
|
||||
/// assert_eq!(numbers_given, numbers_got);
|
||||
/// ```
|
||||
|
@ -1584,7 +1647,7 @@ pub trait ByteOrder
|
|||
/// BigEndian::from_slice_u128(&mut numbers);
|
||||
/// assert_eq!(numbers, [5u128.to_be(), 65000u128.to_be()]);
|
||||
/// ```
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
fn from_slice_u128(numbers: &mut [u128]);
|
||||
|
||||
/// Converts the given slice of signed 16 bit integers to a particular
|
||||
|
@ -1679,7 +1742,7 @@ pub trait ByteOrder
|
|||
/// BigEndian::from_slice_i128(&mut numbers);
|
||||
/// assert_eq!(numbers, [5i128.to_be(), 65000i128.to_be()]);
|
||||
/// ```
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn from_slice_i128(src: &mut [i128]) {
|
||||
let src = unsafe {
|
||||
|
@ -1894,7 +1957,7 @@ impl ByteOrder for BigEndian {
|
|||
read_num_bytes!(u64, 8, buf, to_be)
|
||||
}
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn read_u128(buf: &[u8]) -> u128 {
|
||||
read_num_bytes!(u128, 16, buf, to_be)
|
||||
|
@ -1912,7 +1975,7 @@ impl ByteOrder for BigEndian {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn read_uint128(buf: &[u8], nbytes: usize) -> u128 {
|
||||
assert!(1 <= nbytes && nbytes <= 16 && nbytes <= buf.len());
|
||||
|
@ -1940,7 +2003,7 @@ impl ByteOrder for BigEndian {
|
|||
write_num_bytes!(u64, 8, n, buf, to_be);
|
||||
}
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn write_u128(buf: &mut [u8], n: u128) {
|
||||
write_num_bytes!(u128, 16, n, buf, to_be);
|
||||
|
@ -1959,7 +2022,7 @@ impl ByteOrder for BigEndian {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn write_uint128(buf: &mut [u8], n: u128, nbytes: usize) {
|
||||
assert!(pack_size128(n) <= nbytes && nbytes <= 16);
|
||||
|
@ -1988,7 +2051,7 @@ impl ByteOrder for BigEndian {
|
|||
read_slice!(src, dst, 8, to_be);
|
||||
}
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn read_u128_into(src: &[u8], dst: &mut [u128]) {
|
||||
read_slice!(src, dst, 16, to_be);
|
||||
|
@ -2021,7 +2084,7 @@ impl ByteOrder for BigEndian {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn write_u128_into(src: &[u128], dst: &mut [u8]) {
|
||||
if cfg!(target_endian = "big") {
|
||||
|
@ -2058,7 +2121,7 @@ impl ByteOrder for BigEndian {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn from_slice_u128(numbers: &mut [u128]) {
|
||||
if cfg!(target_endian = "little") {
|
||||
|
@ -2109,7 +2172,7 @@ impl ByteOrder for LittleEndian {
|
|||
read_num_bytes!(u64, 8, buf, to_le)
|
||||
}
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn read_u128(buf: &[u8]) -> u128 {
|
||||
read_num_bytes!(u128, 16, buf, to_le)
|
||||
|
@ -2126,7 +2189,7 @@ impl ByteOrder for LittleEndian {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn read_uint128(buf: &[u8], nbytes: usize) -> u128 {
|
||||
assert!(1 <= nbytes && nbytes <= 16 && nbytes <= buf.len());
|
||||
|
@ -2153,7 +2216,7 @@ impl ByteOrder for LittleEndian {
|
|||
write_num_bytes!(u64, 8, n, buf, to_le);
|
||||
}
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn write_u128(buf: &mut [u8], n: u128) {
|
||||
write_num_bytes!(u128, 16, n, buf, to_le);
|
||||
|
@ -2169,7 +2232,7 @@ impl ByteOrder for LittleEndian {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn write_uint128(buf: &mut [u8], n: u128, nbytes: usize) {
|
||||
assert!(pack_size128(n as u128) <= nbytes && nbytes <= 16);
|
||||
|
@ -2195,7 +2258,7 @@ impl ByteOrder for LittleEndian {
|
|||
read_slice!(src, dst, 8, to_le);
|
||||
}
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn read_u128_into(src: &[u8], dst: &mut [u128]) {
|
||||
read_slice!(src, dst, 16, to_le);
|
||||
|
@ -2228,7 +2291,7 @@ impl ByteOrder for LittleEndian {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn write_u128_into(src: &[u128], dst: &mut [u8]) {
|
||||
if cfg!(target_endian = "little") {
|
||||
|
@ -2265,7 +2328,7 @@ impl ByteOrder for LittleEndian {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
#[inline]
|
||||
fn from_slice_u128(numbers: &mut [u128]) {
|
||||
if cfg!(target_endian = "big") {
|
||||
|
@ -2306,8 +2369,11 @@ mod test {
|
|||
extern crate rand;
|
||||
|
||||
use self::quickcheck::{QuickCheck, StdGen, Testable};
|
||||
use self::rand::{Rng, thread_rng};
|
||||
#[cfg(feature = "i128")] use self::quickcheck::{Arbitrary, Gen};
|
||||
use self::rand::thread_rng;
|
||||
#[cfg(byteorder_i128)]
|
||||
use self::rand::Rng;
|
||||
#[cfg(byteorder_i128)]
|
||||
use self::quickcheck::{Arbitrary, Gen};
|
||||
|
||||
pub const U24_MAX: u32 = 16_777_215;
|
||||
pub const I24_MAX: i32 = 8_388_607;
|
||||
|
@ -2327,7 +2393,7 @@ mod test {
|
|||
#[derive(Clone, Debug)]
|
||||
pub struct Wi128<T>(pub T);
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
impl<T: Clone> Wi128<T> {
|
||||
pub fn clone(&self) -> T {
|
||||
self.0.clone()
|
||||
|
@ -2340,7 +2406,7 @@ mod test {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
impl Arbitrary for Wi128<u128> {
|
||||
fn arbitrary<G: Gen>(gen: &mut G) -> Wi128<u128> {
|
||||
let max = calc_max!(::core::u128::MAX, gen.size(), 16);
|
||||
|
@ -2351,7 +2417,7 @@ mod test {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
impl Arbitrary for Wi128<i128> {
|
||||
fn arbitrary<G: Gen>(gen: &mut G) -> Wi128<i128> {
|
||||
let max = calc_max!(::core::i128::MAX, gen.size(), 16);
|
||||
|
@ -2464,9 +2530,9 @@ mod test {
|
|||
qc_byte_order!(prop_f32, f32, ::core::u64::MAX as u64, read_f32, write_f32);
|
||||
qc_byte_order!(prop_f64, f64, ::core::i64::MAX as u64, read_f64, write_f64);
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_u128, Wi128<u128>, 16 + 1, read_u128, write_u128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_i128, Wi128<i128>, 16 + 1, read_i128, write_i128);
|
||||
|
||||
qc_byte_order!(prop_uint_1,
|
||||
|
@ -2486,52 +2552,52 @@ mod test {
|
|||
qc_byte_order!(prop_uint_8,
|
||||
u64, calc_max!(super::U64_MAX, 8), 8, read_uint, write_uint);
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_uint128_1,
|
||||
Wi128<u128>, 1, 1, read_uint128, write_uint128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_uint128_2,
|
||||
Wi128<u128>, 2, 2, read_uint128, write_uint128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_uint128_3,
|
||||
Wi128<u128>, 3, 3, read_uint128, write_uint128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_uint128_4,
|
||||
Wi128<u128>, 4, 4, read_uint128, write_uint128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_uint128_5,
|
||||
Wi128<u128>, 5, 5, read_uint128, write_uint128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_uint128_6,
|
||||
Wi128<u128>, 6, 6, read_uint128, write_uint128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_uint128_7,
|
||||
Wi128<u128>, 7, 7, read_uint128, write_uint128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_uint128_8,
|
||||
Wi128<u128>, 8, 8, read_uint128, write_uint128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_uint128_9,
|
||||
Wi128<u128>, 9, 9, read_uint128, write_uint128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_uint128_10,
|
||||
Wi128<u128>, 10, 10, read_uint128, write_uint128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_uint128_11,
|
||||
Wi128<u128>, 11, 11, read_uint128, write_uint128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_uint128_12,
|
||||
Wi128<u128>, 12, 12, read_uint128, write_uint128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_uint128_13,
|
||||
Wi128<u128>, 13, 13, read_uint128, write_uint128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_uint128_14,
|
||||
Wi128<u128>, 14, 14, read_uint128, write_uint128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_uint128_15,
|
||||
Wi128<u128>, 15, 15, read_uint128, write_uint128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_uint128_16,
|
||||
Wi128<u128>, 16, 16, read_uint128, write_uint128);
|
||||
|
||||
|
@ -2552,52 +2618,52 @@ mod test {
|
|||
qc_byte_order!(prop_int_8,
|
||||
i64, calc_max!(super::I64_MAX, 8), 8, read_int, write_int);
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_int128_1,
|
||||
Wi128<i128>, 1, 1, read_int128, write_int128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_int128_2,
|
||||
Wi128<i128>, 2, 2, read_int128, write_int128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_int128_3,
|
||||
Wi128<i128>, 3, 3, read_int128, write_int128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_int128_4,
|
||||
Wi128<i128>, 4, 4, read_int128, write_int128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_int128_5,
|
||||
Wi128<i128>, 5, 5, read_int128, write_int128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_int128_6,
|
||||
Wi128<i128>, 6, 6, read_int128, write_int128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_int128_7,
|
||||
Wi128<i128>, 7, 7, read_int128, write_int128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_int128_8,
|
||||
Wi128<i128>, 8, 8, read_int128, write_int128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_int128_9,
|
||||
Wi128<i128>, 9, 9, read_int128, write_int128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_int128_10,
|
||||
Wi128<i128>, 10, 10, read_int128, write_int128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_int128_11,
|
||||
Wi128<i128>, 11, 11, read_int128, write_int128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_int128_12,
|
||||
Wi128<i128>, 12, 12, read_int128, write_int128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_int128_13,
|
||||
Wi128<i128>, 13, 13, read_int128, write_int128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_int128_14,
|
||||
Wi128<i128>, 14, 14, read_int128, write_int128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_int128_15,
|
||||
Wi128<i128>, 15, 15, read_int128, write_int128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_byte_order!(prop_int128_16,
|
||||
Wi128<i128>, 16, 16, read_int128, write_int128);
|
||||
|
||||
|
@ -2692,9 +2758,9 @@ mod test {
|
|||
too_small!(small_i64, 7, 0, read_i64, write_i64);
|
||||
too_small!(small_f32, 3, 0.0, read_f32, write_f32);
|
||||
too_small!(small_f64, 7, 0.0, read_f64, write_f64);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_u128, 15, 0, read_u128, write_u128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_i128, 15, 0, read_i128, write_i128);
|
||||
|
||||
too_small!(small_uint_1, 1, read_uint);
|
||||
|
@ -2705,35 +2771,35 @@ mod test {
|
|||
too_small!(small_uint_6, 6, read_uint);
|
||||
too_small!(small_uint_7, 7, read_uint);
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_uint128_1, 1, read_uint128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_uint128_2, 2, read_uint128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_uint128_3, 3, read_uint128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_uint128_4, 4, read_uint128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_uint128_5, 5, read_uint128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_uint128_6, 6, read_uint128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_uint128_7, 7, read_uint128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_uint128_8, 8, read_uint128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_uint128_9, 9, read_uint128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_uint128_10, 10, read_uint128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_uint128_11, 11, read_uint128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_uint128_12, 12, read_uint128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_uint128_13, 13, read_uint128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_uint128_14, 14, read_uint128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_uint128_15, 15, read_uint128);
|
||||
|
||||
too_small!(small_int_1, 1, read_int);
|
||||
|
@ -2744,35 +2810,35 @@ mod test {
|
|||
too_small!(small_int_6, 6, read_int);
|
||||
too_small!(small_int_7, 7, read_int);
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_int128_1, 1, read_int128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_int128_2, 2, read_int128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_int128_3, 3, read_int128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_int128_4, 4, read_int128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_int128_5, 5, read_int128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_int128_6, 6, read_int128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_int128_7, 7, read_int128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_int128_8, 8, read_int128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_int128_9, 9, read_int128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_int128_10, 10, read_int128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_int128_11, 11, read_int128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_int128_12, 12, read_int128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_int128_13, 13, read_int128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_int128_14, 14, read_int128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
too_small!(small_int128_15, 15, read_int128);
|
||||
|
||||
// Test that reading/writing slices enforces the correct lengths.
|
||||
|
@ -2860,16 +2926,16 @@ mod test {
|
|||
slice_lengths!(
|
||||
slice_len_too_big_i64, read_i64_into, write_i64_into, 17, [0, 0]);
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
slice_lengths!(
|
||||
slice_len_too_small_u128, read_u128_into, write_u128_into, 31, [0, 0]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
slice_lengths!(
|
||||
slice_len_too_big_u128, read_u128_into, write_u128_into, 33, [0, 0]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
slice_lengths!(
|
||||
slice_len_too_small_i128, read_i128_into, write_i128_into, 31, [0, 0]);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
slice_lengths!(
|
||||
slice_len_too_big_i128, read_i128_into, write_i128_into, 33, [0, 0]);
|
||||
|
||||
|
@ -3016,9 +3082,9 @@ mod stdtests {
|
|||
qc_bytes_ext!(prop_ext_f64,
|
||||
f64, ::std::i64::MAX as u64, read_f64, write_f64);
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_u128, Wi128<u128>, 16 + 1, read_u128, write_u128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_i128, Wi128<i128>, 16 + 1, read_i128, write_i128);
|
||||
|
||||
qc_bytes_ext!(prop_ext_uint_1,
|
||||
|
@ -3038,52 +3104,52 @@ mod stdtests {
|
|||
qc_bytes_ext!(prop_ext_uint_8,
|
||||
u64, calc_max!(::test::U64_MAX, 8), 8, read_uint, write_u64);
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_uint128_1,
|
||||
Wi128<u128>, 1, 1, read_uint128, write_u128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_uint128_2,
|
||||
Wi128<u128>, 2, 2, read_uint128, write_u128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_uint128_3,
|
||||
Wi128<u128>, 3, 3, read_uint128, write_u128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_uint128_4,
|
||||
Wi128<u128>, 4, 4, read_uint128, write_u128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_uint128_5,
|
||||
Wi128<u128>, 5, 5, read_uint128, write_u128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_uint128_6,
|
||||
Wi128<u128>, 6, 6, read_uint128, write_u128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_uint128_7,
|
||||
Wi128<u128>, 7, 7, read_uint128, write_u128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_uint128_8,
|
||||
Wi128<u128>, 8, 8, read_uint128, write_u128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_uint128_9,
|
||||
Wi128<u128>, 9, 9, read_uint128, write_u128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_uint128_10,
|
||||
Wi128<u128>, 10, 10, read_uint128, write_u128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_uint128_11,
|
||||
Wi128<u128>, 11, 11, read_uint128, write_u128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_uint128_12,
|
||||
Wi128<u128>, 12, 12, read_uint128, write_u128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_uint128_13,
|
||||
Wi128<u128>, 13, 13, read_uint128, write_u128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_uint128_14,
|
||||
Wi128<u128>, 14, 14, read_uint128, write_u128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_uint128_15,
|
||||
Wi128<u128>, 15, 15, read_uint128, write_u128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_uint128_16,
|
||||
Wi128<u128>, 16, 16, read_uint128, write_u128);
|
||||
|
||||
|
@ -3104,52 +3170,52 @@ mod stdtests {
|
|||
qc_bytes_ext!(prop_ext_int_8,
|
||||
i64, calc_max!(::test::I64_MAX, 8), 8, read_int, write_i64);
|
||||
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_int128_1,
|
||||
Wi128<i128>, 1, 1, read_int128, write_i128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_int128_2,
|
||||
Wi128<i128>, 2, 2, read_int128, write_i128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_int128_3,
|
||||
Wi128<i128>, 3, 3, read_int128, write_i128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_int128_4,
|
||||
Wi128<i128>, 4, 4, read_int128, write_i128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_int128_5,
|
||||
Wi128<i128>, 5, 5, read_int128, write_i128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_int128_6,
|
||||
Wi128<i128>, 6, 6, read_int128, write_i128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_int128_7,
|
||||
Wi128<i128>, 7, 7, read_int128, write_i128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_int128_8,
|
||||
Wi128<i128>, 8, 8, read_int128, write_i128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_int128_9,
|
||||
Wi128<i128>, 9, 9, read_int128, write_i128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_int128_10,
|
||||
Wi128<i128>, 10, 10, read_int128, write_i128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_int128_11,
|
||||
Wi128<i128>, 11, 11, read_int128, write_i128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_int128_12,
|
||||
Wi128<i128>, 12, 12, read_int128, write_i128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_int128_13,
|
||||
Wi128<i128>, 13, 13, read_int128, write_i128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_int128_14,
|
||||
Wi128<i128>, 14, 14, read_int128, write_i128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_int128_15,
|
||||
Wi128<i128>, 15, 15, read_int128, write_i128);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_bytes_ext!(prop_ext_int128_16,
|
||||
Wi128<i128>, 16, 16, read_int128, write_i128);
|
||||
|
||||
|
@ -3235,15 +3301,15 @@ mod stdtests {
|
|||
qc_slice!(prop_slice_i32, i32, read_i32_into, write_i32_into, 0);
|
||||
qc_slice!(prop_slice_u64, u64, read_u64_into, write_u64_into, 0);
|
||||
qc_slice!(prop_slice_i64, i64, read_i64_into, write_i64_into, 0);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_slice!(
|
||||
prop_slice_u128, Wi128<u128>, read_u128_into, write_u128_into, 0);
|
||||
#[cfg(feature = "i128")]
|
||||
#[cfg(byteorder_i128)]
|
||||
qc_slice!(
|
||||
prop_slice_i128, Wi128<i128>, read_i128_into, write_i128_into, 0);
|
||||
|
||||
qc_slice!(
|
||||
prop_slice_f32, f32, read_f32_into_unchecked, write_f32_into, 0.0);
|
||||
prop_slice_f32, f32, read_f32_into, write_f32_into, 0.0);
|
||||
qc_slice!(
|
||||
prop_slice_f64, f64, read_f64_into_unchecked, write_f64_into, 0.0);
|
||||
prop_slice_f64, f64, read_f64_into, write_f64_into, 0.0);
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"COPYING":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"6bf850af90d5a3828cf26170a161f2ed06fa3cf3783dce79d28fe6444654408e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"1acb12040be43a3582d5897f11870b3ffdcd7ce0f4f32de158175bb6b33ec0b7","build.rs":"6ee689b1edfcd469dea669b0dc11ca89e0172c3b58bb82ff7a58acc94e1f7e88","rustfmt.toml":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","src/gl.rs":"2663b598573f7521d06f878229eee65434c831cf9fd4b543b4fcdd3bb1b281aa","src/gl_fns.rs":"239ace5607ee8dd4bcad35db0c4908469d7deb4841c162f736e404e1403980f7","src/gles_fns.rs":"51f25388f092242fb25bfe4861e70690006f4ac28e854d709ebb440cbef3df03","src/lib.rs":"16610c19b45a3f26d56b379a3591aa2e4fc9477e7bd88f86b31c6ea32e834861"},"package":"39bb69499005e11b7b7cc0af38404a1bc0f53d954bffa8adcdb6e8d5b14f75d5"}
|
||||
{"files":{"COPYING":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"40dda1b03ff20d8a3b4b544683f37a8d2b2137cfbb4d545122167352690d6b16","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"1acb12040be43a3582d5897f11870b3ffdcd7ce0f4f32de158175bb6b33ec0b7","build.rs":"2d3833a24fee9d1f669f4cd7347b4ca8444a138d473ab9188f4d65f6981c4191","rustfmt.toml":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","src/gl.rs":"b7791f77dbbea690a7a0d33e3c083337a6b04a233a192dc8c96d4fe481a4a7ed","src/gl_fns.rs":"f88cd940691e0fca169cabbe2a95418300d09392d91a020079cfbdd5bacd753b","src/gles_fns.rs":"3766f2b76aa4038774a4754ce89cdcbb50286ab5bcf07cb0bb6e88f0de31f96f","src/lib.rs":"16610c19b45a3f26d56b379a3591aa2e4fc9477e7bd88f86b31c6ea32e834861"},"package":"7f46fd8874e043ffac0d638ed1567a2584f7814f6d72b4db37ab1689004a26c4"}
|
|
@ -3,7 +3,7 @@
|
|||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g. crates.io) dependencies
|
||||
# to registry (e.g., crates.io) dependencies
|
||||
#
|
||||
# If you believe there's an error in this file please file an
|
||||
# issue against the rust-lang/cargo repository. If you're
|
||||
|
@ -12,7 +12,7 @@
|
|||
|
||||
[package]
|
||||
name = "gleam"
|
||||
version = "0.6.16"
|
||||
version = "0.6.17"
|
||||
authors = ["The Servo Project Developers"]
|
||||
build = "build.rs"
|
||||
description = "Generated OpenGL bindings and wrapper for Servo."
|
||||
|
|
|
@ -26,6 +26,8 @@ fn main() {
|
|||
"GL_EXT_debug_marker",
|
||||
"GL_EXT_texture_filter_anisotropic",
|
||||
"GL_KHR_debug",
|
||||
"GL_KHR_blend_equation_advanced",
|
||||
"GL_KHR_blend_equation_advanced_coherent",
|
||||
];
|
||||
let gl_reg = Registry::new(
|
||||
Api::Gl,
|
||||
|
@ -47,12 +49,14 @@ fn main() {
|
|||
"GL_EXT_texture_filter_anisotropic",
|
||||
"GL_EXT_texture_format_BGRA8888",
|
||||
"GL_EXT_texture_storage",
|
||||
"GL_KHR_debug",
|
||||
"GL_OES_EGL_image_external",
|
||||
"GL_OES_EGL_image",
|
||||
"GL_OES_texture_half_float",
|
||||
"GL_EXT_shader_pixel_local_storage",
|
||||
"GL_ANGLE_provoking_vertex",
|
||||
"GL_KHR_debug",
|
||||
"GL_KHR_blend_equation_advanced",
|
||||
"GL_KHR_blend_equation_advanced_coherent",
|
||||
];
|
||||
let gles_reg = Registry::new(
|
||||
Api::Gles2,
|
||||
|
|
|
@ -568,6 +568,8 @@ declare_gl_apis! {
|
|||
fn test_fence_apple(&self, fence: GLuint);
|
||||
fn test_object_apple(&self, object: GLenum, name: GLuint) -> GLboolean;
|
||||
fn finish_object_apple(&self, object: GLenum, name: GLuint);
|
||||
// GL_KHR_blend_equation_advanced
|
||||
fn blend_barrier_khr(&self);
|
||||
|
||||
// GL_ARB_blend_func_extended
|
||||
fn bind_frag_data_location_indexed(
|
||||
|
|
|
@ -2144,4 +2144,13 @@ impl Gl for GlFns {
|
|||
fn provoking_vertex_angle(&self, _mode: GLenum) {
|
||||
unimplemented!("This extension is GLES only");
|
||||
}
|
||||
|
||||
// GL_KHR_blend_equation_advanced
|
||||
fn blend_barrier_khr(&self) {
|
||||
if self.ffi_gl_.BlendBarrierKHR.is_loaded() {
|
||||
unsafe {
|
||||
self.ffi_gl_.BlendBarrierKHR();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2111,4 +2111,13 @@ impl Gl for GlesFns {
|
|||
self.ffi_gl_.ProvokingVertexANGLE(mode);
|
||||
}
|
||||
}
|
||||
|
||||
// GL_KHR_blend_equation_advanced
|
||||
fn blend_barrier_khr(&self) {
|
||||
if self.ffi_gl_.BlendBarrierKHR.is_loaded() {
|
||||
unsafe {
|
||||
self.ffi_gl_.BlendBarrierKHR();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
{"files":{"CHANGELOG.rst":"11fdd5b156fc2ef5fb7ed980ba91c2a32bdabb79fa386926cbd70673ca6086a5","Cargo.toml":"f61656d89dfd6de3f420e021a55672979d02c4732154b3e91122582af084b8b5","LICENSE":"bb5492d70d4de524e3e29507fb9d87165a49acbc3a5b0e946aaed7e8cfbbd01b","README.rst":"9abdacc75d4886d6201d22b4406353beafb0f3012180109d47fca78e3b8ee5a2","src/hasher.rs":"0022eaa0525dc48b1d8e1dae3fdf5b86b8ae036cb6f87d68f3f5e3b31819f90f","src/lib.rs":"5fc49f47993193b09f170de2747679dc090ff7ec3a62858d62e8cb5213c67392","src/mmh3_128.rs":"0003106e26c34bd9b98155a19953bba946ae4c7899427b160dd74060afa96805","src/mmh3_32.rs":"67fef38bb5f6f4109b401d4b4aaa6bdd3fd4b83f89caeac6666b5f2173a8340e"},"package":"a2983372caf4480544083767bf2d27defafe32af49ab4df3a0b7fc90793a3664"}
|
|
@ -0,0 +1,24 @@
|
|||
Change Log
|
||||
==========
|
||||
|
||||
Unreleased_
|
||||
----------
|
||||
|
||||
0.0.4_ — 2014-04-04
|
||||
----------
|
||||
|
||||
* Enable ``HashState`` implementation
|
||||
|
||||
|
||||
0.0.3_ — 2014-03-29
|
||||
------------------
|
||||
|
||||
* PR1_: Fixes to keep Rust Nightly compatibility, thanks polyfractal_
|
||||
|
||||
|
||||
.. _Unreleased: https://github.com/mhallin/murmurhash3-rs/compare/v0.0.4...HEAD
|
||||
.. _0.0.4: https://github.com/mhallin/murmurhash3-rs/compare/v0.0.3...v0.0.4
|
||||
.. _0.0.3: https://github.com/mhallin/murmurhash3-rs/compare/v0.0.2...v0.0.3
|
||||
|
||||
.. _PR1: https://github.com/mhallin/murmurhash3-rs/pull/1
|
||||
.. _polyfractal: https://github.com/polyfractal
|
|
@ -0,0 +1,19 @@
|
|||
[package]
|
||||
|
||||
name = "murmurhash3"
|
||||
version = "0.0.5"
|
||||
authors = ["mhallin <mhallin@gmail.com>"]
|
||||
description = "MurmurHash3 implementation"
|
||||
license = "MIT"
|
||||
readme = "README.rst"
|
||||
homepage = "https://github.com/mhallin/murmurhash3-rs"
|
||||
|
||||
[lib]
|
||||
name = "murmurhash3"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dev-dependencies]
|
||||
rand = "*"
|
||||
|
||||
[features]
|
||||
nightly = []
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Magnus Hallin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,50 @@
|
|||
**************
|
||||
MurmurHash3.rs
|
||||
**************
|
||||
|
||||
.. image:: https://travis-ci.org/mhallin/murmurhash3-rs.svg?branch=master
|
||||
:target: https://travis-ci.org/mhallin/murmurhash3-rs
|
||||
|
||||
A rust implementation of the MurmurHash3_. Both 32 bit and 128 bit versions are included. The 128
|
||||
bit version is implemented with 64 bit datatypes, making it most suitable for x86_64 or other 64 bit
|
||||
architectures.
|
||||
|
||||
----
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
In your ``Cargo.toml``:
|
||||
|
||||
.. code:: toml
|
||||
|
||||
[dependencies]
|
||||
murmurhash3 = "*"
|
||||
|
||||
Then you can start to use either ``murmurhash3_x86_32`` or ``murmurhash3_x64_128``:
|
||||
|
||||
.. code:: rust
|
||||
|
||||
use murmurhash3::murmurhash3_x64_128;
|
||||
|
||||
fn hash_value() {
|
||||
let data = "test data";
|
||||
let seed = 48221234;
|
||||
|
||||
let hash = murmurhash3_x64_128(data.as_bytes(), seed);
|
||||
}
|
||||
|
||||
Unfortunately, there is a bug in the ``HashState`` library implementation which prevents
|
||||
implementation of new ``Hasher`` implementations for use in for example ``HashMap``. Additionally,
|
||||
only the 32 bit hasher can be used there since ``HashMap`` uses a 64 bit hash internally.
|
||||
|
||||
Tests
|
||||
=====
|
||||
|
||||
.. code::
|
||||
|
||||
cargo test
|
||||
|
||||
Runs all tests with optimization level 3 in order to weed out potential problems with the optimizer.
|
||||
|
||||
.. _MurmurHash3: https://code.google.com/p/smhasher/wiki/MurmurHash3
|
|
@ -0,0 +1,61 @@
|
|||
use std::hash::Hasher;
|
||||
use std::collections::hash_state::HashState;
|
||||
|
||||
use mmh3_32::murmurhash3_x86_32;
|
||||
|
||||
pub struct Murmur3Hasher {
|
||||
seed: u32,
|
||||
bytes: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Murmur3HashState {
|
||||
seed: u32,
|
||||
}
|
||||
|
||||
impl Murmur3HashState {
|
||||
pub fn new() -> Murmur3HashState {
|
||||
return Murmur3HashState { seed: 0 };
|
||||
}
|
||||
|
||||
pub fn with_seed(seed: u32) -> Murmur3HashState {
|
||||
return Murmur3HashState { seed: seed };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Hasher for Murmur3Hasher {
|
||||
fn finish(&self) -> u64 {
|
||||
return murmurhash3_x86_32(&self.bytes, self.seed) as u64;
|
||||
}
|
||||
|
||||
fn write(&mut self, bytes: &[u8]) {
|
||||
self.bytes.push_all(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
impl HashState for Murmur3HashState {
|
||||
type Hasher = Murmur3Hasher;
|
||||
|
||||
fn hasher(&self) -> Murmur3Hasher {
|
||||
return Murmur3Hasher { seed: self.seed, bytes: vec![] };
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::Murmur3HashState;
|
||||
use std::collections::hash_map::HashMap;
|
||||
|
||||
#[test]
|
||||
fn use_in_hashmap() {
|
||||
let mut hashmap = HashMap::with_hash_state(Murmur3HashState::new());
|
||||
hashmap.insert("one", 1);
|
||||
hashmap.insert("two", 2);
|
||||
|
||||
assert!(hashmap.len() == 2);
|
||||
|
||||
assert!(*hashmap.get("one").unwrap() == 1);
|
||||
assert!(*hashmap.get("two").unwrap() == 2);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#![cfg_attr(feature = "nightly", feature(hashmap_hasher))]
|
||||
#![cfg_attr(feature = "nightly", feature(test))]
|
||||
#![cfg_attr(feature = "nightly", feature(vec_push_all))]
|
||||
|
||||
mod mmh3_128;
|
||||
mod mmh3_32;
|
||||
|
||||
#[cfg(feature="nightly")]
|
||||
mod hasher;
|
||||
|
||||
pub use mmh3_128::murmurhash3_x64_128;
|
||||
pub use mmh3_32::murmurhash3_x86_32;
|
||||
|
||||
#[cfg(feature="nightly")]
|
||||
pub use hasher::Murmur3HashState;
|
|
@ -0,0 +1,181 @@
|
|||
use std::mem;
|
||||
|
||||
fn fmix64(mut k: u64) -> u64 {
|
||||
k ^= k >> 33;
|
||||
k = k.wrapping_mul(0xff51afd7ed558ccdu64);
|
||||
k ^= k >> 33;
|
||||
k = k.wrapping_mul(0xc4ceb9fe1a85ec53u64);
|
||||
k ^= k >> 33;
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
fn get_128_block(bytes: &[u8], index: usize) -> (u64, u64) {
|
||||
let b64: &[u64] = unsafe { mem::transmute(bytes) };
|
||||
|
||||
return (b64[index], b64[index + 1]);
|
||||
}
|
||||
|
||||
pub fn murmurhash3_x64_128(bytes: &[u8], seed: u64) -> (u64, u64) {
|
||||
let c1 = 0x87c37b91114253d5u64;
|
||||
let c2 = 0x4cf5ad432745937fu64;
|
||||
let read_size = 16;
|
||||
let len = bytes.len() as u64;
|
||||
let block_count = len / read_size;
|
||||
|
||||
let (mut h1, mut h2) = (seed, seed);
|
||||
|
||||
|
||||
for i in 0..block_count as usize {
|
||||
let (mut k1, mut k2) = get_128_block(bytes, i * 2);
|
||||
|
||||
k1 = k1.wrapping_mul(c1);
|
||||
k1 = k1.rotate_left(31);
|
||||
k1 = k1.wrapping_mul(c2);
|
||||
h1 ^= k1;
|
||||
|
||||
h1 = h1.rotate_left(27);
|
||||
h1 = h1.wrapping_add(h2);
|
||||
h1 = h1.wrapping_mul(5);
|
||||
h1 = h1.wrapping_add(0x52dce729);
|
||||
|
||||
k2 = k2.wrapping_mul(c2);
|
||||
k2 = k2.rotate_left(33);
|
||||
k2 = k2.wrapping_mul(c1);
|
||||
h2 ^= k2;
|
||||
|
||||
h2 = h2.rotate_left(31);
|
||||
h2 = h2.wrapping_add(h1);
|
||||
h2 = h2.wrapping_mul(5);
|
||||
h2 = h2.wrapping_add(0x38495ab5);
|
||||
}
|
||||
|
||||
|
||||
let (mut k1, mut k2) = (0u64, 0u64);
|
||||
|
||||
if len & 15 == 15 { k2 ^= (bytes[(block_count * read_size) as usize + 14] as u64) << 48; }
|
||||
if len & 15 >= 14 { k2 ^= (bytes[(block_count * read_size) as usize + 13] as u64) << 40; }
|
||||
if len & 15 >= 13 { k2 ^= (bytes[(block_count * read_size) as usize + 12] as u64) << 32; }
|
||||
if len & 15 >= 12 { k2 ^= (bytes[(block_count * read_size) as usize + 11] as u64) << 24; }
|
||||
if len & 15 >= 11 { k2 ^= (bytes[(block_count * read_size) as usize + 10] as u64) << 16; }
|
||||
if len & 15 >= 10 { k2 ^= (bytes[(block_count * read_size) as usize + 9] as u64) << 8; }
|
||||
if len & 15 >= 9 { k2 ^= bytes[(block_count * read_size) as usize + 8] as u64;
|
||||
k2 = k2.wrapping_mul(c2);
|
||||
k2 = k2.rotate_left(33);
|
||||
k2 = k2.wrapping_mul(c1);
|
||||
h2 ^= k2;
|
||||
}
|
||||
|
||||
if len & 15 >= 8 { k1 ^= (bytes[(block_count * read_size) as usize + 7] as u64) << 56; }
|
||||
if len & 15 >= 7 { k1 ^= (bytes[(block_count * read_size) as usize + 6] as u64) << 48; }
|
||||
if len & 15 >= 6 { k1 ^= (bytes[(block_count * read_size) as usize + 5] as u64) << 40; }
|
||||
if len & 15 >= 5 { k1 ^= (bytes[(block_count * read_size) as usize + 4] as u64) << 32; }
|
||||
if len & 15 >= 4 { k1 ^= (bytes[(block_count * read_size) as usize + 3] as u64) << 24; }
|
||||
if len & 15 >= 3 { k1 ^= (bytes[(block_count * read_size) as usize + 2] as u64) << 16; }
|
||||
if len & 15 >= 2 { k1 ^= (bytes[(block_count * read_size) as usize + 1] as u64) << 8; }
|
||||
if len & 15 >= 1 { k1 ^= bytes[(block_count * read_size) as usize + 0] as u64;
|
||||
k1 = k1.wrapping_mul(c1);
|
||||
k1 = k1.rotate_left(31);
|
||||
k1 = k1.wrapping_mul(c2);
|
||||
h1 ^= k1;
|
||||
}
|
||||
|
||||
h1 ^= bytes.len() as u64;
|
||||
h2 ^= bytes.len() as u64;
|
||||
|
||||
h1 = h1.wrapping_add(h2);
|
||||
h2 = h2.wrapping_add(h1);
|
||||
|
||||
h1 = fmix64(h1);
|
||||
h2 = fmix64(h2);
|
||||
|
||||
h1 = h1.wrapping_add(h2);
|
||||
h2 = h2.wrapping_add(h1);
|
||||
|
||||
return (h1, h2);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::murmurhash3_x64_128;
|
||||
|
||||
#[test]
|
||||
fn test_empty_string() {
|
||||
assert!(murmurhash3_x64_128("".as_bytes(), 0) == (0, 0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tail_lengths() {
|
||||
assert!(murmurhash3_x64_128("1".as_bytes(), 0)
|
||||
== (8213365047359667313, 10676604921780958775));
|
||||
assert!(murmurhash3_x64_128("12".as_bytes(), 0)
|
||||
== (5355690773644049813, 9855895140584599837));
|
||||
assert!(murmurhash3_x64_128("123".as_bytes(), 0)
|
||||
== (10978418110857903978, 4791445053355511657));
|
||||
assert!(murmurhash3_x64_128("1234".as_bytes(), 0)
|
||||
== (619023178690193332, 3755592904005385637));
|
||||
assert!(murmurhash3_x64_128("12345".as_bytes(), 0)
|
||||
== (2375712675693977547, 17382870096830835188));
|
||||
assert!(murmurhash3_x64_128("123456".as_bytes(), 0)
|
||||
== (16435832985690558678, 5882968373513761278));
|
||||
assert!(murmurhash3_x64_128("1234567".as_bytes(), 0)
|
||||
== (3232113351312417698, 4025181827808483669));
|
||||
assert!(murmurhash3_x64_128("12345678".as_bytes(), 0)
|
||||
== (4272337174398058908, 10464973996478965079));
|
||||
assert!(murmurhash3_x64_128("123456789".as_bytes(), 0)
|
||||
== (4360720697772133540, 11094893415607738629));
|
||||
assert!(murmurhash3_x64_128("123456789a".as_bytes(), 0)
|
||||
== (12594836289594257748, 2662019112679848245));
|
||||
assert!(murmurhash3_x64_128("123456789ab".as_bytes(), 0)
|
||||
== (6978636991469537545, 12243090730442643750));
|
||||
assert!(murmurhash3_x64_128("123456789abc".as_bytes(), 0)
|
||||
== (211890993682310078, 16480638721813329343));
|
||||
assert!(murmurhash3_x64_128("123456789abcd".as_bytes(), 0)
|
||||
== (12459781455342427559, 3193214493011213179));
|
||||
assert!(murmurhash3_x64_128("123456789abcde".as_bytes(), 0)
|
||||
== (12538342858731408721, 9820739847336455216));
|
||||
assert!(murmurhash3_x64_128("123456789abcdef".as_bytes(), 0)
|
||||
== (9165946068217512774, 2451472574052603025));
|
||||
assert!(murmurhash3_x64_128("123456789abcdef1".as_bytes(), 0)
|
||||
== (9259082041050667785, 12459473952842597282));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_large_data() {
|
||||
assert!(murmurhash3_x64_128("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam at consequat massa. Cras eleifend pellentesque ex, at dignissim libero maximus ut. Sed eget nulla felis".as_bytes(), 0)
|
||||
== (9455322759164802692, 17863277201603478371));
|
||||
}
|
||||
|
||||
#[cfg(feature="nightly")]
|
||||
mod bench {
|
||||
extern crate rand;
|
||||
extern crate test;
|
||||
|
||||
use std::iter::FromIterator;
|
||||
use self::rand::Rng;
|
||||
use self::test::{Bencher, black_box};
|
||||
|
||||
use super::super::murmurhash3_x64_128;
|
||||
|
||||
fn run_bench(b: &mut Bencher, size: u64) {
|
||||
let mut data: Vec<u8> = FromIterator::from_iter((0..size).map(|_| 0u8));
|
||||
rand::thread_rng().fill_bytes(&mut data);
|
||||
|
||||
b.bytes = size;
|
||||
b.iter(|| {
|
||||
black_box(murmurhash3_x64_128(&data, 0));
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_random_256k(b: &mut Bencher) {
|
||||
run_bench(b, 256 * 1024);
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_random_16b(b: &mut Bencher) {
|
||||
run_bench(b, 16);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
use std::mem;
|
||||
|
||||
fn fmix32(mut h: u32) -> u32 {
|
||||
h ^= h >> 16;
|
||||
h = h.wrapping_mul(0x85ebca6b);
|
||||
h ^= h >> 13;
|
||||
h = h.wrapping_mul(0xc2b2ae35);
|
||||
h ^= h >> 16;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
fn get_32_block(bytes: &[u8], index: usize) -> u32 {
|
||||
let b32: &[u32] = unsafe { mem::transmute(bytes) };
|
||||
|
||||
return b32[index];
|
||||
}
|
||||
|
||||
pub fn murmurhash3_x86_32(bytes: &[u8], seed: u32) -> u32 {
|
||||
let c1 = 0xcc9e2d51u32;
|
||||
let c2 = 0x1b873593u32;
|
||||
let read_size = 4;
|
||||
let len = bytes.len() as u32;
|
||||
let block_count = len / read_size;
|
||||
|
||||
let mut h1 = seed;
|
||||
|
||||
for i in 0..block_count as usize {
|
||||
let mut k1 = get_32_block(bytes, i);
|
||||
|
||||
k1 = k1.wrapping_mul(c1);
|
||||
k1 = k1.rotate_left(15);
|
||||
k1 = k1.wrapping_mul(c2);
|
||||
|
||||
h1 ^= k1;
|
||||
h1 = h1.rotate_left(13);
|
||||
h1 = h1.wrapping_mul(5);
|
||||
h1 = h1.wrapping_add(0xe6546b64)
|
||||
}
|
||||
let mut k1 = 0u32;
|
||||
|
||||
if len & 3 == 3 { k1 ^= (bytes[(block_count * read_size) as usize + 2] as u32) << 16; }
|
||||
if len & 3 >= 2 { k1 ^= (bytes[(block_count * read_size) as usize + 1] as u32) << 8; }
|
||||
if len & 3 >= 1 { k1 ^= bytes[(block_count * read_size) as usize + 0] as u32;
|
||||
k1 = k1.wrapping_mul(c1);
|
||||
k1 = k1.rotate_left(15);
|
||||
k1 = k1.wrapping_mul(c2);
|
||||
h1 ^= k1;
|
||||
}
|
||||
|
||||
h1 ^= bytes.len() as u32;
|
||||
h1 = fmix32(h1);
|
||||
|
||||
return h1;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::murmurhash3_x86_32;
|
||||
|
||||
#[test]
|
||||
fn test_empty_string() {
|
||||
assert!(murmurhash3_x86_32("".as_bytes(), 0) == 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tail_lengths() {
|
||||
assert!(murmurhash3_x86_32("1".as_bytes(), 0)
|
||||
== 2484513939);
|
||||
assert!(murmurhash3_x86_32("12".as_bytes(), 0)
|
||||
== 4191350549);
|
||||
assert!(murmurhash3_x86_32("123".as_bytes(), 0)
|
||||
== 2662625771);
|
||||
assert!(murmurhash3_x86_32("1234".as_bytes(), 0)
|
||||
== 1914461635);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_large_data() {
|
||||
assert!(murmurhash3_x86_32("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam at consequat massa. Cras eleifend pellentesque ex, at dignissim libero maximus ut. Sed eget nulla felis".as_bytes(), 0)
|
||||
== 1004899618);
|
||||
}
|
||||
|
||||
#[cfg(feature="nightly")]
|
||||
mod bench {
|
||||
extern crate rand;
|
||||
extern crate test;
|
||||
|
||||
use std::iter::FromIterator;
|
||||
use self::rand::Rng;
|
||||
use self::test::{Bencher, black_box};
|
||||
|
||||
use super::super::murmurhash3_x86_32;
|
||||
|
||||
fn run_bench(b: &mut Bencher, size: u64) {
|
||||
let mut data: Vec<u8> = FromIterator::from_iter((0..size).map(|_| 0u8));
|
||||
rand::thread_rng().fill_bytes(&mut data);
|
||||
|
||||
b.bytes = size;
|
||||
b.iter(|| {
|
||||
black_box(murmurhash3_x86_32(&data, 0));
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_random_256k(b: &mut Bencher) {
|
||||
run_bench(b, 256 * 1024);
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_random_16b(b: &mut Bencher) {
|
||||
run_bench(b, 16);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
{"files":{"Cargo.toml":"3b884e551bfc961c49fd6b66b3fa4620f49190450991e390c94ab67994e314e8","README.md":"684439af17ec43b5a186e1c23c625681e06877a325e2ad13540bca47951de936","license.txt":"c76f740d1521b9bed9ca7a04ad526c310493c62621b1341d623b431736533b30","src/lib.rs":"d2e01c467812921509932e8f449bde77bcc18dc3954092ad3558535ef2e4139b","test_data/test_bf":"afa0b9e6b9244522302aa8d153e92e25d7fd16388f34c06497487fc0332a4d34","test_data/test_mlbf":"2c6a5f13ad459f1bcf88d91c2eaab94eda84a60fc123b9914203dee725d70ba0","test_data/test_short_mlbf":"55f0d1361acb4f4ec25dba6bfa92a777d49dcc2e71f623a9ec2a70c6ff5f61eb"},"package":"f3fe4900d38dab1ad21a515e44687dd0711e6b0ec5b214a3b1aa8857343bcf3a"}
|
|
@ -0,0 +1,35 @@
|
|||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g., crates.io) dependencies
|
||||
#
|
||||
# If you believe there's an error in this file please file an
|
||||
# issue against the rust-lang/cargo repository. If you're
|
||||
# editing this file be aware that the upstream Cargo.toml
|
||||
# will likely look very different (and much more reasonable)
|
||||
|
||||
[package]
|
||||
name = "rust_cascade"
|
||||
version = "0.3.4"
|
||||
authors = ["Mark Goodwin <mgoodwin@mozilla.com>"]
|
||||
description = "A simple mmh3 based bloom filter cascade implementation in Rust."
|
||||
license = "MPL-2.0"
|
||||
[dependencies.bit-vec]
|
||||
version = "0.5.1"
|
||||
|
||||
[dependencies.bit_reverse]
|
||||
version = "0.1.7"
|
||||
|
||||
[dependencies.byteorder]
|
||||
version = "1.3.1"
|
||||
|
||||
[dependencies.digest]
|
||||
version = "0.8.0"
|
||||
|
||||
[dependencies.murmurhash3]
|
||||
version = "0.0.5"
|
||||
|
||||
[dependencies.rand]
|
||||
version = "0.*"
|
|
@ -0,0 +1,5 @@
|
|||
# rust-cascade
|
||||
A filter cascade implementation in rust. This uses the 32 bit version of the MurmurHash3 algorithm and is specifically implemented for compatibility with a specific
|
||||
python filter cascade implementation (https://github.com/mozilla/crlite/blob/master/create_filter_cascade/FilterCascade.py).
|
||||
|
||||
See tests in src/lib.rs to get an idea of usage.
|
|
@ -0,0 +1,373 @@
|
|||
Mozilla Public License Version 2.0
|
||||
==================================
|
||||
|
||||
1. Definitions
|
||||
--------------
|
||||
|
||||
1.1. "Contributor"
|
||||
means each individual or legal entity that creates, contributes to
|
||||
the creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
means the combination of the Contributions of others (if any) used
|
||||
by a Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
means Source Code Form to which the initial Contributor has attached
|
||||
the notice in Exhibit A, the Executable Form of such Source Code
|
||||
Form, and Modifications of such Source Code Form, in each case
|
||||
including portions thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
(a) that the initial Contributor has attached the notice described
|
||||
in Exhibit B to the Covered Software; or
|
||||
|
||||
(b) that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the
|
||||
terms of a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
means a work that combines Covered Software with other material, in
|
||||
a separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
means having the right to grant, to the maximum extent possible,
|
||||
whether at the time of the initial grant or subsequently, any and
|
||||
all of the rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
means any of the following:
|
||||
|
||||
(a) any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered
|
||||
Software; or
|
||||
|
||||
(b) any new file in Source Code Form that contains any Covered
|
||||
Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the
|
||||
License, by the making, using, selling, offering for sale, having
|
||||
made, import, or transfer of either its Contributions or its
|
||||
Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
means either the GNU General Public License, Version 2.0, the GNU
|
||||
Lesser General Public License, Version 2.1, the GNU Affero General
|
||||
Public License, Version 3.0, or any later versions of those
|
||||
licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that
|
||||
controls, is controlled by, or is under common control with You. For
|
||||
purposes of this definition, "control" means (a) the power, direct
|
||||
or indirect, to cause the direction or management of such entity,
|
||||
whether by contract or otherwise, or (b) ownership of more than
|
||||
fifty percent (50%) of the outstanding shares or beneficial
|
||||
ownership of such entity.
|
||||
|
||||
2. License Grants and Conditions
|
||||
--------------------------------
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
(a) under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
||||
for sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
(a) for any code that a Contributor has removed from Covered Software;
|
||||
or
|
||||
|
||||
(b) for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
(c) under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights
|
||||
to grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
||||
in Section 2.1.
|
||||
|
||||
3. Responsibilities
|
||||
-------------------
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
(a) such Covered Software must also be made available in Source Code
|
||||
Form, as described in Section 3.1, and You must inform recipients of
|
||||
the Executable Form how they can obtain a copy of such Source Code
|
||||
Form by reasonable means in a timely manner, at a charge no more
|
||||
than the cost of distribution to the recipient; and
|
||||
|
||||
(b) You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter
|
||||
the recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty,
|
||||
or limitations of liability) contained within the Source Code Form of
|
||||
the Covered Software, except that You may alter any license notices to
|
||||
the extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
---------------------------------------------------
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this
|
||||
License with respect to some or all of the Covered Software due to
|
||||
statute, judicial order, or regulation then You must: (a) comply with
|
||||
the terms of this License to the maximum extent possible; and (b)
|
||||
describe the limitations and the code they affect. Such description must
|
||||
be placed in a text file included with all distributions of the Covered
|
||||
Software under this License. Except to the extent prohibited by statute
|
||||
or regulation, such description must be sufficiently detailed for a
|
||||
recipient of ordinary skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
--------------
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically
|
||||
if You fail to comply with any of its terms. However, if You become
|
||||
compliant, then the rights granted under this License from a particular
|
||||
Contributor are reinstated (a) provisionally, unless and until such
|
||||
Contributor explicitly and finally terminates Your grants, and (b) on an
|
||||
ongoing basis, if such Contributor fails to notify You of the
|
||||
non-compliance by some reasonable means prior to 60 days after You have
|
||||
come back into compliance. Moreover, Your grants from a particular
|
||||
Contributor are reinstated on an ongoing basis if such Contributor
|
||||
notifies You of the non-compliance by some reasonable means, this is the
|
||||
first time You have received notice of non-compliance with this License
|
||||
from such Contributor, and You become compliant prior to 30 days after
|
||||
Your receipt of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
||||
end user license agreements (excluding distributors and resellers) which
|
||||
have been validly granted by You or Your distributors under this License
|
||||
prior to termination shall survive termination.
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 6. Disclaimer of Warranty *
|
||||
* ------------------------- *
|
||||
* *
|
||||
* Covered Software is provided under this License on an "as is" *
|
||||
* basis, without warranty of any kind, either expressed, implied, or *
|
||||
* statutory, including, without limitation, warranties that the *
|
||||
* Covered Software is free of defects, merchantable, fit for a *
|
||||
* particular purpose or non-infringing. The entire risk as to the *
|
||||
* quality and performance of the Covered Software is with You. *
|
||||
* Should any Covered Software prove defective in any respect, You *
|
||||
* (not any Contributor) assume the cost of any necessary servicing, *
|
||||
* repair, or correction. This disclaimer of warranty constitutes an *
|
||||
* essential part of this License. No use of any Covered Software is *
|
||||
* authorized under this License except under this disclaimer. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 7. Limitation of Liability *
|
||||
* -------------------------- *
|
||||
* *
|
||||
* Under no circumstances and under no legal theory, whether tort *
|
||||
* (including negligence), contract, or otherwise, shall any *
|
||||
* Contributor, or anyone who distributes Covered Software as *
|
||||
* permitted above, be liable to You for any direct, indirect, *
|
||||
* special, incidental, or consequential damages of any character *
|
||||
* including, without limitation, damages for lost profits, loss of *
|
||||
* goodwill, work stoppage, computer failure or malfunction, or any *
|
||||
* and all other commercial damages or losses, even if such party *
|
||||
* shall have been informed of the possibility of such damages. This *
|
||||
* limitation of liability shall not apply to liability for death or *
|
||||
* personal injury resulting from such party's negligence to the *
|
||||
* extent applicable law prohibits such limitation. Some *
|
||||
* jurisdictions do not allow the exclusion or limitation of *
|
||||
* incidental or consequential damages, so this exclusion and *
|
||||
* limitation may not apply to You. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
8. Litigation
|
||||
-------------
|
||||
|
||||
Any litigation relating to this License may be brought only in the
|
||||
courts of a jurisdiction where the defendant maintains its principal
|
||||
place of business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions.
|
||||
Nothing in this Section shall prevent a party's ability to bring
|
||||
cross-claims or counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
----------------
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides
|
||||
that the language of a contract shall be construed against the drafter
|
||||
shall not be used to construe this License against a Contributor.
|
||||
|
||||
10. Versions of the License
|
||||
---------------------------
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses
|
||||
|
||||
If You choose to distribute Source Code Form that is Incompatible With
|
||||
Secondary Licenses under the terms of this version of the License, the
|
||||
notice described in Exhibit B of this License must be attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
-------------------------------------------
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular
|
||||
file, then You may include the notice in a location (such as a LICENSE
|
||||
file in a relevant directory) where a recipient would be likely to look
|
||||
for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||
---------------------------------------------------------
|
||||
|
||||
This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
defined by the Mozilla Public License, v. 2.0.
|
|
@ -0,0 +1,331 @@
|
|||
extern crate bit_reverse;
|
||||
extern crate bit_vec;
|
||||
extern crate byteorder;
|
||||
extern crate digest;
|
||||
extern crate murmurhash3;
|
||||
extern crate rand;
|
||||
|
||||
use bit_reverse::ParallelReverse;
|
||||
use bit_vec::BitVec;
|
||||
use byteorder::ReadBytesExt;
|
||||
use murmurhash3::murmurhash3_x86_32;
|
||||
|
||||
use std::io::{Error, ErrorKind, Read};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Bloom {
|
||||
level: u32,
|
||||
n_hash_funcs: u32,
|
||||
size: usize,
|
||||
bitvec: BitVec,
|
||||
}
|
||||
|
||||
pub fn calculate_n_hash_funcs(error_rate: f32) -> u32 {
|
||||
((1.0 / error_rate).ln() / (2.0_f32).ln()).ceil() as u32
|
||||
}
|
||||
|
||||
pub fn calculate_size(elements: usize, error_rate: f32) -> usize {
|
||||
let n_hash_funcs = calculate_n_hash_funcs(error_rate);
|
||||
let hashes = n_hash_funcs as f32;
|
||||
(1.0_f32
|
||||
- (hashes * (elements as f32 + 0.5) / (1.0_f32 - error_rate.powf(1.0 / hashes)).ln()))
|
||||
.ceil() as usize
|
||||
}
|
||||
|
||||
impl Bloom {
|
||||
pub fn new(size: usize, n_hash_funcs: u32, level: u32) -> Bloom {
|
||||
let bitvec: BitVec = BitVec::from_elem(size, false);
|
||||
|
||||
Bloom {
|
||||
level: level,
|
||||
n_hash_funcs: n_hash_funcs,
|
||||
size: size,
|
||||
bitvec: bitvec,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_bytes(cursor: &mut &[u8]) -> Result<Bloom, Error> {
|
||||
// Load the layer metadata. bloomer.py writes size, nHashFuncs and level as little-endian
|
||||
// unsigned ints.
|
||||
let size = cursor.read_u32::<byteorder::LittleEndian>()? as usize;
|
||||
let n_hash_funcs = cursor.read_u32::<byteorder::LittleEndian>()?;
|
||||
let level = cursor.read_u32::<byteorder::LittleEndian>()?;
|
||||
|
||||
let shifted_size = size.wrapping_shr(3);
|
||||
let byte_count = if size % 8 != 0 {
|
||||
shifted_size + 1
|
||||
} else {
|
||||
shifted_size
|
||||
};
|
||||
|
||||
let mut bitvec_buf = vec![0u8; byte_count];
|
||||
cursor.read_exact(&mut bitvec_buf)?;
|
||||
|
||||
// swap the bits, since the bit order of our python libraries differs
|
||||
let v: Vec<u8> = bitvec_buf.into_iter().map(|x| x.swap_bits()).collect();
|
||||
|
||||
Ok(Bloom {
|
||||
level,
|
||||
n_hash_funcs,
|
||||
size,
|
||||
bitvec: BitVec::from_bytes(&v),
|
||||
})
|
||||
}
|
||||
|
||||
fn hash(&self, n_fn: u32, key: &[u8]) -> usize {
|
||||
let hash_seed = (n_fn << 16) + self.level;
|
||||
let h = murmurhash3_x86_32(key, hash_seed) as usize % self.size;
|
||||
h
|
||||
}
|
||||
|
||||
pub fn put(&mut self, item: &[u8]) {
|
||||
for i in 0..self.n_hash_funcs {
|
||||
let index = self.hash(i, item);
|
||||
self.bitvec.set(index, true);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has(&self, item: &[u8]) -> bool {
|
||||
for i in 0..self.n_hash_funcs {
|
||||
match self.bitvec.get(self.hash(i, item)) {
|
||||
Some(false) => return false,
|
||||
Some(true) => (),
|
||||
None => panic!(
|
||||
"access outside the bloom filter bit vector (this is almost certainly a bug)"
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.bitvec.clear()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Cascade {
|
||||
filter: Bloom,
|
||||
child_layer: Option<Box<Cascade>>,
|
||||
}
|
||||
|
||||
impl Cascade {
|
||||
pub fn new(size: usize, n_hash_funcs: u32) -> Cascade {
|
||||
return Cascade::new_layer(size, n_hash_funcs, 1);
|
||||
}
|
||||
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Option<Box<Cascade>>, Error> {
|
||||
if bytes.len() == 0 {
|
||||
return Ok(None);
|
||||
}
|
||||
let mut cursor = bytes;
|
||||
let version = cursor.read_u16::<byteorder::LittleEndian>()?;
|
||||
if version != 1 {
|
||||
return Err(Error::new(ErrorKind::InvalidInput, "Invalid version"));
|
||||
}
|
||||
Ok(Some(Box::new(Cascade {
|
||||
filter: Bloom::from_bytes(&mut cursor)?,
|
||||
child_layer: Cascade::from_bytes(cursor)?,
|
||||
})))
|
||||
}
|
||||
|
||||
fn new_layer(size: usize, n_hash_funcs: u32, layer: u32) -> Cascade {
|
||||
Cascade {
|
||||
filter: Bloom::new(size, n_hash_funcs, layer),
|
||||
child_layer: Option::None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn initialize(&mut self, entries: Vec<Vec<u8>>, exclusions: Vec<Vec<u8>>) {
|
||||
let mut false_positives = Vec::new();
|
||||
for entry in &entries {
|
||||
self.filter.put(entry);
|
||||
}
|
||||
|
||||
for entry in exclusions {
|
||||
if self.filter.has(&entry) {
|
||||
false_positives.push(entry);
|
||||
}
|
||||
}
|
||||
|
||||
if false_positives.len() > 0 {
|
||||
let n_hash_funcs = calculate_n_hash_funcs(0.5);
|
||||
let size = calculate_size(false_positives.len(), 0.5);
|
||||
let mut child = Box::new(Cascade::new_layer(
|
||||
size,
|
||||
n_hash_funcs,
|
||||
self.filter.level + 1,
|
||||
));
|
||||
child.initialize(false_positives, entries);
|
||||
self.child_layer = Some(child);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has(&self, entry: &[u8]) -> bool {
|
||||
if self.filter.has(&entry) {
|
||||
match self.child_layer {
|
||||
Some(ref child) => {
|
||||
let child_value = !child.has(entry);
|
||||
return child_value;
|
||||
}
|
||||
None => {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn check(&self, entries: Vec<Vec<u8>>, exclusions: Vec<Vec<u8>>) -> bool {
|
||||
for entry in entries {
|
||||
if !self.has(&entry) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for entry in exclusions {
|
||||
if self.has(&entry) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use calculate_n_hash_funcs;
|
||||
use calculate_size;
|
||||
use rand::Rng;
|
||||
use Bloom;
|
||||
use Cascade;
|
||||
|
||||
#[test]
|
||||
fn bloom_test_bloom_size() {
|
||||
let error_rate = 0.01;
|
||||
let elements = 1024;
|
||||
let n_hash_funcs = calculate_n_hash_funcs(error_rate);
|
||||
let size = calculate_size(elements, error_rate);
|
||||
|
||||
let bloom = Bloom::new(size, n_hash_funcs, 0);
|
||||
assert!(bloom.bitvec.len() == 9829);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bloom_test_put() {
|
||||
let error_rate = 0.01;
|
||||
let elements = 1024;
|
||||
let n_hash_funcs = calculate_n_hash_funcs(error_rate);
|
||||
let size = calculate_size(elements, error_rate);
|
||||
|
||||
let mut bloom = Bloom::new(size, n_hash_funcs, 0);
|
||||
let key: &[u8] = b"foo";
|
||||
|
||||
bloom.put(key);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bloom_test_has() {
|
||||
let error_rate = 0.01;
|
||||
let elements = 1024;
|
||||
let n_hash_funcs = calculate_n_hash_funcs(error_rate);
|
||||
let size = calculate_size(elements, error_rate);
|
||||
|
||||
let mut bloom = Bloom::new(size, n_hash_funcs, 0);
|
||||
let key: &[u8] = b"foo";
|
||||
|
||||
bloom.put(key);
|
||||
assert!(bloom.has(key) == true);
|
||||
assert!(bloom.has(b"bar") == false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bloom_test_from_bytes() {
|
||||
let src: Vec<u8> = vec![
|
||||
0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x41, 0x00,
|
||||
];
|
||||
|
||||
match Bloom::from_bytes(&mut &src[..]) {
|
||||
Ok(mut bloom) => {
|
||||
assert!(bloom.has(b"this") == true);
|
||||
assert!(bloom.has(b"that") == true);
|
||||
assert!(bloom.has(b"other") == false);
|
||||
|
||||
bloom.put(b"other");
|
||||
assert!(bloom.has(b"other") == true);
|
||||
}
|
||||
Err(_) => {
|
||||
panic!("Parsing failed");
|
||||
}
|
||||
};
|
||||
|
||||
let short: Vec<u8> = vec![
|
||||
0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x41,
|
||||
];
|
||||
match Bloom::from_bytes(&mut &short[..]) {
|
||||
Ok(_) => {
|
||||
panic!("Parsing should fail; data is truncated");
|
||||
}
|
||||
Err(_) => {}
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bloom_test_from_file() {
|
||||
let v = include_bytes!("../test_data/test_bf");
|
||||
let bloom = Bloom::from_bytes(&mut &v[..]).expect("parsing Bloom should succeed");
|
||||
assert!(bloom.has(b"this") == true);
|
||||
assert!(bloom.has(b"that") == true);
|
||||
assert!(bloom.has(b"yet another test") == false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cascade_test() {
|
||||
// thread_rng is often the most convenient source of randomness:
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
// create some entries and exclusions
|
||||
let mut foo: Vec<Vec<u8>> = Vec::new();
|
||||
let mut bar: Vec<Vec<u8>> = Vec::new();
|
||||
|
||||
for i in 0..500 {
|
||||
let s = format!("{}", i);
|
||||
let bytes = s.into_bytes();
|
||||
foo.push(bytes);
|
||||
}
|
||||
|
||||
for _ in 0..100 {
|
||||
let idx = rng.gen_range(0, foo.len());
|
||||
bar.push(foo.swap_remove(idx));
|
||||
}
|
||||
|
||||
let error_rate = 0.5;
|
||||
let elements = 500;
|
||||
let n_hash_funcs = calculate_n_hash_funcs(error_rate);
|
||||
let size = calculate_size(elements, error_rate);
|
||||
|
||||
let mut cascade = Cascade::new(size, n_hash_funcs);
|
||||
cascade.initialize(foo.clone(), bar.clone());
|
||||
|
||||
assert!(cascade.check(foo.clone(), bar.clone()) == true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cascade_from_file_bytes_test() {
|
||||
let v = include_bytes!("../test_data/test_mlbf");
|
||||
let cascade = Cascade::from_bytes(v)
|
||||
.expect("parsing Cascade should succeed")
|
||||
.expect("Cascade should be Some");
|
||||
assert!(cascade.has(b"test") == true);
|
||||
assert!(cascade.has(b"another test") == true);
|
||||
assert!(cascade.has(b"yet another test") == true);
|
||||
assert!(cascade.has(b"blah") == false);
|
||||
assert!(cascade.has(b"blah blah") == false);
|
||||
assert!(cascade.has(b"blah blah blah") == false);
|
||||
|
||||
let v = include_bytes!("../test_data/test_short_mlbf");
|
||||
Cascade::from_bytes(v).expect_err("parsing truncated Cascade should fail");
|
||||
}
|
||||
}
|
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
|
@ -288,7 +288,12 @@ const BackgroundPageThumbs = {
|
|||
|
||||
// an event that is sent if the remote process crashes - no need to remove
|
||||
// it as we want it to be there as long as the browser itself lives.
|
||||
browser.addEventListener("oop-browser-crashed", () => {
|
||||
browser.addEventListener("oop-browser-crashed", event => {
|
||||
if (!event.isTopFrame) {
|
||||
// It was a subframe that crashed. We'll ignore this.
|
||||
return;
|
||||
}
|
||||
|
||||
Cu.reportError("BackgroundThumbnails remote process crashed - recovering");
|
||||
this._destroyBrowser();
|
||||
let curCapture = this._captureQueue.length ? this._captureQueue[0] : null;
|
||||
|
|
|
@ -24,8 +24,8 @@
|
|||
* Child and Parent variants, but only Child variants are currently implemented.
|
||||
* The parent and child variants live in separate JSMs, and have separate class
|
||||
* names, each of which have Child or Parent appended to their names, as
|
||||
* appropriate. For instance, the Browser actor has a child instance named
|
||||
* BrowserChild which lives in BrowserChild.jsm.
|
||||
* appropriate. For instance, the AudioPlayback actor has a child instance named
|
||||
* AudioPlaybackChild which lives in AudioPlaybackChild.jsm.
|
||||
*
|
||||
*
|
||||
* Actors are defined by calling ActorManagerParent.addActors, with an object
|
||||
|
@ -41,8 +41,8 @@
|
|||
* - "module": The URI from which the modules is loaded. This should be a
|
||||
* resource: URI, ideally beginning with "resource://gre/actors/" or
|
||||
* "resource:///actors/", with a filename matching the name of the actor for
|
||||
* the given side. So, the child side of the Browser actor should live at
|
||||
* "resource://gre/actors/BrowserChild.jsm".
|
||||
* the given side. So, the child side of the AudioPlayback actor should live at
|
||||
* "resource://gre/actors/AudioPlaybackChild.jsm".
|
||||
*
|
||||
* - "group": A group name which restricts the message managers to which this
|
||||
* actor may be attached. This should match the "messagemanagergroup"
|
||||
|
@ -101,6 +101,9 @@ const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|||
const {DefaultMap} = ExtensionUtils;
|
||||
|
||||
let ACTORS = {
|
||||
};
|
||||
|
||||
let LEGACY_ACTORS = {
|
||||
AudioPlayback: {
|
||||
child: {
|
||||
module: "resource://gre/actors/AudioPlaybackChild.jsm",
|
||||
|
@ -417,6 +420,12 @@ var ActorManagerParent = {
|
|||
singletons: new DefaultMap(() => new ActorSet(null, "Child")),
|
||||
|
||||
addActors(actors) {
|
||||
for (let [actorName, actor] of Object.entries(actors)) {
|
||||
ChromeUtils.registerWindowActor(actorName, actor);
|
||||
}
|
||||
},
|
||||
|
||||
addLegacyActors(actors) {
|
||||
for (let [actorName, actor] of Object.entries(actors)) {
|
||||
let {child} = actor;
|
||||
{
|
||||
|
@ -455,3 +464,4 @@ var ActorManagerParent = {
|
|||
};
|
||||
|
||||
ActorManagerParent.addActors(ACTORS);
|
||||
ActorManagerParent.addLegacyActors(LEGACY_ACTORS);
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче