Backed out changeset 3fa81f747c93 (bug 1538161) for causing rust build bustages CLOSED TREE

This commit is contained in:
Noemi Erli 2019-04-29 17:19:42 +03:00
parent 8814fd6055
commit de59160691
54 changed files with 222 additions and 15353 deletions

64
Cargo.lock generated
View File

@ -178,7 +178,7 @@ name = "base64"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.7 (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.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.7 (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.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -323,11 +323,6 @@ dependencies = [
"xpcom 0.1.0",
]
[[package]]
name = "bitvec"
version = "0.11.0"
source = "git+https://github.com/mozmark/bitvec?branch=20190426-bitvec-vendor-issues#fd9393e92a0d4223b3bda7318ca5fb893f7632e1"
[[package]]
name = "blake2-rfc"
version = "0.2.18"
@ -344,7 +339,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.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -391,7 +386,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "byteorder"
version = "1.3.1"
version = "1.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -399,7 +394,7 @@ name = "bytes"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -443,7 +438,6 @@ 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.2 (git+https://github.com/mozmark/rust-cascade?branch=20190426-bitvec-vendor-issues)",
"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)",
@ -847,7 +841,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.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -1149,7 +1143,7 @@ name = "fxhash"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -1321,7 +1315,7 @@ name = "h2"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.7 (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)",
@ -1338,7 +1332,7 @@ name = "hashbrown"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"scopeguard 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1417,7 +1411,7 @@ name = "image"
version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.7 (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)",
@ -1886,7 +1880,7 @@ name = "mp4parse"
version = "0.11.2"
dependencies = [
"bitreader 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.7 (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)",
@ -1900,7 +1894,7 @@ version = "0.1.0"
name = "mp4parse_capi"
version = "0.11.2"
dependencies = [
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.7 (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)",
@ -1920,11 +1914,6 @@ 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"
@ -2196,7 +2185,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.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.7 (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)",
@ -2450,18 +2439,6 @@ name = "rust-ini"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rust_cascade"
version = "0.3.2"
source = "git+https://github.com/mozmark/rust-cascade?branch=20190426-bitvec-vendor-issues#86c24aa1f2f9de1b4b5e1bb451255d530ac7c03f"
dependencies = [
"bitvec 0.11.0 (git+https://github.com/mozmark/bitvec?branch=20190426-bitvec-vendor-issues)",
"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"
@ -2742,7 +2719,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.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.7 (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)",
@ -3344,7 +3321,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.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.7 (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)",
@ -3382,7 +3359,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.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.7 (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)",
@ -3491,7 +3468,7 @@ name = "ws"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.7 (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)",
@ -3609,14 +3586,13 @@ dependencies = [
"checksum bit-vec 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4440d5cb623bb7390ae27fec0bb6c61111969860f8e3ae198bfa0663645e67cf"
"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 bitvec 0.11.0 (git+https://github.com/mozmark/bitvec?branch=20190426-bitvec-vendor-issues)" = "<none>"
"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400"
"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
"checksum block-padding 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc4358306e344bf9775d0197fd00d2603e5afb0771bb353538630f022068ea3"
"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.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb"
"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d"
"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"
@ -3751,7 +3727,6 @@ 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"
@ -3807,7 +3782,6 @@ 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.2 (git+https://github.com/mozmark/rust-cascade?branch=20190426-bitvec-vendor-issues)" = "<none>"
"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"

View File

@ -12,7 +12,6 @@ moz_task = { path = "../../../../xpcom/rust/moz_task" }
nserror = { path = "../../../../xpcom/rust/nserror" }
nsstring = { path = "../../../../xpcom/rust/nsstring" }
rkv = "^0.9"
rust_cascade = { git = "https://github.com/mozmark/rust-cascade", branch = "20190426-bitvec-vendor-issues" }
sha2 = "^0.8"
style = { path = "../../../../servo/components/style" }
thin-vec = { version = "0.1.0", features = ["gecko-ffi"] }

View File

@ -1 +0,0 @@
{"files":{".editorconfig":"ad2ddd2235a1ca26d8be9df333baae560b8f696f9475a8084d5169bc598feced",".gitmodules":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".travis.yml":"e3d5a6154d4ad058f85387f2bd0ff369185c74eab6c877222bffa26cb94cbb43","AUTHORS.txt":"2bdfa77827b6fd352f398752c30acbca48ada04284656b6d38fb97b85534d5bf","CHANGELOG.md":"7247fb1b50a9d1d278f01918d4143a5055eed27bbbb7d815e5dd866eea23d265","CODE_OF_CONDUCT.md":"bae3bf173a3748f4b62eb808133bb1597f811f0fa919e997149882125f91746d","CONTRIBUTING.md":"035ebfb837464470c7649e6b306c7f0b831c242cbbf25fb97a0b3f40ea4acde6","Cargo.toml":"c7ad5c8b5d8fa6da8aed9afc587f90ea50bd5143b9242d67196d9bfc7f06e775","Justfile":"f40ee5a5a5b3dbbebf90d6704909029b680bc5a3b3084e2792897995e833bcb2","LICENSE.txt":"411781fd38700f2357a14126d0ab048164ab881f1dcb335c1bb932e232c9a2f5","README.md":"06220e7785d27d8899aa5b27e3f8914225aa1d2a79a44142d8eb76cbe4c76820","doc/Bit Patterns.md":"cfd36f3ec70df5541c37f4c25a59211a3eccc3cc5d189efb4a61eb5d4f2357df","examples/readme.rs":"25de2cee995538d755149cbd1050e521ac92c852dd0d9da1f1c2c8cbc24704f7","examples/serdes.rs":"08df19dc1d83d75bf159f06c502469ccf8aa7ccaafca00cf6ad015def4dfcf94","examples/sieve.rs":"a827fcf1749987b4fd3182b9dcc5843a79062a9ed3f45ffc32a32fe6cc589b40","examples/tour.rs":"b489ab7706777360b1a2eb374326dc302fd7f861a94f19489c2fd89a9e2edd6e","src/bits.rs":"3cbf151e51ae0788ec25ba3da7b0b2602d2406bbd2d6c656f6ecfc1198646217","src/boxed.rs":"a1c7a82b0e99a8935ebdf9cfcd81c4bf8c3318b8f68a0098cd674fbea62a5190","src/cursor.rs":"12fb0c0397b95ca5ec781c597399dcbc8c613085e37a4c8b9aed52ec71429563","src/domain.rs":"ee48d5d9730103d5b4ec2d2033916511e2e3e3ea8e6d5b02b0865871ff654777","src/lib.rs":"e9ff103498255208e952aba0826736c07d31d626503f2264ec68359c7cc0367a","src/macros.rs":"9bbc09012519dcdd27fc8153b3d0b5c77c9d2501caa41ec3d82598929c1b493a","src/pointer.rs":"78edf17c31976e87a9244ce7d7315a89b99e3f7e295a7b0901d4ef9e1e4c31c7","src/prelude.rs":"355767c31fe1da51b28b6aeda4150b54e7966f1762b6d4cd5425ac2060d78419","src/serdes.rs":"f1c22be942230f119e2b622a88930058c2be69c3f4b48d25b17e61e655514083","src/slice.rs":"63bfe42e69251a439bbc60c0c3c95d4ca040f17cd5a68c27d238718a2639e864","src/vec.rs":"e04056e7529a4fe0cce76a139f928cf385f99b2869cf69dd86291ae4b490fea5"},"package":null}

View File

@ -1,21 +0,0 @@
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
indent_size = 2
indent_style = space
[*.rs]
indent_size = 4
indent_style = tab
[*.toml]
indent_size = 8
indent_style = tab
[*.yml]
indent_size = 2
indent_style = space

View File

View File

@ -1,40 +0,0 @@
language: rust
sudo: required
rust:
- stable
- beta
- nightly
matrix:
allow_failures:
- rust: nightly
# codecov
addons:
apt:
packages:
- libcurl4-openssl-dev
- libelf-dev
- libdw-dev
- cmake
- gcc
- binutils-dev
- libiberty-dev
# codecov
after_success: |
wget https://github.com/SimonKagstrom/kcov/archive/master.tar.gz &&
tar xzf master.tar.gz &&
cd kcov-master &&
mkdir build &&
cd build &&
cmake .. &&
make &&
make install DESTDIR=../../kcov-build &&
cd ../.. &&
rm -rf kcov-master &&
for file in target/debug/bitvec-*[^\.d]; do mkdir -p "target/cov/$(basename $file)"; ./kcov-build/usr/local/bin/kcov --exclude-pattern=/.cargo,/usr/lib --verify "target/cov/$(basename $file)" "$file"; done &&
bash <(curl -s https://codecov.io/bash) &&
echo "Uploaded code coverage"

View File

@ -1 +0,0 @@
myrrlyn <self@myrrlyn.dev>

View File

@ -1,260 +0,0 @@
# Changelog
All notable changes will be documented in this file.
## 0.11.0
This contains the last (planned) compiler version upgrade, to `1.33.0`, and the
last major feature add before `1.0`: Serde-powered de/serialization.
Deserialization is not possible without access to an allocator, so it is behind
a feature gate, `serdes`, which depends on the `alloc` feature.
`BitSlice`, `BitBox`, and `BitVec` all support serialization, and `BitBox` and
`BitVec` support deserialization
### Added
- `serdes` feature to serialize `BitSlice`, `BitBox`, and `BitVec`, and
deserialize `BitBox` and `BitVec`.
- `change_cursor<D>` method on `BitSlice`, `BitBox`, and `BitVec`, which enable
changing the element traversal order on a data set without modifying that
data. This is useful for working with slices that have their cursor type
erased, such as crossing serialization or foreign-language boundaries.
- Internal domain models for the memory regions governed by `BitPtr`. These
models provide improved logical support for manipulating bit sequences with as
little inefficiency as possible.
- `BitPtr::bare_parts` and `BitPtr::region_data` internal APIs for accessing
components of the pointer structure.
- Clippy is now part of the development routine.
### Changed
- The internal `Bits` trait uses a `const fn` stabilized in `1.33.0` in order to
compute type information, rather than requiring explicit statements in the
implementations.
## 0.10.1
Bugfix for [Issue #7](https://github.com/myrrlyn/bitvec/issues/7).
`BitSlice::count_ones` and `BitSlice::count_zeros` counted the total number of
bits present in a slice, not the number of bits set or unset, when operating
inside a single element.
The small case used `.map().count()`, but the large case correctly used
`.map().filter().count()`. The missing `.filter()` call, to remove unset or set
bits from the counting, was the cause of the bug.
Thanks to GitHub user [@geq1t](https://github.com/geq1t) for the report!
## 0.10.0
This version was a complete rewrite of the entire crate. The minimum compiler
version has been upgraded to `1.31.0`. The crate is written against the Rust
2018 edition of the language. It will be a `1.0` release after polishing.
### Added
- `BitPtr` custom pointer representation. This is the most important component
of the rewrite, and what enabled the expanded feature set and API surface.
This structure allows `BitSlice` and `BitVec` to have head cursors at any bit,
not just at the front edge of an element. This allows the crate to support
arbitrary range slicing and slice splitting, and in turn greatly expand the
usability of the slice and vector types.
The `BitPtr` type is wholly crate-internal, and renders the `&BitSlice` and
`BitVec` handle types ***wholly incompatible*** with standard Rust slice and
vector handles. With great power comes great responsibility to never, ever,
interchange these types through any means except the provided translation API.
- Range indexing and more powerful iteration. Bit-precision addressing allows
arbitrary subslices and enables more of the slice API from `core`.
### Changed
- Almost everything has been rewritten. The git diff for this version is
horrifying.
- Formatting traits better leverage the builtin printing structures available
from `core::fmt`, and are made available on `no_std`.
### Removed
- `u64` is only usable as the storage type on 64-bit systems; it has 32-bit
alignment on 32-bit systems and as such is unusable there.
## 0.9.0
### Changed
- The trait `Endian` has been renamed to `Cursor`, and all type variables
`E: Endian` have been renamed to `C: Cursor`.
- The `Bits` trait is no longer bound by `Default`.
## 0.8.0
### Added
- `std` and `alloc` features, which can be disabled for use in `#![no_std]`
libraries. This was implemented by Robert Habermeier, `rphmeier@gmail.com`.
Note that the `BitSlice` tests and all the examples are disabled when the
`alloc` feature is not present. They will function normally when `alloc` is
present but `std` is not.
### Changed
- Compute `Bits::WIDTH` as `size_of::<Self>() * 8` instead of `1 << Bits::BITS`.
## 0.7.0
### Added
- `examples/readme.rs` tracks the contents of the example code in `README.md`.
It will continue to do so until the `external_doc` feature stabilizes so that
the contents of the README can be included in the module documentation of
`src/lib.rs`.
- Officially use the Rust community code of conduct.
- README sections describe why a user might want this library, and what makes it
different than `bit-vec`.
### Changed
- Update minimum Rust version to `1.30.0`.
Internally, this permits use of `std` rather than `::std`. This compiler
edition does not change *intra-crate* macro usage. Clients at `1.30.0` and
above no longer need `#[macro_use]` above `extern crate bitvec;`, and are able
to import the `bitvec!` macro directly with `use bitvec::bitvec;` or
`use bitvec::prelude::*`.
Implementation note: References to literals stabilized at *some* point between
`1.20.0` and `1.30.0`, so the static bool items used for indexing are no
longer needed.
- Include numeric arithmetic as well as set arithmetic in the README.
## 0.6.0
### Changed
- Update minimum Rust version to `1.25.0` in order to use nested imports.
- Fix logic in `Endian::prev`, and re-enabled edge tests.
- Pluralize `BitSlice::count_one()` and `BitSlice::count_zero()` function names.
- Fix documentation and comments.
- Consolidate implementation of `bitvec!` to not use any other macros.
## 0.5.0
### Added
- `BitVec` and `BitSlice` implement `Hash`.
- `BitVec` fully implements addition, negation, and subtraction.
- `BitSlice` implements in-place addition and negation.
- `impl AddAssign for BitSlice`
- `impl Neg for &mut BitSlice`
This distinction is required in order to match the expectations of the
arithmetic traits and the realities of immovable `BitSlice`.
- `BitSlice` offers `.all()`, `.any()`, `.not_all()`, `.not_any()`, and
`.some()` methods to perform n-ary Boolean logic.
- `.all()` tests if all bits are set high
- `.any()` tests if any bits are set high (includes `.all()`)
- `.not_all()` tests if any bits are set low (includes `.not_all()`)
- `.not_any()` tests if all bits are set low
- `.some()` tests if any bits are high and any are low (excludes `.all()` and
`.not_all()`)
- `BitSlice` can count how many bits are set high or low with `.count_one()` and
`.count_zero()`.
## 0.4.0
### Added
`BitSlice::for_each` provides mutable iteration over a slice. It yields each
successive `(index: usize, bit: bool)` pair to a closure, and stores the return
value of that closure at the yielded index.
`BitVec` now implements `Eq` and `Ord` against other `BitVec`s. It is impossible
at this time to make `BitVec` generic over anything that is `Borrow<BitSlice>`,
which would allow comparisons over different ownership types. The declaration
```rust
impl<A, B, C, D, E> PartialEq<C> for BitVec<A, B>
where A: Endian,
B: Bits,
C: Borrow<BitSlice<D, E>>,
D: Endian,
E: Bits,
{
fn eq(&self, rhs: E) { … }
}
```
is impossible to write, so `BitVec == BitSlice` will be rejected.
As with many other traits on `BitVec`, the implementations are just a thin
wrapper over the corresponding `BitSlice` implementations.
### Changed
Refine the API documentation. Rust guidelines recommend imperative rather than
descriptive summaries for function documentation, which largely meant stripping
the trailing -s from the first verb in each function document.
I also moved the example code from the trait-level documentation to the
function-level documentation, so that it would show up an `type::func` in the
`rustdoc` output rather than just `type`. This makes it much clearer what is
being tested.
### Removed
`BitVec` methods `iter` and `raw_len` moved to `BitSlice` in `0.3.0` but were
not removed in that release.
The remaining debugging `eprintln!` calls have been stripped.
## 0.3.0
Split `BitVec` off into `BitSlice` wherever possible.
### Added
- The `BitSlice` type is the `[T]` to `BitVec`'s `Vec<T>`. `BitVec` now `Deref`s
to it, and has offloaded all the work that does not require managing allocated
memory.
- Almost all of the public API on both types has documentation and example code.
### Changed
- The implementations of left- ard right- shift are now faster.
- `BitVec` can `Borrow` and `Deref` down to `BitSlice`, and offloads as much
work as possible to it.
- `Clone` is more intelligent.
## 0.2.0
Improved the `bitvec!` macro.
### Changed
- `bitvec!` takes more syntaxes to better match `vec!`, and has better
runtime performance. The increased static memory used by `bitvec!` should be
more than counterbalanced by the vastly better generated code.
## 0.1.0
Initial implementation and release.
### Added
- `Endian` and `Bits` traits
- `BitVec` type with basic `Vec` idioms and parallel trait implementations
- `bitvec!` generator macro

View File

@ -1,5 +0,0 @@
# Code of Conduct
See the official [Rust code of conduct][coc].
[coc]: https://www.rust-lang.org/policies/code-of-conduct

View File

@ -1,45 +0,0 @@
# Contributing Guide
Contributions are absolutely welcome!
## Contact Information
In order of likelihood that I will actionably receive your contact, my
information is:
- [appayne@outlook.com](mailto:appayne@outlook.com)
- [@myrrlyn](//github.com/myrrlyn)
- [@myrrlyn](//twitter.com/myrrlyn)
- [@myrrlyn@cybre.space](//cybre.space/myrrlyn)
- [/u/myrrlyn](//reddit.com/u/myrrlyn)
I am not active on any IRC channels at this time. I am on Discord in the Rust
channel, so you may be able to reach me there, but I dont know offhand how to
give out Discord profile links. I have a very consistent username scheme and so
anywhere you see my name, its *probably* me and Ill *probably* respond to it.
## Preconditions
Be able to make a Rust project compile. I will happily help you learn how to do
this, but this particular crate is probably not something you want to explore as
a beginner.
Be comfortable using `U+0009 CHARACTER TABULATION` as your indentation setting.
Thats about it for prerequisites! This crate intends to power the lowest-level
of memory manipulation while also offering a convenient, powerful, and idiomatic
high-level API, so I encourage and welcome inputs on any aspect of this crates
construction. I know that I personally am much more capable at the low end than
the high, and so the user-facing API may not be as strong as it should be.
## Contributing
If you have a patch you think is worth inspecting right away, opening a pull
request without prelude is fine, although I would certainly appreciate an
accompanying explanation of what the patch does and why.
If you have questions, bugs, suggestions, or other contributions of any kind
that do not immediately touch the codebase, you can reach me informally to talk
about them or open an issue.
I will do my best to respond to all contacts in a timely manner.

View File

@ -1,71 +0,0 @@
[package]
name = "bitvec"
version = "0.11.0"
authors = [
"myrrlyn <self@myrrlyn.dev>",
]
categories = [
"data-structures",
"embedded",
"no-std",
"rust-patterns",
]
description = "A crate for manipulating memory, bit by bit"
documentation = "https://docs.rs/bitvec"
edition = "2018"
homepage = "https://myrrlyn.net/bitvec"
keywords = [
"bits",
"bitvec",
]
license = "MIT"
readme = "README.md"
repository = "https://github.com/myrrlyn/bitvec"
[features]
alloc = []
default = [
"std",
]
serdes = [
"serde",
]
std = [
"alloc",
]
testing = [
"std",
]
[dependencies.serde]
default-features = false
features = [
"derive",
]
optional = true
version = "1"
[dev-dependencies]
serde = "1"
serde_json = "1"
serde_test = "1"
[package.metadata.docs.rs]
features = [
"serdes",
"std",
]
[badges.codecov]
repository = "myrrlyn/bitvec"
branch = "master"
service = "github"
[badges.is-it-maintained-issue-resolution]
repository = "myrrlyn/bitvec"
[badges.is-it-maintained-open-issues]
repository = "myrrlyn/bitvec"
[badges.maintenance]
status = "actively-developed"

View File

@ -1,59 +0,0 @@
################################################################################
# Justfile #
# #
# Set of routines to execute for development work. As of 2019-03-31, `just` #
# does not work on Windows. #
################################################################################
# Cargo features
features = "serdes,std,testing"
# Builds the library.
build:
cargo build --features {{features}}
cargo build --features {{features}} --example sieve
cargo build --features {{features}} --example tour
cargo build --features {{features}} --example serdes
cargo build --features {{features}} --example readme
# Checks the library for syntax and HIR errors.
check:
cargo check --features {{features}}
# Runs all of the recipes necessary for pre-publish.
checkout: check clippy build doc test package
# Continually runs the development routines.
ci:
just loop dev
# Removes all build artifacts.
clean:
cargo clean
# Runs clippy.
clippy: check
cargo clippy --features {{features}}
# Runs the development routines.
dev: clippy doc test
# Builds the crate documentation.
doc:
cargo doc --features {{features}} --document-private-items
# Continually runs some recipe from this file.
loop action:
cargo watch -s "just {{action}}"
# Packages the crate in preparation for publishing on crates.io
package:
cargo package --allow-dirty
# Publishes the crate to crates.io
publish: checkout
cargo publish
# Runs the test suites.
test: check
cargo test --features {{features}}

View File

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2018 myrrlyn (Alexander Payne)
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.

View File

@ -1,243 +0,0 @@
# `BitVec` Managing memory bit by bit
[![Crate][crate_img]][crate]
[![Documentation][docs_img]][docs]
[![License][license_img]][license_file]
[![Continuous Integration][travis_img]][travis]
[![Code Coverage][codecov_img]][codecov]
[![Crate Downloads][downloads_img]][crate]
This crate provides packed bit-level analogues to `[T]` and `Vec<T>`. The slice
type `BitSlice` and the vector type `BitVec` allow bitwise access to a region of
memory in any endian ordering or underlying primitive type. This permits
construction of space-efficient sets or fine-grained control over the values in
a region of memory.
`BitVec` is a strict expansion of `BitSlice` to include allocation management.
Since `BitVec` is shorter to type, the rest of this document will use it by
default, and mark out sections that apply *only* to the vector type and not to
the slice type. Unless marked, assume that the text applies to both.
`BitVec` is generic over an ordering cursor, using the trait `Cursor`, and the
primitive type, using the trait `Bits`. This means that `BitVec` structures can
be built with a great deal of flexibility over how they manage their memory and
translate between the in-memory representation and their semantic contents.
`BitVec` acts as closely to a standard `Vec` as possible, and can be assumed by
default to be what a `Vec<u1>` would be if such a type were possible to express
in Rust. It has stack semantics, in that push and pop operations take place only
on one end of the `BitVec`s buffer. It supports iteration, bitwise operations,
and rendering for `Display` and `Debug`.
## How Is This Different Than the `bit_vec` Crate
- It is more recently actively maintained (I may, in the future as of this
writing, let it lapse)
- It doesnt have a hyphen in the name, so you dont have to deal with the
hyphen/underscore dichotomy.
- My `BitVec` structure is exactly the size of a `Vec`; theirs is larger.
- I have a `BitSlice` borrowed view.
- My types implement all of the standard librarys slice and vector APIs
## Why Would You Use This
- You need to directly control a bitstreams representation in memory.
- You need to do unpleasant things with communications protocols.
- You need a list of `bool`s that doesnt waste 7 bits for every bit used.
- You need to do set arithmetic, or numeric arithmetic, on those lists.
## Usage
**Minimum Rust Version**: `1.31.0`
I wrote this crate because I was unhappy with the other bit-vector crates
available. I specifically need to manage raw memory in bit-level precision, and
this is not a behavior pattern the other bit-vector crates made easily available
to me. This served as the guiding star for my development process on this crate,
and remains the crates primary goal.
To this end, the default type parameters for the `BitVec` type use `u8` as the
storage primitive and use big-endian ordering of bits: the forwards direction is
from MSb to LSb, and the backwards direction is from LSb to MSb.
To use this crate, you need to depend on it in `Cargo.toml`:
```toml
[dependencies]
bitvec = "0.11"
```
and include it in your crate root `src/main.rs` or `src/lib.rs`:
```rust,no-run
extern crate bitvec;
use bitvec::prelude::*;
```
This imports the following symbols:
- `bitvec!` a macro similar to `vec!`, which allows the creation of `BitVec`s
of any desired endianness, storage type, and contents. The documentation page
has a detailed explanation of its syntax.
- `BitSlice<C: Cursor, T: Bits>` the actual bit-slice reference type. It is
generic over a cursor type (`C`) and storage type (`T`). Note that `BitSlice`
is unsized, and can never be held directly; it must always be behind a
reference such as `&BitSlice` or `&mut BitSlice`.
Furthermore, it is *impossible* to put `BitSlice` into any kind of intelligent
pointer such as a `Box` or `Rc`! Any work that involves managing the memory
behind a bitwise type *must* go through `BitBox` or `BitVec` instead. This may
change in the future as I learn how to better manage this library, but for now
this limitation stands.
- `BitVec<C: Cursor, T: Bits>` the actual bit-vector structure type. It is
generic over a cursor type (`C`) and storage type (`T`).
- `Cursor` an open trait that defines an ordering schema for `BitVec` to use.
Little and big endian orderings are provided by default. If you wish to
implement other ordering types, the `Cursor` trait requires one function:
- `fn at<T: Bits>(index: u8) -> u8` takes a semantic index and computes a bit
offset into the primitive `T` for it.
- `BigEndian` a zero-sized struct that implements `Cursor` by defining the
forward direction as towards LSb and the backward direction as towards MSb.
- `LittleEndian` a zero-sized struct that implements `Cursor` by defining the
forward direction as towards MSb and the backward direction as towards LSb.
- `Bits` a sealed trait that provides generic access to the four Rust
primitives usable as storage types: `u8`, `u16`, `u32`, and `u64`. `usize`
and the signed integers do *not* implement `Bits` and cannot be used as the
storage type. `u128` also does not implement `Bits`, as I am not confident in
its memory representation.
`BitVec` has the same API as `Vec`, and should be easy to use.
The `bitvec!` macro requires type information as its first two arguments.
Because macros do not have access to the type checker, this currently only
accepts the literal tokens `BigEndian` or `LittleEndian` as the first argument,
one of the four unsigned integer primitives as the second argument, and then as
many values as you wish to insert into the `BitVec`. It accepts any integer
value, and maps them to bits by comparing against 0. `0` becomes `0` and any
other integer, whether it is odd or not, becomes `1`. While the syntax is loose,
you should only use `0` and `1` to fill the macro, for readability and lack of
surprise.
### `no_std`
This crate can be used in `#![no_std]` libraries, by disabling the default
feature set. In your `Cargo.toml`, write:
```toml
[dependencies]
bitvec = { version = "0.11", default-features = false }
```
or
```toml
[dependencies.bitvec]
version = "0.11"
default-features = false
```
This turns off the standard library imports *and* all usage of dynamic memory
allocation. Without an allocator, the `bitvec!` macro and the `BitVec` type are
both disable and removed from the library, leaving only the `BitSlice` type.
To use `bitvec` in a `#![no_std]` environment that *does* have an allocator,
re-enable the `alloc` feature, like so:
```toml
[dependencies.bitvec]
version = "0.11"
default-features = false
features = ["alloc"]
```
The `alloc` feature restores `bitvec!` and `BitVec`, as well as the `BitSlice`
interoperability with `BitVec`. The only difference between `alloc` and `std` is
the presence of the standard library façade and runtime support.
The `std` feature turns on `alloc`, so using this crate without any feature
flags *or* by explicitly enabling the `std` feature will enable full
functionality.
## Example
```rust
extern crate bitvec;
use bitvec::prelude::*;
use std::iter::repeat;
fn main() {
let mut bv = bitvec![BigEndian, u8; 0, 1, 0, 1];
bv.reserve(8);
bv.extend(repeat(false).take(4).chain(repeat(true).take(4)));
// Memory access
assert_eq!(bv.as_slice(), &[0b0101_0000, 0b1111_0000]);
// index 0 -^ ^- index 11
assert_eq!(bv.len(), 12);
assert!(bv.capacity() >= 16);
// Set operations
bv &= repeat(true);
bv = bv | repeat(false);
bv ^= repeat(true);
bv = !bv;
// Arithmetic operations
let one = bitvec![1];
bv += one.clone();
assert_eq!(bv.as_slice(), &[0b0101_0001, 0b0000_0000]);
bv -= one.clone();
assert_eq!(bv.as_slice(), &[0b0101_0000, 0b1111_0000]);
// Borrowing iteration
let mut iter = bv.iter();
// index 0
assert_eq!(iter.next().unwrap(), false);
// index 11
assert_eq!(iter.next_back().unwrap(), true);
assert_eq!(iter.len(), 10);
}
```
Immutable and mutable access to the underlying memory is provided by the `AsRef`
and `AsMut` implementations, so the `BitVec` can be readily passed to transport
functions.
`BitVec` implements `Borrow` down to `BitSlice`, and `BitSlice` implements
`ToOwned` up to `BitVec`, so they can be used in a `Cow` or wherever this API
is desired. Any case where a `Vec`/`[T]` pair cannot be replaced with a
`BitVec`/`BitSlice` pair is a bug in this library, and a bug report is
appropriate.
`BitVec` can relinquish its owned memory as a `Box<[T]>` via the
`.into_boxed_slice()` method, and `BitSlice` can relinquish access to its memory
simply by going out of scope.
## Planned Features
Contributions of items in this list are *absolutely* welcome! Contributions of
other features are also welcome, but Ill have to be sold on them.
- Creation of specialized pointers `Rc<BitSlice>` and `Arc<BitSlice>`.
[codecov]: https://codecov.io/gh/myrrlyn/bitvec "Code Coverage"
[codecov_img]: https://img.shields.io/codecov/c/github/myrrlyn/bitvec.svg?logo=codecov "Code Coverage Display"
[crate]: https://crates.io/crates/bitvec "Crate Link"
[crate_img]: https://img.shields.io/crates/v/bitvec.svg?logo=rust "Crate Page"
[docs]: https://docs.rs/bitvec "Documentation"
[docs_img]: https://docs.rs/bitvec/badge.svg "Documentation Display"
[downloads_img]: https://img.shields.io/crates/dv/bitvec.svg?logo=rust "Crate Downloads"
[license_file]: https://github.com/myrrlyn/bitvec/blob/master/LICENSE.txt "License File"
[license_img]: https://img.shields.io/crates/l/bitvec.svg "License Display"
[travis]: https://travis-ci.org/myrrlyn/bitvec "Travis CI"
[travis_img]: https://img.shields.io/travis/myrrlyn/bitvec.svg?logo=travis "Travis CI Display"

View File

@ -1,118 +0,0 @@
# Bit Patterns
This table displays the *bit index*, in [base64], of each position in a
`BitSlice<Cursor, Fundamental>` on a little-endian machine.
```text
byte | 00000000 11111111 22222222 33333333 44444444 55555555 66666666 77777777
bit | 76543210 76543210 76543210 76543210 76543210 76543210 76543210 76543210
------+------------------------------------------------------------------------
LEu__ | HGFEDCBA PONMLKJI XWVUTSRQ fedcbaZY nmlkjihg vutsrqpo 3210zyxw /+987654
BEu64 | 456789+/ wxyz0123 opqrstuv ghijklmn YZabcdef QRSTUVWX IJKLMNOP ABCDEFGH
BEu32 | YZabcdef QRSTUVWX IJKLMNOP ABCDEFGH 456789+/ wxyz0123 opqrstuv ghijklmn
BEu16 | IJKLMNOP ABCDEFGH YZabcdef QRSTUVWX opqrstuv ghijklmn 456789+/ wxyz0123
BEu8 | ABCDEFGH IJKLMNOP QRSTUVWX YZabcdef ghijklmn opqrstuv wxyz0123 456789+/
```
This table displays the bit index in [base64] of each position in a
`BitSlice<Cursor, Fundamental>` on a big-endian machine.
```text
byte | 00000000 11111111 22222222 33333333 44444444 55555555 66666666 77777777
bit | 76543210 76543210 76543210 76543210 76543210 76543210 76543210 76543210
------+------------------------------------------------------------------------
BEu__ | ABCDEFGH IJKLMNOP QRSTUVWX YZabcdef ghijklmn opqrstuv wxyz0123 456789+/
LEu64 | /+987654 3210zyxw vutsrqpo nmlkjihg fedcbaZY XWVUTSRQ PONMLKJI HGFEDCBA
LEu32 | fedcbaZY XWVUTSRQ PONMLKJI HGFEDCBA /+987654 3210zyxw vutsrqpo nmlkjihg
LEu16 | PONMLKJI HGFEDCBA fedcbaZY XWVUTSRQ vutsrqpo nmlkjihg /+987654 3210zyxw
LEu8 | HGFEDCBA PONMLKJI XWVUTSRQ fedcbaZY nmlkjihg vutsrqpo 3210zyxw /+987654
```
`<BigEndian, u8>` and `<LittleEndian, u8>` will always have the same
representation in memory on all machines. The wider cursors will not.
# Pointer Representation
Currently, the bitslice pointer uses the `len` field to address an individual
bit in the slice. This means that all bitslices can address `usize::MAX` bits,
regardless of the underlying storage fundamental. The bottom `3 <= n <= 6` bits
of `len` address the bit in the fundamental, and the high bits address the
fundamental in the slice.
The next representation of bitslice pointer will permit the data pointer to
address any *byte*, regardless of fundamental type, and address any bit in that
byte by storing the bit position in `len`. This reduces the bit storage capacity
of bitslice from `usize::MAX` to `usize::MAX / 8`. 2<sup>29</sup> is still a
very large number, so I do not anticipate 32-bit machines being too limited by
this.
This means that bitslice pointers will have the following representation, in C++
because Rust lacks bitfield syntax.
```cpp
template<typename T>
struct WidePtr<T> {
size_t ptr_byte : __builtin_ctzll(alignof(T)); // 0 ... 3
size_t ptr_data : sizeof(T*) * 8
- __builtin_ctzll(alignof(T)); // 64 ... 61
size_t len_head : 3;
size_t len_tail : 3 + __builtin_ctzll(alignof(T)); // 3 ... 6
size_t len_data : sizeof(size_t) * 8
- 6 - __builtin_ctzll(alignof(T)); // 58 ... 55
};
```
So, for any storage fundamental, its bitslice pointer representation has:
- the low `alignof` bits of the pointer for selecting a byte, and the rest of
the pointer for selecting the fundamental. This is just a `*const u8` except
the type remembers how to find the correctly aligned pointer.
- the lowest 3 bits of the length counter for selecting the bit under the head
pointer
- the *next* (3 + log<sub>2</sub>(bit size)) bits of the length counter address
the final bit within the final *storage fundamental* of the slice.
- the remaining high bits address the final *storage fundamental* of the slice,
counting from the correctly aligned address in the pointer.
# Calculations
Given an arbitrary `WidePtr<T>` value,
- the initial `*const T` pointer is retrieved by masking away the low bits of
the `ptr` value
- the number of `T` elements *between* the first and the last is found by taking
the `len` value, masking away the low bits, and shifting right/down.
- the number of `T` elements in the slice is found by taking the above and
adding one
- the address of the last `T` element in the slice is found by taking the
initial pointer, and adding the `T`-element-count to it
- the slot number of the first live bit in the slice is found by masking away
the high bits of `ptr` and shifting the result left/up by three, then adding
the low three bits of `len`
# Values
## Uninhabited Domains
All pointers whose non-`data` members are fully zeroed are considered
uninhabited. When the `data` member is the null pointer, then the slice is
*empty*; when it is non-null, the slice points to a validly allocated region of
memory and is merely uninhabited. This distinction is important for vectors.
## Full Domains
The longest possible domain has `!0` as its `elts`, and `tail` values, and `0`
as its `head` value.
When `elts` and `tail` are both `!0`, then the `!0`th element has `!0 - 1` live
bits. The final bit in the final element is a tombstone that cannot be used.
This is a regrettable consequence of the need to distinguish between the nil and
uninhabited slices.
[base64]: https://en.wikipedia.org/wiki/Base64

View File

@ -1,50 +0,0 @@
/*! Prove that the example code in `README.md` executes.
!*/
#[cfg(feature = "alloc")]
extern crate bitvec;
#[cfg(feature = "alloc")]
use bitvec::prelude::*;
#[cfg(feature = "alloc")]
use std::iter::repeat;
#[cfg(feature = "alloc")]
fn main() {
let mut bv = bitvec![BigEndian, u8; 0, 1, 0, 1];
bv.reserve(8);
bv.extend(repeat(false).take(4).chain(repeat(true).take(4)));
// Memory access
assert_eq!(bv.as_slice(), &[0b0101_0000, 0b1111_0000]);
// index 0 -^ ^- index 11
assert_eq!(bv.len(), 12);
assert!(bv.capacity() >= 16);
// Set operations
bv &= repeat(true);
bv = bv | repeat(false);
bv ^= repeat(true);
bv = !bv;
// Arithmetic operations
let one = bitvec![1];
bv += one.clone();
assert_eq!(bv.as_slice(), &[0b0101_0001, 0b0000_0000]);
bv -= one.clone();
assert_eq!(bv.as_slice(), &[0b0101_0000, 0b1111_0000]);
// Borrowing iteration
let mut iter = bv.iter();
// index 0
assert_eq!(iter.next().unwrap(), false);
// index 11
assert_eq!(iter.next_back().unwrap(), true);
assert_eq!(iter.len(), 10);
}
#[cfg(not(feature = "alloc"))]
fn main() {
println!("This example only runs when an allocator is present");
}

View File

@ -1,27 +0,0 @@
/*! This example shows off de/serializing a bit sequence using serde.
The example uses JSON for simplicity of demonstration; it should work with all
serde-compatible de/ser protocols.
!*/
extern crate bitvec;
extern crate serde;
extern crate serde_json;
use bitvec::prelude::*;
#[cfg(all(feature = "alloc", feature = "serdes"))]
fn main() {
let bv = bitvec![1, 0, 1, 1, 0, 0, 1, 0];
let json = serde_json::to_string(&bv).expect("cannot fail to serialize");
assert_eq!(json.trim(),r#"{"elts":1,"head":0,"tail":8,"data":[178]}"#);
let bb: BitBox = serde_json::from_str(&json).expect("cannot fail to deserialize");
assert!(bb[0]);
assert_eq!(bb.as_slice()[0], 178);
}
#[cfg(not(all(feature = "alloc", feature = "serdes")))]
fn main() {
println!("This test needs to be compiled with `--features serdes` to work");
}

View File

@ -1,125 +0,0 @@
/*! Sieve of Eratosthenes
The `bit_vec` crate had this as an example, so I do too, I guess.
Run with
```sh
$ cargo run --release --example sieve -- [max] [count]
```
where max is an optional maximum number below which all primes will be found,
and count is an optional number whose square will be used to display the bottom
primes.
For example,
```sh
$ cargo run --release --example sieve -- 10000000 25
```
will find all primes less than ten million, and print the primes below 625 in a
square 25x25.
!*/
#[cfg(feature = "alloc")]
extern crate bitvec;
#[cfg(feature = "alloc")]
use bitvec::prelude::{
BitVec,
BigEndian,
};
#[cfg(feature = "alloc")]
use std::env;
#[cfg(feature = "alloc")]
fn main() {
let max_prime: usize = env::args()
.nth(1)
.unwrap_or("1000000".into())
.parse()
.unwrap_or(1_000_000);
let primes = {
let mut bv = BitVec::<BigEndian, u64>::with_capacity(max_prime);
bv.set_elements(!0u64);
// Consider the vector fully populated
unsafe { bv.set_len(max_prime); }
// 0 and 1 are not primes
bv.set(0, false);
bv.set(1, false);
for n in 2 .. (1 + (max_prime as f64).sqrt() as usize) {
// Adjust the frequency of log statements vaguely logarithmically.
if n < 20_000 && n % 1_000 == 0
|| n < 50_000 && n % 5_000 == 0
|| n < 100_000 && n % 10_000 == 0 {
println!("Calculating {}", n);
}
// If n is prime, mark all multiples as non-prime
if bv[n] {
if n < 50 {
println!("Calculating {}", n);
}
'inner:
for i in n .. {
let j = n * i;
if j >= max_prime {
break 'inner;
}
bv.set(j, false);
}
}
}
println!("Calculation complete!");
bv
};
// Count primes and non-primes.
let (mut one, mut zero) = (0u64, 0u64);
for n in primes.iter() {
if n {
one += 1;
}
else {
zero += 1;
}
}
println!("Counting complete!");
println!("There are {} primes and {} non-primes below {}", one, zero, max_prime);
let dim: usize = env::args()
.nth(2)
.unwrap_or("10".into())
.parse()
.unwrap_or(10);
println!("The primes smaller than {} are:", dim * dim);
let len = primes.len();
'outer:
for i in 0 .. dim {
for j in 0 .. dim {
let k = i * dim + j;
if k >= len {
println!();
break 'outer;
}
if primes[k] {
print!("{:>4} ", k);
}
else {
print!(" ");
}
}
println!();
}
}
#[cfg(not(feature = "alloc"))]
fn main() {
println!("This example only runs when an allocator is present");
}

View File

@ -1,113 +0,0 @@
/*! Demonstrates construction and use of a big-endian, u8, `BitVec`
This example uses `bitvec!` to construct a `BitVec` from literals, then shows
a sample of the various operations that can be applied to it.
This example prints **a lot** of text to the console.
!*/
#[cfg(feature = "alloc")]
extern crate bitvec;
#[cfg(feature = "alloc")]
use bitvec::prelude::{
// `bitvec!` macro
bitvec,
// trait unifying the primitives (you shouldnt explicitly need this)
Bits,
// primary type of the whole crate! this is where the magic happens
BitVec,
// element-traversal trait (you shouldnt explicitly need this)
Cursor,
// directionality type marker (the default for `BitVec`; you will rarely
// explicitly need this)
BigEndian,
// directionality type marker (you will explicitly need this if you want
// this ordering)
LittleEndian,
};
#[cfg(feature = "alloc")]
use std::iter::repeat;
#[cfg(feature = "alloc")]
fn main() {
let bv = bitvec![ // BigEndian, u8; // default type values
0, 0, 0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0,
0, 1, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 1,
1, 0, 1, 0,
];
println!("A BigEndian BitVec has the same layout in memory as it does \
semantically");
render(&bv);
// BitVec can turn into iterators, and be built from iterators.
let bv: BitVec<LittleEndian, u8> = bv.into_iter().collect();
println!("A LittleEndian BitVec has the opposite layout in memory as it \
does semantically");
render(&bv);
let bv: BitVec<BigEndian, u16> = bv.into_iter().collect();
println!("A BitVec can use storage other than u8");
render(&bv);
println!("BitVec can participate in Boolean arithmetic");
let full = bv.clone() | repeat(true);
render(&full);
let empty = full & repeat(false);
render(&empty);
let flip = bv ^ repeat(true);
render(&flip);
let bv = !flip;
render(&bv);
println!("\
Notice that `^` did not affect the parts of the tail that were not in
use, while `!` did affect them. `^` requires a second source, while `!`
can just flip all elements. `!` is faster, but `^` is less likely to
break your assumptions about what the memory looks like.\
");
// Push and pop to the bitvec
let mut bv = bv;
for _ in 0 .. 12 {
bv.push(false);
}
for _ in 0 .. 12 {
bv.pop();
}
render(&bv);
println!("End example");
fn render<C: Cursor, T: Bits>(bv: &BitVec<C, T>) {
println!("Memory information: {} elements, {}", bv.as_slice().len(), bv.len());
println!("Print out the semantic contents");
println!("{:#?}", bv);
println!("Print out the memory contents");
println!("{:?}", bv.as_slice());
println!("Show the bits in memory");
for elt in bv.as_slice() {
println!("{:0w$b} ", elt, w=std::mem::size_of::<T>() * 8);
}
println!();
}
}
#[cfg(not(feature = "alloc"))]
fn main() {
println!("This example only runs when an allocator is present");
}

View File

@ -1,815 +0,0 @@
/*! Bit Management
The `Bits` trait defines constants and free functions suitable for managing bit
storage of a fundamental, and is the constraint for the storage type of the data
structures of the rest of the crate.
!*/
use crate::cursor::Cursor;
use core::{
cmp::Eq,
convert::From,
fmt::{
self,
Binary,
Debug,
Display,
Formatter,
LowerHex,
UpperHex,
},
mem::size_of,
ops::{
BitAnd,
BitAndAssign,
BitOrAssign,
Deref,
DerefMut,
Not,
Shl,
ShlAssign,
Shr,
ShrAssign,
},
};
/** Generalizes over the fundamental types for use in `bitvec` data structures.
This trait must only be implemented on unsigned integer primitives with full
alignment. It cannot be implemented on `u128` on any architecture, or on `u64`
on 32-bit systems.
The `Sealed` supertrait ensures that this can only be implemented locally, and
will never be implemented by downstream crates on new types.
**/
pub trait Bits:
// Forbid external implementation
Sealed
+ Binary
// Element-wise binary manipulation
+ BitAnd<Self, Output=Self>
+ BitAndAssign<Self>
+ BitOrAssign<Self>
// Permit indexing into a generic array
+ Copy
+ Debug
+ Display
// Permit testing a value against 1 in `get()`.
+ Eq
// Rust treats numeric literals in code as vaguely typed and does not make
// them concrete until long after trait expansion, so this enables building
// a concrete Self value from a numeric literal.
+ From<u8>
// Permit extending into a `u64`.
+ Into<u64>
+ LowerHex
+ Not<Output=Self>
+ Shl<u8, Output=Self>
+ ShlAssign<u8>
+ Shr<u8, Output=Self>
+ ShrAssign<u8>
// Allow direct access to a concrete implementor type.
+ Sized
+ UpperHex
{
/// The size, in bits, of this type.
const SIZE: u8 = size_of::<Self>() as u8 * 8;
/// The number of bits required to index the type. This is always
/// log<sub>2</sub> of the types bit size.
const BITS: u8 = Self::SIZE.trailing_zeros() as u8;
/// The bitmask to turn an arbitrary `usize` into a bit index. Bit indices
/// are always stored in the lowest bits of an index value.
const MASK: u8 = Self::SIZE - 1;
/// Name of the implementing type.
const TYPENAME: &'static str;
/// Sets a specific bit in an element to a given value.
///
/// # Parameters
///
/// - `place`: A bit index in the element, from `0` to `Self::MASK`. The bit
/// under this index will be set according to `value`.
/// - `value`: A Boolean value, which sets the bit on `true` and unsets it
/// on `false`.
///
/// # Type Parameters
///
/// - `C: Cursor`: A `Cursor` implementation to translate the index into a
/// position.
///
/// # Panics
///
/// This function panics if `place` is not less than `T::SIZE`, in order to
/// avoid index out of range errors.
///
/// # Examples
///
/// This example sets and unsets bits in a byte.
///
/// ```rust
/// use bitvec::prelude::{Bits, BigEndian};
/// let mut elt: u8 = 0;
/// elt.set::<BigEndian>(0.into(), true);
/// assert_eq!(elt, 0b1000_0000);
/// elt.set::<BigEndian>(4.into(), true);
/// assert_eq!(elt, 0b1000_1000);
/// elt.set::<BigEndian>(0.into(), false);
/// assert_eq!(elt, 0b0000_1000);
/// ```
///
/// This example overruns the index, and panics.
///
/// ```rust,should_panic
/// use bitvec::prelude::{Bits, BigEndian};
/// let mut elt: u8 = 0;
/// elt.set::<BigEndian>(8.into(), true);
/// ```
fn set<C: Cursor>(&mut self, place: BitIdx, value: bool) {
self.set_at(C::at::<Self>(place), value)
}
/// Sets a specific bit in an element to a given value.
///
/// # Parameters
///
/// - `place`: A bit *position* in the element, where `0` is the LSbit and
/// `Self::MASK` is the MSbit.
/// - `value`: A Boolean value, which sets the bit high on `true` and unsets
/// it low on `false`.
///
/// # Panics
///
/// This function panics if `place` is not less than `T::SIZE`, in order to
/// avoid index out of range errors.
///
/// # Examples
///
/// This example sets and unsets bits in a byte.
///
/// ```rust
/// use bitvec::bits::Bits;
/// let mut elt: u8 = 0;
/// elt.set_at(0.into(), true);
/// assert_eq!(elt, 0b0000_0001);
/// elt.set_at(7.into(), true);
/// assert_eq!(elt, 0b1000_0001);
/// ```
///
/// This example overshoots the width, and panics.
///
/// ```rust,should_panic
/// use bitvec::bits::Bits;
/// let mut elt: u8 = 0;
/// elt.set_at(8.into(), true);
/// ```
fn set_at(&mut self, place: BitPos, value: bool) {
assert!(
*place < Self::SIZE,
"Index out of range: {} overflows {}",
*place,
Self::SIZE,
);
// Blank the selected bit
*self &= !(Self::from(1u8) << *place);
// Set the selected bit
*self |= Self::from(value as u8) << *place;
}
/// Gets a specific bit in an element.
///
/// # Parameters
///
/// - `place`: A bit index in the element, from `0` to `Self::MASK`. The bit
/// under this index will be retrieved as a `bool`.
///
/// # Returns
///
/// The value of the bit under `place`, as a `bool`.
///
/// # Type Parameters
///
/// - `C: Cursor`: A `Cursor` implementation to translate the index into a
/// position.
///
/// # Panics
///
/// This function panics if `place` is not less than `T::SIZE`, in order to
/// avoid index out of range errors.
///
/// # Examples
///
/// This example gets two bits from a byte.
///
/// ```rust
/// use bitvec::prelude::{Bits, BigEndian};
/// let elt: u8 = 0b0010_0000;
/// assert!(!elt.get::<BigEndian>(1.into()));
/// assert!(elt.get::<BigEndian>(2.into()));
/// assert!(!elt.get::<BigEndian>(3.into()));
/// ```
///
/// This example overruns the index, and panics.
///
/// ```rust,should_panic
/// use bitvec::prelude::{Bits, BigEndian};
/// 0u8.get::<BigEndian>(8.into());
/// ```
fn get<C: Cursor>(&self, place: BitIdx) -> bool {
self.get_at(C::at::<Self>(place))
}
/// Gets a specific bit in an element.
///
/// # Parameters
///
/// - `place`: A bit *position* in the element, from `0` at LSbit to
/// `Self::MASK` at MSbit. The bit under this position will be retrieved
/// as a `bool`.
///
/// # Returns
///
/// The value of the bit under `place`, as a `bool`.
///
/// # Panics
///
/// This function panics if `place` is not less than `T::SIZE`, in order to
/// avoid index out of range errors.
///
/// # Examples
///
/// This example gets two bits from a byte.
///
/// ```rust
/// use bitvec::bits::Bits;
/// let elt: u8 = 0b0010_0000;
/// assert!(!elt.get_at(4.into()));
/// assert!(elt.get_at(5.into()));
/// assert!(!elt.get_at(6.into()));
/// ```
///
/// This example overruns the index, and panics.
///
/// ```rust,should_panic
/// use bitvec::bits::Bits;
/// 0u8.get_at(8.into());
/// ```
fn get_at(&self, place: BitPos) -> bool {
assert!(
*place < Self::SIZE,
"Index out of range: {} overflows {}",
*place,
Self::SIZE,
);
// Shift down so the targeted bit is in LSb, then blank all other bits.
(*self >> *place) & Self::from(1) == Self::from(1)
}
/// Counts how many bits in `self` are set to `1`.
///
/// This zero-extends `self` to `u64`, and uses the [`u64::count_ones`]
/// inherent method.
///
/// # Parameters
///
/// - `&self`
///
/// # Returns
///
/// The number of bits in `self` set to `1`. This is a `usize` instead of a
/// `u32` in order to ease arithmetic throughout the crate.
///
/// # Examples
///
/// ```rust
/// use bitvec::bits::Bits;
/// assert_eq!(Bits::count_ones(&0u8), 0);
/// assert_eq!(Bits::count_ones(&128u8), 1);
/// assert_eq!(Bits::count_ones(&192u8), 2);
/// assert_eq!(Bits::count_ones(&224u8), 3);
/// assert_eq!(Bits::count_ones(&240u8), 4);
/// assert_eq!(Bits::count_ones(&248u8), 5);
/// assert_eq!(Bits::count_ones(&252u8), 6);
/// assert_eq!(Bits::count_ones(&254u8), 7);
/// assert_eq!(Bits::count_ones(&255u8), 8);
/// ```
///
/// [`u64::count_ones`]: https://doc.rust-lang.org/stable/std/primitive.u64.html#method.count_ones
#[inline(always)]
fn count_ones(&self) -> usize {
u64::count_ones((*self).into()) as usize
}
/// Counts how many bits in `self` are set to `0`.
///
/// This inverts `self`, so all `0` bits are `1` and all `1` bits are `0`,
/// then zero-extends `self` to `u64` and uses the [`u64::count_ones`]
/// inherent method.
///
/// # Parameters
///
/// - `&self`
///
/// # Returns
///
/// The number of bits in `self` set to `0`. This is a `usize` instead of a
/// `u32` in order to ease arithmetic throughout the crate.
///
/// # Examples
///
/// ```rust
/// use bitvec::bits::Bits;
/// assert_eq!(Bits::count_zeros(&0u8), 8);
/// assert_eq!(Bits::count_zeros(&1u8), 7);
/// assert_eq!(Bits::count_zeros(&3u8), 6);
/// assert_eq!(Bits::count_zeros(&7u8), 5);
/// assert_eq!(Bits::count_zeros(&15u8), 4);
/// assert_eq!(Bits::count_zeros(&31u8), 3);
/// assert_eq!(Bits::count_zeros(&63u8), 2);
/// assert_eq!(Bits::count_zeros(&127u8), 1);
/// assert_eq!(Bits::count_zeros(&255u8), 0);
/// ```
///
/// [`u64::count_ones`]: https://doc.rust-lang.org/stable/std/primitive.u64.html#method.count_ones
#[inline(always)]
fn count_zeros(&self) -> usize {
// invert (0 become 1, 1 become 0), zero-extend, count ones
u64::count_ones((!*self).into()) as usize
}
}
/** Newtype indicating a semantic index into an element.
This type is consumed by [`Cursor`] implementors, which use it to produce a
concrete bit position inside an element.
`BitIdx` is a semantic counter which has a defined, constant, and predictable
ordering. Values of `BitIdx` refer strictly to abstract ordering, and not to the
actual position in an element, so `BitIdx(0)` is the first bit in an element,
but is not required to be the electrical `LSb`, `MSb`, or any other.
[`Cursor`]: ../trait.Cursor.html
**/
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct BitIdx(pub(crate) u8);
impl BitIdx {
/// Checks if the index is valid for a type.
///
/// Indices are valid in the range `0 .. T::SIZE`.
///
/// # Parameters
///
/// - `self`: The index to validate.
///
/// # Returns
///
/// Whether the index is valid for the storage type in question.
///
/// # Type Parameters
///
/// - `T: Bits`: The storage type used to determine index validity.
pub fn is_valid<T: Bits>(self) -> bool {
*self < T::SIZE
}
/// Checks if the index is valid as a tail index for a type.
///
/// Tail indices are vaild in the range `1 ..= T::SIZE`.
///
/// # Parameters
///
/// - `self`: The index to validate as a tail.
///
/// # Returns
///
/// Whether the index is valid as a tail for the storage type in question.
///
/// # Type Parameters
///
/// - `T: Bits`: The storage used to determine index tail validity.
pub fn is_valid_tail<T: Bits>(self) -> bool {
*self > 0 && *self <= T::SIZE
}
/// Increments a cursor to the next value, wrapping if needed.
///
/// # Parameters
///
/// - `self`: The original cursor.
///
/// # Returns
///
/// - `Self`: An incremented cursor.
/// - `bool`: Marks whether the increment crossed an element boundary.
///
/// # Type Parameters
///
/// - `T: Bits`: The storage type for which the increment will be
/// calculated.
///
/// # Panics
///
/// This method panics if `self` is not less than `T::SIZE`, in order to
/// avoid index out of range errors.
///
/// # Examples
///
/// This example increments inside an element.
///
/// ```rust
/// # #[cfg(feature = "testing")] {
/// use bitvec::testing::BitIdx;
/// assert_eq!(BitIdx::from(3).incr::<u8>(), (4.into(), false));
/// # }
/// ```
///
/// This example increments at the high edge, and wraps to the next element.
///
/// ```rust
/// # #[cfg(feature = "testing")] {
/// use bitvec::testing::BitIdx;
/// assert_eq!(BitIdx::from(7).incr::<u8>(), (0.into(), true));
/// # }
/// ```
pub fn incr<T: Bits>(self) -> (Self, bool) {
assert!(
self.is_valid::<T>(),
"Index out of range: {} overflows {}",
*self,
T::SIZE,
);
let next = (*self).wrapping_add(1) & T::MASK;
(next.into(), next == 0)
}
/// Decrements a cursor to the previous value, wrapping if needed.
///
/// # Parameters
///
/// - `self`: The original cursor.
///
/// # Returns
///
/// - `Self`: A decremented cursor.
/// - `bool`: Marks whether the decrement crossed an element boundary.
///
/// # Type Parameters
///
/// - `T: Bits`: The storage type for which the decrement will be
/// calculated.
///
/// # Panics
///
/// This method panics if `self` is not less than `T::SIZE`, in order to
/// avoid index out of range errors.
///
/// # Examples
///
/// This example decrements inside an element.
///
/// ```rust
/// # #[cfg(feature = "testing")] {
/// use bitvec::testing::BitIdx;
/// assert_eq!(BitIdx::from(5).decr::<u8>(), (4.into(), false));
/// # }
/// ```
///
/// This example decrements at the low edge, and wraps to the previous
/// element.
///
/// ```rust
/// # #[cfg(feature = "testing")] {
/// use bitvec::testing::BitIdx;
/// assert_eq!(BitIdx::from(0).decr::<u8>(), (7.into(), true));
/// # }
pub fn decr<T: Bits>(self) -> (Self, bool) {
assert!(
self.is_valid::<T>(),
"Index out of range: {} overflows {}",
*self,
T::SIZE,
);
let (prev, wrap) = (*self).overflowing_sub(1);
((prev & T::MASK).into(), wrap)
}
/// Finds the destination bit a certain distance away from a starting bit.
///
/// This produces the number of elements to move, and then the bit index of
/// the destination bit in the destination element.
///
/// # Parameters
///
/// - `self`: The bit index in an element of the starting position. This
/// must be in the domain `0 .. T::SIZE`.
/// - `by`: The number of bits by which to move. Negative values move
/// downwards in memory: towards `LSb`, then starting again at `MSb` of
/// the prior element in memory (decreasing address). Positive values move
/// upwards in memory: towards `MSb`, then starting again at `LSb` of the
/// subsequent element in memory (increasing address).
///
/// # Returns
///
/// - `isize`: The number of elements by which to change the callers
/// element cursor. This value can be passed directly into [`ptr::offset`]
/// - `BitIdx`: The bit index of the destination bit in the newly selected
/// element. This will always be in the domain `0 .. T::SIZE`. This
/// value can be passed directly into [`Cursor`] functions to compute the
/// correct place in the element.
///
/// # Type Parameters
///
/// - `T: Bits`: The storage type with which the offset will be calculated.
///
/// # Panics
///
/// This function panics if `from` is not less than `T::SIZE`, in order
/// to avoid index out of range errors.
///
/// # Safety
///
/// `by` must not be large enough to cause the returned `isize` value to,
/// when applied to [`ptr::offset`], produce a reference out of bounds of
/// the original allocation. This method has no means of checking this
/// requirement.
///
/// # Examples
///
/// This example calculates offsets within the same element.
///
/// ```rust
/// # #[cfg(feature = "testing")] {
/// use bitvec::testing::BitIdx;
/// assert_eq!(BitIdx::from(1).offset::<u32>(4isize), (0, 5.into()));
/// assert_eq!(BitIdx::from(6).offset::<u32>(-3isize), (0, 3.into()));
/// # }
/// ```
///
/// This example calculates offsets that cross into other elements. It uses
/// `u32`, so the bit index domain is `0 ..= 31`.
///
/// `7 - 18`, modulo 32, wraps down from 0 to 31 and continues decreasing.
/// `23 + 68`, modulo 32, wraps up from 31 to 0 and continues increasing.
///
/// ```rust
/// # #[cfg(feature = "testing")] {
/// use bitvec::testing::BitIdx;
/// assert_eq!(BitIdx::from(7).offset::<u32>(-18isize), (-1, 21.into()));
/// assert_eq!(BitIdx::from(23).offset::<u32>(68isize), (2, 27.into()));
/// # }
/// ```
///
/// [`Cursor`]: ../trait.Cursor.html
/// [`ptr::offset`]: https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.offset
pub fn offset<T: Bits>(self, by: isize) -> (isize, Self) {
assert!(
*self < T::SIZE,
"Index out of range: {} overflows {}",
*self,
T::SIZE,
);
// If the `isize` addition does not overflow, then the sum can be used
// directly.
if let (far, false) = by.overflowing_add(*self as isize) {
// If `far` is in the domain `0 .. T::SIZE`, then the offset did
// not depart the element.
if far >= 0 && far < T::SIZE as isize {
(0, (far as u8).into())
}
// If `far` is negative, then the offset leaves the initial element
// going down. If `far` is not less than `T::SIZE`, then the
// offset leaves the initial element going up.
else {
// `Shr` on `isize` sign-extends
(
far >> T::BITS,
((far & (T::MASK as isize)) as u8).into(),
)
}
}
// If the `isize` addition overflows, then the `by` offset is positive.
// Add as `usize` and use that. This is guaranteed not to overflow,
// because `isize -> usize` doubles the domain, but `self` is limited
// to `0 .. T::SIZE`.
else {
let far = *self as usize + by as usize;
// This addition will always result in a `usize` whose lowest
// `T::BITS` bits are the bit index in the destination element,
// and the rest of the high bits (shifted down) are the number of
// elements by which to advance.
(
(far >> T::BITS) as isize,
((far & (T::MASK as usize)) as u8).into(),
)
}
}
/// Computes the size of a span from `self` for `len` bits.
///
/// # Parameters
///
/// - `self`
/// - `len`: The number of bits to include in the span.
///
/// # Returns
///
/// - `usize`: The number of elements `T` included in the span. This will
/// be in the domain `1 .. usize::max_value()`.
/// - `BitIdx`: The index of the first bit *after* the span. This will be in
/// the domain `1 ..= T::SIZE`.
///
/// # Type Parameters
///
/// - `T: Bits`: The type of the elements for which this span is computed.
///
/// # Examples
///
/// ```rust
/// # #[cfg(feature = "testing")] {
/// use bitvec::testing::{BitIdx, Bits};
///
/// let h: BitIdx = 0.into();
/// assert_eq!(BitIdx::from(0).span::<u8>(8), (1, 8.into()))
/// # }
/// ```
pub fn span<T: Bits>(self, len: usize) -> (usize, BitIdx) {
// Number of bits in the head *element*. Domain 32 .. 0.
let bits_in_head = (T::SIZE - *self) as usize;
// If there are n bits live between the head cursor (which marks the
// address of the first live bit) and the back edge of the element,
// then when len is <= n, the span covers one element.
// When len == n, the tail will be T::SIZE, which is valid for a tail.
if len <= bits_in_head {
(1, (*self + len as u8).into())
}
// If there are more bits in the span than n, then subtract n from len
// and use the difference to count elements and bits.
else {
// 1 ..
let bits_after_head = len - bits_in_head;
// Count the number of wholly filled elements
let whole_elts = bits_after_head >> T::BITS;
// Count the number of bits in the *next* element. If this is zero,
// become T::SIZE; if it is nonzero, add one more to elts. elts
// must have one added to it by default to account for the head
// element.
let tail_bits = bits_after_head as u8 & T::MASK;
if tail_bits == 0 {
(whole_elts + 1, T::SIZE.into())
}
else {
(whole_elts + 2, tail_bits.into())
}
}
}
}
/// Wraps a `u8` as a `BitIdx`.
impl From<u8> for BitIdx {
fn from(src: u8) -> Self {
BitIdx(src)
}
}
/// Unwraps a `BitIdx` to a `u8`.
impl Into<u8> for BitIdx {
fn into(self) -> u8 {
self.0
}
}
impl Display for BitIdx {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "BitIdx({})", self.0)
}
}
impl Deref for BitIdx {
type Target = u8;
fn deref(&self) -> &Self::Target { &self.0 } }
impl DerefMut for BitIdx {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
}
/** Newtype indicating a concrete index into an element.
This type is produced by [`Cursor`] implementors, and denotes a concrete bit in
an element rather than a semantic bit.
`Cursor` implementors translate `BitIdx` values, which are semantic places, into
`BitPos` values, which are concrete electrical positions.
[`Cursor`]: ../trait.Cursor.html
**/
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct BitPos(u8);
impl BitPos {
/// Checks if the position is valid for a type.
///
/// # Parameters
///
/// - `self`: The position to validate.
///
/// # Returns
///
/// Whether the position is valid for the storage type in question.
///
/// # Type Parameters
///
/// - `T: Bits`: The storage type used to determine position validity.
pub fn is_valid<T: Bits>(self) -> bool {
*self < T::SIZE
}
}
/// Wraps a `u8` as a `BitPos`.
impl From<u8> for BitPos {
fn from(src: u8) -> Self {
BitPos(src)
}
}
/// Unwraps a `BitPos` to a `u8`.
impl Into<u8> for BitPos {
fn into(self) -> u8 {
self.0
}
}
impl Display for BitPos {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "BitPos({})", self.0)
}
}
impl Deref for BitPos {
type Target = u8;
fn deref(&self) -> &Self::Target { &self.0 }
}
impl DerefMut for BitPos {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
}
impl Bits for u8 { const TYPENAME: &'static str = "u8"; }
impl Bits for u16 { const TYPENAME: &'static str = "u16"; }
impl Bits for u32 { const TYPENAME: &'static str = "u32"; }
#[cfg(target_pointer_width = "64")]
impl Bits for u64 { const TYPENAME: &'static str = "u64"; }
/// Marker trait to seal `Bits` against downstream implementation.
///
/// This trait is public in the module, so that other modules in the crate can
/// use it, but so long as it is not exported by the crate root and this module
/// is private, this trait effectively forbids downstream implementation of the
/// `Bits` trait.
#[doc(hidden)]
pub trait Sealed {}
impl Sealed for u8 {}
impl Sealed for u16 {}
impl Sealed for u32 {}
#[cfg(target_pointer_width = "64")]
impl Sealed for u64 {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn jump_far_up() {
// isize::max_value() is 0x7f...ff, so the result bit will be one less
// than the start bit.
for n in 1 .. 8 {
let (elt, bit) = BitIdx::from(n).offset::<u8>(isize::max_value());
assert_eq!(elt, (isize::max_value() >> u8::BITS) + 1);
assert_eq!(*bit, n - 1);
}
let (elt, bit) = BitIdx::from(0).offset::<u8>(isize::max_value());
assert_eq!(elt, isize::max_value() >> u8::BITS);
assert_eq!(*bit, 7);
}
#[test]
fn jump_far_down() {
// isize::min_value() is 0x80...00, so the result bit will be equal to
// the start bit
for n in 0 .. 8 {
let (elt, bit) = BitIdx::from(n).offset::<u8>(isize::min_value());
assert_eq!(elt, isize::min_value() >> u8::BITS);
assert_eq!(*bit, n);
}
}
#[test]
#[should_panic]
fn offset_out_of_bound() {
BitIdx::from(64).offset::<u64>(isize::max_value());
}
}

View File

@ -1,938 +0,0 @@
/*! `BitBox` structure
This module holds the type for an owned but ungrowable bit sequence. `BitVec` is
the more appropriate and useful type for most collections.
!*/
#![cfg(feature = "alloc")]
use crate::{
bits::Bits,
cursor::{
BigEndian,
Cursor,
},
pointer::BitPtr,
slice::BitSlice,
vec::BitVec,
};
#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::{
borrow::{
Borrow,
BorrowMut,
ToOwned,
},
boxed::Box,
vec::Vec,
};
use core::{
clone::Clone,
cmp::{
Eq,
PartialEq,
PartialOrd,
Ord,
Ordering,
},
convert::{
AsMut,
AsRef,
From,
Into,
},
default::Default,
fmt::{
self,
Debug,
Display,
Formatter,
},
hash::{
Hash,
Hasher,
},
iter::{
DoubleEndedIterator,
ExactSizeIterator,
FusedIterator,
Iterator,
IntoIterator,
},
marker::PhantomData,
mem,
ops::{
Add,
AddAssign,
BitAnd,
BitAndAssign,
BitOr,
BitOrAssign,
BitXor,
BitXorAssign,
Deref,
DerefMut,
Drop,
Index,
IndexMut,
Range,
RangeFrom,
RangeFull,
RangeInclusive,
RangeTo,
RangeToInclusive,
Neg,
Not,
Shl,
ShlAssign,
Shr,
ShrAssign,
},
};
#[cfg(feature = "std")]
use std::{
borrow::{
Borrow,
BorrowMut,
ToOwned,
},
boxed::Box,
vec::Vec,
};
/** A pointer type for owned bit sequences.
This type is essentially a `&BitSlice` that owns its own memory. It can change
the contents of its domain, but it cannot change its own domain like `BitVec`
can. It is useful for fixed-size collections without lifetime tracking.
# Type Parameters
- `C: Cursor`: An implementor of the [`Cursor`] trait. This type is used to
convert semantic indices into concrete bit positions in elements, and store or
retrieve bit values from the storage type.
- `T: Bits`: An implementor of the [`Bits`] trait: `u8`, `u16`, `u32`, or `u64`.
This is the actual type in memory that the box will use to store data.
# Safety
The `BitBox` handle has the same *size* as standard Rust `Box<[T]>` handles, but
it is ***extremely binary incompatible*** with them. Attempting to treat
`BitBox<_, T>` as `Box<[T]>` in any manner except through the provided APIs is
***catastrophically*** unsafe and unsound.
# Trait Implementations
`BitBox<C, T>` implements all the traits that `BitSlice<C, T>` does, by
deferring to the `BitSlice` implementation. It also implements conversion traits
to and from `BitSlice`, and to/from `BitVec`.
**/
#[repr(C)]
pub struct BitBox<C = BigEndian, T = u8>
where C: Cursor, T: Bits {
_cursor: PhantomData<C>,
pointer: BitPtr<T>,
}
impl<C, T> BitBox<C, T>
where C: Cursor, T: Bits {
/// Constructs an empty slice at a given location.
///
/// # Parameters
///
/// - `data`: The address of the empty `BitBox` to construct.
///
/// # Returns
///
/// An empty `BitBox` at the given location.
pub fn uninhabited(data: *const T) -> Self {
Self {
_cursor: PhantomData,
pointer: BitPtr::uninhabited(data),
}
}
/// Copies a `BitSlice` into an owned `BitBox`.
///
/// # Parameters
///
/// - `src`: The `&BitSlice` to make owned.
///
/// # Returns
///
/// An owned clone of the given bit slice.
pub fn new(src: &BitSlice<C, T>) -> Self {
let store: Box<[T]> = src.as_ref().to_owned().into_boxed_slice();
let data = store.as_ptr();
let (_, elts, head, tail) = src.bitptr().raw_parts();
let out = Self {
_cursor: PhantomData,
pointer: BitPtr::new(data, elts, head, tail),
};
mem::forget(store);
out
}
/// Constructs a `BitBox` from a raw `BitPtr`.
///
/// After calling this function, the raw pointer is owned by the resulting
/// `BitBox`. The `BitBox` will deallocate the memory region it describes.
///
/// # Parameters
///
/// - `pointer`: A `BitPtr<T>` describing a region of owned memory. This
/// must have previously produced by `BitBox` constructors; it is unsound
/// to even pass in `BitPtr<T>` values taken from `BitVec<C, T>` handles.
///
/// # Returns
///
/// An owned `BitBox` over the given pointer.
///
/// # Safety
///
/// Because Rust does not specify the allocation scheme used, the only
/// valid pointer to pass into this function is one that had previously been
/// produced by `BitBox` constructors and extracted by [`BitBox::into_raw`].
///
/// This function is unsafe because improper use can lead to double-free
/// errors (constructing multiple `BitBox`es from the same `BitPtr`) or
/// allocator inconsistencies (arbitrary pointers).
///
/// [`BitBox::into_raw`]: #method.into_raw
pub unsafe fn from_raw(pointer: BitPtr<T>) -> Self {
Self {
_cursor: PhantomData,
pointer,
}
}
/// Consumes the `BitBox`, returning the wrapped `BitPtr` directly.
///
/// After calling this function, the caller is responsible for the memory
/// previously managed by the `BitBox`. In particular, the caller must
/// properly release the memory region to which the `BitPtr` refers.
/// The proper way to do so is to convert the `BitPtr` back into a `BitBox`
/// with the [`BitBox::from_raw`] function.
///
/// Note: this is an associated function, which means that you must call it
/// as `BitBox::into_raw(b)` instead of `b.into_raw()`. This is to match the
/// API of [`Box`]; there is no method conflict with [`BitSlice`].
///
/// [`BitBox::from_raw`]: #method.from_raw
/// [`BitSlice`]: ../struct.BitSlice.html
#[cfg_attr(not(feature = "std"), doc = "[`Box`]: https://doc.rust-lang.org/stable/alloc/boxed/struct.Box.html")]
#[cfg_attr(feature = "std", doc = "[`Box`]: https://doc.rust-lang.org/stable/std/boxed/struct.Box.html")]
// Permit associated function rather than method
#[allow(clippy::wrong_self_convention)]
pub unsafe fn into_raw(b: BitBox<C, T>) -> BitPtr<T> {
let out = b.bitptr();
mem::forget(b);
out
}
/// Consumes and leaks the `BitBox`, returning a mutable reference,
/// `&'a mut BitSlice<C, T>`. Note that the memory region `[T]` must outlive
/// the chosen lifetime `'a`.
///
/// This function is mainly useful for bit regions that live for the
/// remainder of the programs life. Dropping the returned reference will
/// cause a memory leak. If this is not acceptable, the reference should
/// first be wrapped with the [`Box::from_raw`] function, producing a
/// `BitBox`. This `BitBox` can then be dropped which will properly
/// deallocate the memory.
///
/// Note: this is an associated function, which means that you must call it
/// as `BitBox::leak(b)` instead of `b.leak()`. This is to match the API of
/// [`Box`]; there is no method conflict with [`BitSlice`].
///
/// # Parameters
///
/// - `b`: The `BitBox` to deconstruct.
///
/// # Returns
///
/// The raw pointer from inside the `BitBox`.
///
/// [`BitBox::from_raw`]: #method.from_raw
/// [`BitSlice`]: ../struct.BitSlice.html
#[cfg_attr(not(feature = "std"), doc = "[`Box`]: https://doc.rust-lang.org/stable/alloc/boxed/struct.Box.html")]
#[cfg_attr(feature = "std", doc = "[`Box`]: https://doc.rust-lang.org/stable/std/boxed/struct.Box.html")]
pub fn leak<'a>(b: BitBox<C, T>) -> &'a mut BitSlice<C, T> {
let out = b.bitptr();
mem::forget(b);
out.into()
}
/// Changes the cursor on a box handle, without changing the data it
/// governs.
///
/// # Parameters
///
/// - `self`
///
/// # Returns
///
/// An equivalent handle to the same data, with a new cursor parameter.
pub fn change_cursor<D>(self) -> BitBox<D, T>
where D: Cursor {
let bp = self.bitptr();
mem::forget(self);
unsafe { BitBox::from_raw(bp) }
}
/// Accesses the `BitSlice<C, T>` to which the `BitBox` refers.
///
/// # Parameters
///
/// - `&self`
///
/// # Returns
///
/// The slice of bits behind the box.
pub fn as_bitslice(&self) -> &BitSlice<C, T> {
self.pointer.into()
}
/// Accesses the `BitSlice<C, T>` to which the `BitBox` refers.
///
/// # Parameters
///
/// - `&mut self`
///
/// # Returns
///
/// The slice of bits behind the box.
pub fn as_mut_bitslice(&mut self) -> &mut BitSlice<C, T> {
self.pointer.into()
}
/// Gives read access to the `BitPtr<T>` structure powering the box.
///
/// # Parameters
///
/// - `&self`
///
/// # Returns
///
/// A copy of the interior `BitPtr<T>`.
pub(crate) fn bitptr(&self) -> BitPtr<T> {
self.pointer
}
/// Allows a function to access the `Box<[T]>` that the `BitBox` is using
/// under the hood.
///
/// # Parameters
///
/// - `&self`
/// - `func`: A function which works with a borrowed `Box<[T]>` representing
/// the actual memory held by the `BitBox`.
///
/// # Type Parameters
///
/// - `F: FnOnce(&Box<[T]>) -> R`: A function which borrows a box.
/// - `R`: The return value of the function.
///
/// # Returns
///
/// The return value of the provided function.
fn do_with_box<F, R>(&self, func: F) -> R
where F: FnOnce(&Box<[T]>) -> R {
let (data, elts, _, _) = self.bitptr().raw_parts();
let b: Box<[T]> = unsafe {
Vec::from_raw_parts(data as *mut T, elts, elts)
}.into_boxed_slice();
let out = func(&b);
mem::forget(b);
out
}
}
impl<C, T> Borrow<BitSlice<C, T>> for BitBox<C, T>
where C: Cursor, T: Bits {
fn borrow(&self) -> &BitSlice<C, T> {
&*self
}
}
impl<C, T> BorrowMut<BitSlice<C, T>> for BitBox<C, T>
where C: Cursor, T: Bits {
fn borrow_mut(&mut self) -> &mut BitSlice<C, T> {
&mut *self
}
}
impl<C, T> Clone for BitBox<C, T>
where C: Cursor, T: Bits {
fn clone(&self) -> Self {
let (e, h, t) = self.bitptr().region_data();
let new_box = self.do_with_box(Clone::clone);
let ptr = new_box.as_ptr();
mem::forget(new_box);
Self {
_cursor: PhantomData,
pointer: BitPtr::new(ptr, e, h, t),
}
}
}
impl<C, T> Eq for BitBox<C, T>
where C: Cursor, T: Bits {}
impl<C, T> Ord for BitBox<C, T>
where C: Cursor, T: Bits {
fn cmp(&self, rhs: &Self) -> Ordering {
(&**self).cmp(&**rhs)
}
}
impl<A, B, C, D> PartialEq<BitBox<C, D>> for BitBox<A, B>
where A: Cursor, B: Bits, C: Cursor, D: Bits {
fn eq(&self, rhs: &BitBox<C, D>) -> bool {
(&**self).eq(&**rhs)
}
}
impl<A, B, C, D> PartialEq<BitSlice<C, D>> for BitBox<A, B>
where A: Cursor, B: Bits, C: Cursor, D: Bits {
fn eq(&self, rhs: &BitSlice<C, D>) -> bool {
(&**self).eq(rhs)
}
}
impl<A, B, C, D> PartialEq<BitBox<C, D>> for BitSlice<A, B>
where A: Cursor, B: Bits, C: Cursor, D: Bits {
fn eq(&self, rhs: &BitBox<C, D>) -> bool {
self.eq(&**rhs)
}
}
impl<A, B, C, D> PartialOrd<BitBox<C, D>> for BitBox<A, B>
where A: Cursor, B: Bits, C: Cursor, D: Bits {
fn partial_cmp(&self, rhs: &BitBox<C, D>) -> Option<Ordering> {
(&**self).partial_cmp(&**rhs)
}
}
impl<A, B, C, D> PartialOrd<BitSlice<C, D>> for BitBox<A, B>
where A: Cursor, B: Bits, C: Cursor, D: Bits {
fn partial_cmp(&self, rhs: &BitSlice<C, D>) -> Option<Ordering> {
(&**self).partial_cmp(rhs)
}
}
impl<A, B, C, D> PartialOrd<BitBox<C, D>> for BitSlice<A, B>
where A: Cursor, B: Bits, C: Cursor, D: Bits {
fn partial_cmp(&self, rhs: &BitBox<C, D>) -> Option<Ordering> {
self.partial_cmp(&**rhs)
}
}
impl<C, T> AsMut<BitSlice<C, T>> for BitBox<C, T>
where C: Cursor, T: Bits {
fn as_mut(&mut self) -> &mut BitSlice<C, T> {
self.as_mut_bitslice()
}
}
impl<C, T> AsMut<[T]> for BitBox<C, T>
where C: Cursor, T: Bits {
fn as_mut(&mut self) -> &mut [T] {
(&mut **self).as_mut()
}
}
impl<C, T> AsRef<BitSlice<C, T>> for BitBox<C, T>
where C: Cursor, T: Bits {
fn as_ref(&self) -> &BitSlice<C, T> {
self.as_bitslice()
}
}
impl<C, T> AsRef<[T]> for BitBox<C, T>
where C: Cursor, T: Bits {
fn as_ref(&self) -> &[T] {
(&**self).as_ref()
}
}
impl<C, T> From<&BitSlice<C, T>> for BitBox<C, T>
where C: Cursor, T: Bits {
fn from(src: &BitSlice<C, T>) -> Self {
let (_, elts, head, tail) = src.bitptr().raw_parts();
let b: Box<[T]> = src.as_ref().to_owned().into_boxed_slice();
let out = Self {
_cursor: PhantomData,
pointer: BitPtr::new(b.as_ptr(), elts, head, tail),
};
mem::forget(b);
out
}
}
/// Builds a `BitBox` out of a borrowed slice of elements.
///
/// This copies the memory as-is from the source buffer into the new `BitBox`.
/// The source buffer will be unchanged by this operation, so you don't need to
/// worry about using the correct cursor type for the read.
///
/// This operation does a copy from the source buffer into a new allocation, as
/// it can only borrow the source and not take ownership.
impl<C, T> From<&[T]> for BitBox<C, T>
where C: Cursor, T: Bits {
/// Builds a `BitBox<C: Cursor, T: Bits>` from a borrowed `&[T]`.
///
/// # Parameters
///
/// - `src`: The elements to use as the values for the new vector.
///
/// # Examples
///
/// ```rust
/// use bitvec::prelude::*;
///
/// let src: &[u8] = &[5, 10];
/// let bv: BitBox = src.into();
/// assert!(bv[5]);
/// assert!(bv[7]);
/// assert!(bv[12]);
/// assert!(bv[14]);
/// ```
fn from(src: &[T]) -> Self {
assert!(src.len() < BitPtr::<T>::MAX_ELTS, "Box overflow");
<&BitSlice<C, T>>::from(src).into()
}
}
impl<C, T> From<BitVec<C, T>> for BitBox<C, T>
where C: Cursor, T: Bits {
fn from(mut src: BitVec<C, T>) -> Self {
src.shrink_to_fit();
let pointer = src.bitptr();
mem::forget(src);
unsafe { Self::from_raw(pointer) }
}
}
/// Builds a `BitBox` out of an owned slice of elements.
///
/// This moves the memory as-is from the source buffer into the new `BitBox`.
/// The source buffer will be unchanged by this operation, so you don't need to
/// worry about using the correct cursor type.
impl<C, T> From<Box<[T]>> for BitBox<C, T>
where C: Cursor, T: Bits {
/// Consumes a `Box<[T: Bits]>` and creates a `BitBox<C: Cursor, T>` from
/// it.
///
/// # Parameters
///
/// - `src`: The source box whose memory will be used.
///
/// # Returns
///
/// A new `BitBox` using the `src` `Box`s memory.
///
/// # Examples
///
/// ```rust
/// use bitvec::prelude::*;
///
/// let src: Box<[u8]> = Box::new([3, 6, 9, 12, 15]);
/// let bv: BitBox = src.into();
/// ```
fn from(src: Box<[T]>) -> Self {
assert!(src.len() < BitPtr::<T>::MAX_ELTS, "Box overflow");
let out = Self {
_cursor: PhantomData,
pointer: BitPtr::new(src.as_ptr(), src.len(), 0, T::SIZE)
};
mem::forget(src);
out
}
}
impl<C, T> Into<Box<[T]>> for BitBox<C, T>
where C: Cursor, T: Bits {
fn into(self) -> Box<[T]> {
let (ptr, len, _, _) = self.bitptr().raw_parts();
let out = unsafe { Vec::from_raw_parts(ptr as *mut T, len, len) }
.into_boxed_slice();
mem::forget(self);
out
}
}
impl<C, T> Default for BitBox<C, T>
where C: Cursor, T: Bits {
fn default() -> Self {
Self {
_cursor: PhantomData,
pointer: BitPtr::default(),
}
}
}
impl<C, T> Debug for BitBox<C, T>
where C: Cursor, T: Bits {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.write_str("BitBox<")?;
f.write_str(C::TYPENAME)?;
f.write_str(", ")?;
f.write_str(T::TYPENAME)?;
f.write_str("> ")?;
Display::fmt(&**self, f)
}
}
impl<C, T> Display for BitBox<C, T>
where C: Cursor, T: Bits {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
Display::fmt(&**self, f)
}
}
impl<C, T> Hash for BitBox<C, T>
where C: Cursor, T: Bits {
fn hash<H: Hasher>(&self, hasher: &mut H) {
(&**self).hash(hasher)
}
}
impl<C, T> IntoIterator for BitBox<C, T>
where C: Cursor, T: Bits {
type Item = bool;
type IntoIter = IntoIter<C, T>;
fn into_iter(self) -> Self::IntoIter {
IntoIter {
iterator: self.bitptr(),
_original: self,
}
}
}
impl<'a, C, T> IntoIterator for &'a BitBox<C, T>
where C: Cursor, T: 'a + Bits {
type Item = bool;
type IntoIter = <&'a BitSlice<C, T> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
(&**self).into_iter()
}
}
impl<C, T> Add<Self> for BitBox<C, T>
where C: Cursor, T: Bits {
type Output = Self;
fn add(mut self, addend: Self) -> Self::Output {
self += addend;
self
}
}
impl<C, T> AddAssign for BitBox<C, T>
where C: Cursor, T: Bits {
fn add_assign(&mut self, addend: Self) {
**self += &*addend
}
}
impl<C, T, I> BitAnd<I> for BitBox<C, T>
where C: Cursor, T: Bits, I: IntoIterator<Item=bool> {
type Output = Self;
fn bitand(mut self, rhs: I) -> Self::Output {
self &= rhs;
self
}
}
impl<C, T, I> BitAndAssign<I> for BitBox<C, T>
where C: Cursor, T: Bits, I: IntoIterator<Item=bool> {
fn bitand_assign(&mut self, rhs: I) {
**self &= rhs;
}
}
impl<C, T, I> BitOr<I> for BitBox<C, T>
where C: Cursor, T: Bits, I: IntoIterator<Item=bool> {
type Output = Self;
fn bitor(mut self, rhs: I) -> Self::Output {
self |= rhs;
self
}
}
impl<C, T, I> BitOrAssign<I> for BitBox<C, T>
where C: Cursor, T: Bits, I: IntoIterator<Item=bool> {
fn bitor_assign(&mut self, rhs: I) {
**self |= rhs;
}
}
impl<C, T, I> BitXor<I> for BitBox<C, T>
where C: Cursor, T: Bits, I: IntoIterator<Item=bool> {
type Output = Self;
fn bitxor(mut self, rhs: I) -> Self::Output {
self ^= rhs;
self
}
}
impl<C, T, I> BitXorAssign<I> for BitBox<C, T>
where C: Cursor, T: Bits, I: IntoIterator<Item=bool> {
fn bitxor_assign(&mut self, rhs: I) {
**self ^= rhs;
}
}
impl<C, T> Deref for BitBox<C, T>
where C: Cursor, T: Bits {
type Target = BitSlice<C, T>;
fn deref(&self) -> &Self::Target {
self.pointer.into()
}
}
impl<C, T> DerefMut for BitBox<C, T>
where C: Cursor, T: Bits {
fn deref_mut(&mut self) -> &mut Self::Target {
self.pointer.into()
}
}
impl<C, T> Drop for BitBox<C, T>
where C: Cursor, T: Bits {
fn drop(&mut self) {
let ptr = self.as_mut_bitslice().as_mut_ptr();
let len = self.as_bitslice().len();
// Run the `Box<[T]>` destructor.
drop(unsafe { Vec::from_raw_parts(ptr, len, len).into_boxed_slice() });
}
}
impl<C, T> Index<usize> for BitBox<C, T>
where C: Cursor, T: Bits {
type Output = bool;
fn index(&self, index: usize) -> &Self::Output {
&(**self)[index]
}
}
impl<C, T> Index<Range<usize>> for BitBox<C, T>
where C: Cursor, T: Bits {
type Output = BitSlice<C, T>;
fn index(&self, range: Range<usize>) -> &Self::Output {
&(**self)[range]
}
}
impl<C, T> IndexMut<Range<usize>> for BitBox<C, T>
where C: Cursor, T: Bits {
fn index_mut(&mut self, range: Range<usize>) -> &mut Self::Output {
&mut (**self)[range]
}
}
impl<C, T> Index<RangeFrom<usize>> for BitBox<C, T>
where C: Cursor, T: Bits {
type Output = BitSlice<C, T>;
fn index(&self, range: RangeFrom<usize>) -> &Self::Output {
&(**self)[range]
}
}
impl<C, T> IndexMut<RangeFrom<usize>> for BitBox<C, T>
where C: Cursor, T: Bits {
fn index_mut(&mut self, range: RangeFrom<usize>) -> &mut Self::Output {
&mut (**self)[range]
}
}
impl<C, T> Index<RangeFull> for BitBox<C, T>
where C: Cursor, T: Bits {
type Output = BitSlice<C, T>;
fn index(&self, range: RangeFull) -> &Self::Output {
&(**self)[range]
}
}
impl<C, T> IndexMut<RangeFull> for BitBox<C, T>
where C: Cursor, T: Bits {
fn index_mut(&mut self, range: RangeFull) -> &mut Self::Output {
&mut (**self)[range]
}
}
impl<C, T> Index<RangeInclusive<usize>> for BitBox<C, T>
where C: Cursor, T: Bits {
type Output = BitSlice<C, T>;
fn index(&self, range: RangeInclusive<usize>) -> &Self::Output {
&(**self)[range]
}
}
impl<C, T> IndexMut<RangeInclusive<usize>> for BitBox<C, T>
where C: Cursor, T: Bits {
fn index_mut(&mut self, range: RangeInclusive<usize>) -> &mut Self::Output {
&mut (**self)[range]
}
}
impl<C, T> Index<RangeTo<usize>> for BitBox<C, T>
where C: Cursor, T: Bits {
type Output = BitSlice<C, T>;
fn index(&self, range: RangeTo<usize>) -> &Self::Output {
&(**self)[range]
}
}
impl<C, T> IndexMut<RangeTo<usize>> for BitBox<C, T>
where C: Cursor, T: Bits {
fn index_mut(&mut self, range: RangeTo<usize>) -> &mut Self::Output {
&mut (**self)[range]
}
}
impl<C, T> Index<RangeToInclusive<usize>> for BitBox<C, T>
where C: Cursor, T: Bits {
type Output = BitSlice<C, T>;
fn index(&self, range: RangeToInclusive<usize>) -> &Self::Output {
&(**self)[range]
}
}
impl<C, T> IndexMut<RangeToInclusive<usize>> for BitBox<C, T>
where C: Cursor, T: Bits {
fn index_mut(&mut self, range: RangeToInclusive<usize>) -> &mut Self::Output {
&mut (**self)[range]
}
}
impl<C, T> Neg for BitBox<C, T>
where C: Cursor, T: Bits {
type Output = Self;
fn neg(mut self) -> Self::Output {
let _ = -(&mut *self);
self
}
}
impl<C, T> Not for BitBox<C, T>
where C: Cursor, T: Bits {
type Output = Self;
fn not(mut self) -> Self::Output {
let _ = !(&mut *self);
self
}
}
impl<C, T> Shl<usize> for BitBox<C, T>
where C: Cursor, T: Bits {
type Output = Self;
fn shl(mut self, shamt: usize) -> Self::Output {
self <<= shamt;
self
}
}
impl<C, T> ShlAssign<usize> for BitBox<C, T>
where C: Cursor, T: Bits {
fn shl_assign(&mut self, shamt: usize) {
**self <<= shamt;
}
}
impl<C, T> Shr<usize> for BitBox<C, T>
where C: Cursor, T: Bits {
type Output = Self;
fn shr(mut self, shamt: usize) -> Self::Output {
self >>= shamt;
self
}
}
impl<C, T> ShrAssign<usize> for BitBox<C, T>
where C: Cursor, T: Bits {
fn shr_assign(&mut self, shamt: usize) {
**self >>= shamt;
}
}
#[repr(C)]
pub struct IntoIter<C, T>
where C: Cursor, T: Bits {
/// Owning pointer to the full slab
_original: BitBox<C, T>,
/// Slice descriptor for the region undergoing iteration.
iterator: BitPtr<T>,
}
impl<C, T> IntoIter<C, T>
where C: Cursor, T: Bits {
fn iterator(&self) -> <&BitSlice<C, T> as IntoIterator>::IntoIter {
<&BitSlice<C, T>>::from(self.iterator).into_iter()
}
}
impl<C, T> DoubleEndedIterator for IntoIter<C, T>
where C: Cursor, T: Bits {
fn next_back(&mut self) -> Option<Self::Item> {
let mut slice_iter = self.iterator();
let out = slice_iter.next_back();
self.iterator = slice_iter.bitptr();
out
}
}
impl<C, T> ExactSizeIterator for IntoIter<C, T>
where C: Cursor, T: Bits {}
impl<C, T> FusedIterator for IntoIter<C, T>
where C: Cursor, T: Bits {}
impl<C, T> Iterator for IntoIter<C, T>
where C: Cursor, T: Bits {
type Item = bool;
fn next(&mut self) -> Option<Self::Item> {
let mut slice_iter = self.iterator();
let out = slice_iter.next();
self.iterator = slice_iter.bitptr();
out
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iterator().size_hint()
}
fn count(self) -> usize {
self.len()
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
let mut slice_iter = self.iterator();
let out = slice_iter.nth(n);
self.iterator = slice_iter.bitptr();
out
}
fn last(mut self) -> Option<Self::Item> {
self.next_back()
}
}

View File

@ -1,129 +0,0 @@
/*! Bit Cursors
`bitvec` structures are parametric over any ordering of bits within an element.
The `Cursor` trait maps a cursor position (indicated by the `BitIdx` type) to an
electrical position (indicated by the `BitPos` type) within that element, and
also defines the order of traversal over an element.
The only requirement on implementors of `Cursor` is that the transform function
from cursor (`BitIdx`) to position (`BitPos`) is *total* (every integer in the
domain `0 .. T::SIZE` is used) and *unique* (each cursor maps to one and only
one position, and each position is mapped by one and only one cursor).
Contiguity is not required.
`Cursor` is a stateless trait, and implementors should be zero-sized types.
!*/
use super::bits::{
BitIdx,
BitPos,
Bits,
};
/// Traverses an element from `MSbit` to `LSbit`.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct BigEndian;
/// Traverses an element from `LSbit` to `MSbit`.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct LittleEndian;
/** A cursor over an element.
# Usage
`bitvec` structures store and operate on semantic counts, not bit positions. The
`Cursor::at` function takes a semantic cursor, `BitIdx`, and produces an
electrical position, `BitPos`.
**/
pub trait Cursor {
/// Name of the cursor type, for use in text display.
const TYPENAME: &'static str;
/// Translate a semantic bit index into an electrical bit position.
///
/// # Parameters
///
/// - `cursor`: The semantic bit value.
///
/// # Returns
///
/// - A concrete position. This value can be used for shifting and masking
/// to extract a bit from an element. This must be in the domain
/// `0 .. T::SIZE`.
///
/// # Type Parameters
///
/// - `T: Bits`: The storage type for which the position will be calculated.
///
/// # Invariants
///
/// The function **must** be *total* for the domain `.. T::SIZE`. All values
/// in this domain are valid indices that the library will pass to it, and
/// which this function must satisfy.
///
/// The function **must** be *bijective* over the domain `.. T::SIZE`. All
/// input values in this domain must have one and only one correpsonding
/// output, which must also be in this domain.
///
/// The function *may* support input in the domain `T::SIZE ..`. The library
/// will not produce any values in this domain as input indices. The
/// function **must not** produce output in the domain `T::SIZE ..`. It must
/// choose between panicking, or producing an output in `.. T::SIZE`. The
/// reduction in domain from `T::SIZE ..` to `.. T::SIZE` removes the
/// requirement for inputs in `T::SIZE ..` to have unique outputs in
/// `.. T::SIZE`.
///
/// This function **must** be *pure*. Calls which have the same input must
/// produce the same output. This invariant is only required to be upheld
/// for the lifetime of all data structures which use an implementor. The
/// behavior of the function *may* be modified after all existing dependent
/// data structures are destroyed and before any new dependent data
/// structures are created.
///
/// # Non-Invariants
///
/// This function is *not* required to be stateless. It *may* refer to
/// immutable global state, subject to the purity requirement on lifetimes.
///
/// # Safety
///
/// This function requires that the output be in the domain `.. T::SIZE`.
/// Implementors must uphold this themselves. Outputs in the domain
/// `T::SIZE ..` will induce panics elsewhere in the library.
fn at<T: Bits>(cursor: BitIdx) -> BitPos;
}
impl Cursor for BigEndian {
const TYPENAME: &'static str = "BigEndian";
/// Maps a semantic count to a concrete position.
///
/// `BigEndian` order moves from `MSbit` first to `LSbit` last.
fn at<T: Bits>(cursor: BitIdx) -> BitPos {
assert!(
*cursor < T::SIZE,
"Index out of range: {} overflows {}",
*cursor,
T::SIZE,
);
(T::MASK - *cursor).into()
}
}
impl Cursor for LittleEndian {
const TYPENAME: &'static str = "LittleEndian";
/// Maps a semantic count to a concrete position.
///
/// `LittleEndian` order moves from `LSbit` first to `MSbit` last.
fn at<T: Bits>(cursor: BitIdx) -> BitPos {
assert!(
*cursor < T::SIZE,
"Index out of range: {} overflows {}",
*cursor,
T::SIZE,
);
(*cursor).into()
}
}

View File

@ -1,367 +0,0 @@
/*! Data Model for Bit Sequence Domains
The domains governed by `BitSlice` and owned-variant handles have different
representative states depending on the span of governed elements and live bits.
This module provides representations of the domain states for ease of use by
handle operations.
!*/
use crate::{
bits::{
BitIdx,
Bits,
},
pointer::BitPtr,
};
/// Variant markers for the kinds of domains.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum BitDomainKind {
/// Zero elements
Empty,
/// Single element, partial on both edges
Minor,
/// Multiple elements, partial on both edges
Major,
/// Partial on head only
PartialHead,
/// Partial on tail only
PartialTail,
/// Fully spans elements
Spanning,
}
impl BitDomainKind {
/// Tests if the variant is `Empty`.
pub fn is_empty(self) -> bool { self == BitDomainKind::Empty }
/// Tests if the variant is `Minor`.
pub fn is_minor(self) -> bool { self == BitDomainKind::Minor }
/// Tests if the variant is `Major`.
pub fn is_major(self) -> bool { self == BitDomainKind::Major }
/// Tests if the variant is `PartialHead`.
pub fn is_partial_head(self) -> bool { self == BitDomainKind::PartialHead }
/// Tests if the variant is `PartialTail`.
pub fn is_partial_tail(self) -> bool { self == BitDomainKind::PartialTail }
/// Tests if the variant is `Spanning`.
pub fn is_spanning(self) -> bool { self == BitDomainKind::Spanning }
}
impl<T> From<BitPtr<T>> for BitDomainKind
where T: Bits {
fn from(bitptr: BitPtr<T>) -> Self {
let (e, h, t) = bitptr.region_data();
let w = T::SIZE;
match (e, *h, *t) {
// Empty
(0, _, _) => BitDomainKind::Empty,
// Reaches both edges, for any number of elements
(_, 0, tc) if tc == w => BitDomainKind::Spanning,
// Reaches only the tail edge, for any number of elements
(_, _, tc) if tc == w => BitDomainKind::PartialHead,
// Reaches only the head edge, for any number of elements
(_, 0, _ ) => BitDomainKind::PartialTail,
// Reaches neither edge, for one element
(1, _, _) => BitDomainKind::Minor,
// Reaches neither edge, for multiple elements
(_, _, _ ) => BitDomainKind::Major,
}
}
}
/// Representations of the state of the bit domain in its containing elements.
///
/// # Lifetimes
///
/// - `'a`: Lifetime of the containing storage
///
/// # Type Parameters
///
/// - `T: Bits` The type of the elements the domain inhabits.
#[derive(Clone, Debug)]
pub enum BitDomain<'a, T>
where T: 'a + Bits {
/// Empty domain.
Empty,
/// Single element domain which does not reach either edge.
///
/// # Members
///
/// - `.0`: index of the first live domain bit in the element
/// - `.1`: reference to the element contatining the domain
/// - `.2`: index of the first dead bit after the domain
///
/// # Invariants
///
/// - `.0` must satisfy `BitIdx::is_valid::<T>`
/// - `.1` must satisfy `BitIdx::is_valid_tail::<T>`
///
/// # Behavior
///
/// This variant is produced when the domain is contained entirely inside
/// one element, and does not reach to either edge.
Minor(BitIdx, &'a T, BitIdx),
/// Multpile element domain which does not reach the edge of its edge
/// elements.
///
/// # Members
///
/// - `.0`: index of the first live domain bit in the first element
/// - `.1`: reference to the partial head edge element
/// - `.2`: slice handle to the fully-live elements in the interior. This
/// may be empty.
/// - `.3`: reference to the partial tail edge element
/// - `.4`: index of the first dead bit after the domain
///
/// # Behavior
///
/// This variant is produced when the domain uses at least two elements, and
/// reaches neither the head edge of the head element nor the tail edge of
/// the tail element.
Major(BitIdx, &'a T, &'a [T], &'a T, BitIdx),
/// Domain with a partial head cursor and fully extended tail cursor.
///
/// # Members
///
/// - `.0`: index of the first live bit in the head element
/// - `.1`: reference to the partial head element
/// - `.2`: reference to the full elements of the domain. This may be empty.
///
/// # Behavior
///
/// This variant is produced when the domains head cursor is past `0`, and
/// its tail cursor is exactly `T::SIZE`.
PartialHead(BitIdx, &'a T, &'a [T]),
/// Domain with a fully extended head cursor and partial tail cursor.
///
/// # Members
///
/// - `.0`: reference to the full elements of the domain. This may be empty.
/// - `.1`: reference to the partial tail element
/// - `.2`: index of the first dead bit after the live bits in the tail
///
/// # Behavior
///
/// This variant is produced when the domains head cursor is exactly `0`,
/// and its tail cursor is less than `T::SIZE`.
PartialTail(&'a [T], &'a T, BitIdx),
/// Domain which fully spans its containing elements.
///
/// # Members
///
/// - `.0`: slice handle to the elements containing the domain
///
/// # Behavior
///
/// This variant is produced when the all elements in the domain are fully
/// populated.
Spanning(&'a [T]),
}
impl<'a, T> From<BitPtr<T>> for BitDomain<'a, T>
where T: 'a + Bits {
fn from(bitptr: BitPtr<T>) -> Self {
use BitDomainKind as Bdk;
let (e, h, t) = bitptr.region_data();
let data = bitptr.as_slice();
match bitptr.domain_kind() {
Bdk::Empty => BitDomain::Empty,
Bdk::Minor => BitDomain::Minor(h, &data[0], t),
Bdk::Major => BitDomain::Major(
h, &data[0], &data[1 .. e - 1], &data[e - 1], t
),
Bdk::PartialHead => BitDomain::PartialHead(
h, &data[0], &data[1 ..]
),
Bdk::PartialTail => BitDomain::PartialTail(
&data[.. e - 1], &data[e - 1], t
),
Bdk::Spanning => BitDomain::Spanning(data),
}
}
}
/// Representations of the state of the bit domain in its containing elements.
///
/// # Lifetimes
///
/// - `'a`: Lifetime of the containing storage
///
/// # Type Parameters
///
/// - `T: Bits` The type of the elements the domain inhabits.
#[derive(Debug)]
pub enum BitDomainMut<'a, T>
where T: 'a + Bits {
/// Empty domain.
Empty,
/// Single element domain which does not reach either edge.
///
/// # Members
///
/// - `.0`: index of the first live domain bit in the element
/// - `.1`: mutable reference to the element contatining the domain
/// - `.2`: index of the first dead bit after the domain
///
/// # Invariants
///
/// - `.0` must satisfy `BitIdx::is_valid::<T>`
/// - `.1` must satisfy `BitIdx::is_valid_tail::<T>`
///
/// # Behavior
///
/// This variant is produced when the domain is contained entirely inside
/// one element, and does not reach to either edge.
Minor(BitIdx, &'a mut T, BitIdx),
/// Multpile element domain which does not reach the edge of its edge
/// elements.
///
/// # Members
///
/// - `.0`: index of the first live domain bit in the first element
/// - `.1`: mutable reference to the partial head edge element
/// - `.2`: mutable slice handle to the fully-live elements in the interior.
/// This may be empty.
/// - `.3`: mutable reference to the partial tail edge element
/// - `.4`: index of the first dead bit after the domain
///
/// # Behavior
///
/// This variant is produced when the domain uses at least two elements, and
/// reaches neither the head edge of the head element nor the tail edge of
/// the tail element.
Major(BitIdx, &'a mut T, &'a mut [T], &'a mut T, BitIdx),
/// Domain with a partial head cursor and fully extended tail cursor.
///
/// # Members
///
/// - `.0`: index of the first live bit in the head element
/// - `.1`: mutable reference to the partial head element
/// - `.2`: mutable reference to the full elements of the domain. This may
/// be empty.
///
/// # Behavior
///
/// This variant is produced when the domains head cursor is past `0`, and
/// its tail cursor is exactly `T::SIZE`.
PartialHead(BitIdx, &'a mut T, &'a mut [T]),
/// Domain with a fully extended head cursor and partial tail cursor.
///
/// # Members
///
/// - `.0`: mutable reference to the full elements of the domain. This may
/// be empty.
/// - `.1`: mutable reference to the partial tail element
/// - `.2`: index of the first dead bit after the live bits in the tail
///
/// # Behavior
///
/// This variant is produced when the domains head cursor is exactly `0`,
/// and its tail cursor is less than `T::SIZE`.
PartialTail(&'a mut [T], &'a mut T, BitIdx),
/// Domain which fully spans its containing elements.
///
/// # Members
///
/// - `.0`: mutable slice handle to the elements containing the domain
///
/// # Behavior
///
/// This variant is produced when the all elements in the domain are fully
/// populated.
Spanning(&'a mut [T]),
}
impl<'a, T> From<BitPtr<T>> for BitDomainMut<'a, T>
where T: 'a + Bits {
fn from(bitptr: BitPtr<T>) -> Self {
use BitDomainKind as Bdk;
let (h, t) = bitptr.cursors();
let data = bitptr.as_mut_slice();
match bitptr.domain_kind() {
Bdk::Empty => BitDomainMut::Empty,
Bdk::Minor => BitDomainMut::Minor(h, &mut data[0], t),
Bdk::Major => {
let (head, body) = data.split_first_mut()
.expect("Major cannot fail to split head");
let (tail, body) = body.split_last_mut()
.expect("Major cannot fail to split tail");
BitDomainMut::Major(h, head, body, tail, t)
},
Bdk::PartialHead => {
let (head, tail) = data.split_first_mut()
.expect("PartialHead cannot fail to split");
BitDomainMut::PartialHead(h, head, tail)
},
Bdk::PartialTail => {
let (tail, head) = data.split_last_mut()
.expect("PartialTail cannot fail to split");
BitDomainMut::PartialTail(head, tail, t)
},
Bdk::Spanning => BitDomainMut::Spanning(data),
}
}
}
#[cfg(all(test, feature = "testing"))]
mod tests {
use super::*;
#[test]
fn minor() {
let data: u8 = 0u8;
let bp = BitPtr::new(&data, 1, 1, 6);
assert!(bp.domain_kind().is_minor());
}
#[test]
fn major() {
let data: &[u16] = &[0u16, !0u16];
let bp = BitPtr::new(&data[0], 2, 1, 12);
assert!(bp.domain_kind().is_major());
}
#[test]
fn partial_head() {
let data: u32 = 0u32;
let bp = BitPtr::new(&data, 1, 4, 32);
assert!(bp.domain_kind().is_partial_head());
let data: &[u32] = &[0u32, !0u32];
let bp = BitPtr::new(&data[0], 2, 4, 32);
assert!(bp.domain_kind().is_partial_head());
}
#[test]
fn partial_tail() {
let data: u64 = 0u64;
let bp = BitPtr::new(&data, 1, 0, 60);
assert!(bp.domain_kind().is_partial_tail());
let data: &[u64] = &[0u64, !0u64];
let bp = BitPtr::new(&data[0], 2, 0, 60);
assert!(bp.domain_kind().is_partial_tail());
}
#[test]
fn spanning() {
let data: u8 = 0u8;
let bp = BitPtr::new(&data, 1, 0, 8);
assert!(bp.domain_kind().is_spanning());
let data: &[u16] = &[0u16, !0u16];
let bp = BitPtr::new(&data[0], 2, 0, 16);
assert!(bp.domain_kind().is_spanning());
}
}

View File

@ -1,82 +0,0 @@
/*! `bitvec` `[bool]` in overdrive.
This crate provides views into slices of bits that are truly `[u1]`. Each bit in
the data segment is used, unlike `[bool]` which ignores seven bits out of every
byte.
`bitvec`s data structures provide strong guarantees about, and fine-grained
control of, the bit-level representation of a sequence of memory. The user is
empowered to choose the fundamental type underlying the store `u8`, `u16`,
`u32`, or `u64` and the order in which each primitive is traversed
big-endian, from the most significant bit to the least, or little-endian, from
the least significant bit to the most.
This level of control is not necessary for most use cases where users just want
to put bits in a sequence, but it is critically important for users making
packets that leave main memory and hit some external device like a peripheral
controller or a network socket. In order to provide convencienc to users for
whom the storage details do not matter, `bitvec` types default to using
big-endian bit order on `u8`. This means that the bits you would write down on
paper match up with the bits as they are stored in memory.
For example, the bit sequence `[0, 1, 1, 0, 1, 0, 0, 1]` inserted into `bitvec`
structures with no extra type specification will produce the `<BigEndian, u8>`
variant, so the bits in memory are `0b01101001`. With little-endian bit order,
the memory value would be `0b10010110` (reversed order!).
In addition to providing compact, efficient, and powerful storage and
manipulation of bits in memory, the `bitvec` structures are capable of acting as
a queue, set, or stream of bits. They implement the bit-wise operators for
Boolean arithmetic, arithmetic operators for 2s-complement numeric arithmetic,
read indexing, bit shifts, and access to the underlying storage fundamental
elements as a slice.
(Write indexing is impossible in Rust semantics.)
!*/
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(all(feature = "alloc", not(feature = "std")), feature(alloc))]
#[cfg(all(feature = "alloc", not(feature = "std")))]
extern crate alloc;
#[cfg(feature = "std")]
extern crate core;
#[cfg(feature = "serdes")]
extern crate serde;
#[cfg(all(test, feature = "serdes"))]
extern crate serde_test;
#[macro_use]
mod macros;
pub mod bits;
pub mod cursor;
mod domain;
mod pointer;
pub mod prelude;
pub mod slice;
#[cfg(feature = "alloc")]
pub mod boxed;
#[cfg(feature = "alloc")]
pub mod vec;
#[cfg(all(feature = "serdes"))]
mod serdes;
/// Expose crate internals for use in doctests and external tests.
#[cfg(feature = "testing")]
pub mod testing {
pub use crate::{
bits::*,
domain::*,
macros::*,
pointer::*,
slice::*,
vec::*,
};
}

View File

@ -1,211 +0,0 @@
/*! Utility macros for constructing data structures and implementing bulk types.
The only public macro is `bitvec`; this module also provides convenience macros
for code generation.
!*/
/** Construct a `BitVec` out of a literal array in source code, like `vec!`.
`bitvec!` can be invoked in a number of ways. It takes the name of a `Cursor`
implementation, the name of a `Bits`-implementing fundamental, and zero or more
fundamentals (integer, floating-point, or boolean) which are used to build the
bits. Each fundamental literal corresponds to one bit, and is considered to
represent `1` if it is any other value than exactly zero.
`bitvec!` can be invoked with no specifiers, a `Cursor` specifier, or a `Cursor`
and a `Bits` specifier. It cannot be invoked with a `Bits` specifier but no
`Cursor` specifier, due to overlap in how those tokens are matched by the macro
system.
Like `vec!`, `bitvec!` supports bit lists `[0, 1, ]` and repetition markers
`[1; n]`.
# All Syntaxes
```rust
use bitvec::prelude::*;
bitvec![BigEndian, u8; 0, 1];
bitvec![LittleEndian, u8; 0, 1,];
bitvec![BigEndian; 0, 1];
bitvec![LittleEndian; 0, 1,];
bitvec![0, 1];
bitvec![0, 1,];
bitvec![BigEndian, u8; 1; 5];
bitvec![LittleEndian; 0; 5];
bitvec![1; 5];
```
**/
#[cfg(feature = "alloc")]
#[macro_export]
macro_rules! bitvec {
// bitvec![ endian , type ; 0 , 1 , … ]
( $endian:path , $bits:ty ; $( $element:expr ),* ) => {
bitvec![ __bv_impl__ $endian , $bits ; $( $element ),* ]
};
// bitvec![ endian , type ; 0 , 1 , … , ]
( $endian:path , $bits:ty ; $( $element:expr , )* ) => {
bitvec![ __bv_impl__ $endian , $bits ; $( $element ),* ]
};
// bitvec![ endian ; 0 , 1 , … ]
( $endian:path ; $( $element:expr ),* ) => {
bitvec![ __bv_impl__ $endian , u8 ; $( $element ),* ]
};
// bitvec![ endian ; 0 , 1 , … , ]
( $endian:path ; $( $element:expr , )* ) => {
bitvec![ __bv_impl__ $endian , u8 ; $( $element ),* ]
};
// bitvec![ 0 , 1 , … ]
( $( $element:expr ),* ) => {
bitvec![ __bv_impl__ $crate::prelude::BigEndian , u8 ; $( $element ),* ]
};
// bitvec![ 0 , 1 , … , ]
( $( $element:expr , )* ) => {
bitvec![ __bv_impl__ $crate::prelude::BigEndian , u8 ; $( $element ),* ]
};
// bitvec![ endian , type ; bit ; rep ]
( $endian:path , $bits:ty ; $element:expr ; $rep:expr ) => {
bitvec![ __bv_impl__ $endian , $bits ; $element; $rep ]
};
// bitvec![ endian ; bit ; rep ]
( $endian:path ; $element:expr ; $rep:expr ) => {
bitvec![ __bv_impl__ $endian , u8 ; $element ; $rep ]
};
// bitvec![ bit ; rep ]
( $element:expr ; $rep:expr ) => {
bitvec![ __bv_impl__ $crate::prelude::BigEndian , u8 ; $element ; $rep ]
};
// Build an array of `bool` (one bit per byte) and then build a `BitVec`
// from that (one bit per bit). I have yet to think of a way to make the
// source array be binary-compatible with a `BitSlice` data representation,
// so the static source is 8x larger than it needs to be.
//
// Im sure there is a way, but I dont think I need to spend the effort
// yet. Maybe a proc-macro.
( __bv_impl__ $endian:path , $bits:ty ; $( $element:expr ),* ) => {{
let init: &[bool] = &[ $( $element != 0 ),* ];
$crate :: vec :: BitVec :: < $endian , $bits > :: from ( init )
}};
( __bv_impl__ $endian:path , $bits:ty ; $element:expr ; $rep:expr ) => {{
core :: iter :: repeat ( $element != 0 )
.take ( $rep )
.collect :: < $crate :: vec :: BitVec < $endian , $bits > > ( )
}};
}
#[doc(hidden)]
macro_rules! __bitslice_shift {
( $( $t:ty ),+ ) => { $(
#[doc(hidden)]
impl < C , T > core :: ops :: ShlAssign< $t >
for $crate :: prelude :: BitSlice<C, T>
where C : $crate :: cursor :: Cursor , T : $crate :: bits :: Bits
{
fn shl_assign(&mut self, shamt: $t ) {
core :: ops :: ShlAssign::<usize>::shl_assign(self, shamt as usize);
}
}
#[doc(hidden)]
impl < C , T > core :: ops :: ShrAssign< $t >
for $crate :: prelude :: BitSlice<C, T>
where C : $crate :: cursor :: Cursor , T : $crate :: bits :: Bits
{
fn shr_assign(&mut self, shamt: $t ) {
core :: ops :: ShrAssign::<usize>::shr_assign(self, shamt as usize);
}
}
)+ };
}
#[cfg(feature = "alloc")]
#[doc(hidden)]
macro_rules! __bitvec_shift {
( $( $t:ty ),+ ) => { $(
#[doc(hidden)]
impl < C , T > core :: ops :: Shl< $t >
for $crate :: vec :: BitVec < C , T >
where C : $crate :: cursor :: Cursor , T : $crate :: bits :: Bits
{
type Output = <Self as core :: ops :: Shl<usize>>::Output;
fn shl(self, shamt: $t ) -> Self :: Output {
core :: ops :: Shl::<usize>::shl(self, shamt as usize)
}
}
#[doc(hidden)]
impl < C , T > core :: ops :: ShlAssign< $t >
for $crate :: vec :: BitVec < C , T >
where C : $crate :: cursor :: Cursor , T : $crate :: bits :: Bits
{
fn shl_assign(&mut self, shamt: $t ) {
core :: ops :: ShlAssign::<usize>::shl_assign(self, shamt as usize)
}
}
#[doc(hidden)]
impl < C , T > core :: ops :: Shr< $t >
for $crate :: vec :: BitVec < C , T >
where C : $crate :: cursor :: Cursor , T : $crate :: bits :: Bits
{
type Output = <Self as core :: ops :: Shr<usize>>::Output;
fn shr(self, shamt: $t ) -> Self :: Output {
core :: ops :: Shr::<usize>::shr(self, shamt as usize)
}
}
#[doc(hidden)]
impl < C , T> core :: ops :: ShrAssign< $t >
for $crate :: vec :: BitVec < C , T >
where C : $crate :: cursor :: Cursor , T : $crate :: bits :: Bits
{
fn shr_assign(&mut self, shamt: $t ) {
core :: ops :: ShrAssign::<usize>::shr_assign(self, shamt as usize)
}
}
)+ };
}
#[cfg(all(test, feature = "alloc"))]
mod tests {
#[allow(unused_imports)]
use crate::cursor::{
BigEndian,
LittleEndian,
};
#[test]
fn compile_macros() {
bitvec![0, 1];
bitvec![BigEndian; 0, 1];
bitvec![LittleEndian; 0, 1];
bitvec![BigEndian, u8; 0, 1];
bitvec![LittleEndian, u8; 0, 1];
bitvec![BigEndian, u16; 0, 1];
bitvec![LittleEndian, u16; 0, 1];
bitvec![BigEndian, u32; 0, 1];
bitvec![LittleEndian, u32; 0, 1];
bitvec![BigEndian, u64; 0, 1];
bitvec![LittleEndian, u64; 0, 1];
bitvec![1; 70];
bitvec![BigEndian; 0; 70];
bitvec![LittleEndian; 1; 70];
bitvec![BigEndian, u8; 0; 70];
bitvec![LittleEndian, u8; 1; 70];
bitvec![BigEndian, u16; 0; 70];
bitvec![LittleEndian, u16; 1; 70];
bitvec![BigEndian, u32; 0; 70];
bitvec![LittleEndian, u32; 1; 70];
bitvec![BigEndian, u64; 0; 70];
bitvec![LittleEndian, u64; 1; 70];
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,20 +0,0 @@
/*! `bitvec` Prelude
!*/
pub use crate::{
bitvec,
bits::Bits,
cursor::{
Cursor,
BigEndian,
LittleEndian,
},
slice::BitSlice,
};
#[cfg(feature = "alloc")]
pub use crate::{
boxed::BitBox,
vec::BitVec,
};

View File

@ -1,266 +0,0 @@
/*! `serde`-powered de/serialization
!*/
#![cfg(all(feature = "serdes"))]
use crate::{
bits::Bits,
cursor::Cursor,
pointer::BitPtr,
slice::BitSlice,
};
#[cfg(feature = "alloc")]
use crate::{
boxed::BitBox,
vec::BitVec,
};
use core::{
cmp,
fmt::{
self,
Formatter,
},
marker::PhantomData,
mem,
};
use serde::{
Serialize,
ser::{
Serializer,
SerializeStruct,
},
};
#[cfg(feature = "alloc")]
use serde::{
Deserialize,
de::{
self,
Deserializer,
MapAccess,
SeqAccess,
Visitor,
},
};
/// A Serde visitor to pull `BitBox` data out of a serialized stream
#[cfg(feature = "alloc")]
#[derive(Clone, Copy, Default, Debug)]
pub struct BitBoxVisitor<'de, C, T>
where C: Cursor, T: Bits + Deserialize<'de> {
_cursor: PhantomData<C>,
_storage: PhantomData<&'de T>,
}
#[cfg(feature = "alloc")]
impl<'de, C, T> BitBoxVisitor<'de, C, T>
where C: Cursor, T: Bits + Deserialize<'de> {
fn new() -> Self {
BitBoxVisitor { _cursor: PhantomData, _storage: PhantomData }
}
}
#[cfg(feature = "alloc")]
impl<'de, C, T> Visitor<'de> for BitBoxVisitor<'de, C, T>
where C: Cursor, T: Bits + Deserialize<'de> {
type Value = BitBox<C, T>;
fn expecting(&self, fmt: &mut Formatter) -> fmt::Result {
fmt.write_str("A BitSet data series")
}
/// Visit a sequence of anonymous data elements. These must be in the order
/// `usize', `u8`, `u8`, `[T]`.
fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
where V: SeqAccess<'de> {
let elts: usize = seq.next_element()?
.ok_or_else(|| de::Error::invalid_length(0, &self))?;
let head: u8 = seq.next_element()?
.ok_or_else(|| de::Error::invalid_length(1, &self))?;
let tail: u8 = seq.next_element()?
.ok_or_else(|| de::Error::invalid_length(2, &self))?;
let data: Box<[T]> = seq.next_element()?
.ok_or_else(|| de::Error::invalid_length(3, &self))?;
let bitptr = BitPtr::new(data.as_ptr(), cmp::min(elts, data.len()), head, tail);
mem::forget(data);
Ok(unsafe { BitBox::from_raw(bitptr) })
}
/// Visit a map of named data elements. These may be in any order, and must
/// be the pairs `elts: usize`, `head: u8`, `tail: u8`, and `data: [T]`.
fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
where V: MapAccess<'de> {
let mut elts: Option<usize> = None;
let mut head: Option<u8> = None;
let mut tail: Option<u8> = None;
let mut data: Option<Box<[T]>> = None;
while let Some(key) = map.next_key()? {
match key {
"elts" => if elts.replace(map.next_value()?).is_some() {
return Err(de::Error::duplicate_field("elts"));
},
"head" => if head.replace(map.next_value()?).is_some() {
return Err(de::Error::duplicate_field("head"));
},
"tail" => if tail.replace(map.next_value()?).is_some() {
return Err(de::Error::duplicate_field("tail"));
},
"data" => if data.replace(map.next_value()?).is_some() {
return Err(de::Error::duplicate_field("data"));
},
f => return Err(de::Error::unknown_field(
f, &["elts", "head", "tail", "data"]
)),
}
}
let elts = elts.ok_or_else(|| de::Error::missing_field("elts"))?;
let head = head.ok_or_else(|| de::Error::missing_field("head"))?;
let tail = tail.ok_or_else(|| de::Error::missing_field("tail"))?;
let data = data.ok_or_else(|| de::Error::missing_field("data"))?;
let bitptr = BitPtr::new(
data.as_ptr(),
cmp::min(elts as usize, data.len()),
head,
tail,
);
mem::forget(data);
Ok(unsafe { BitBox::from_raw(bitptr) })
}
}
#[cfg(feature = "alloc")]
impl<'de, C, T> Deserialize<'de> for BitBox<C, T>
where C: Cursor, T: 'de + Bits + Deserialize<'de> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de> {
deserializer.deserialize_struct("BitSet", &[
"elts", "head", "tail", "data",
], BitBoxVisitor::new())
}
}
#[cfg(feature = "alloc")]
impl<'de, C, T> Deserialize<'de> for BitVec<C, T>
where C: Cursor, T: 'de + Bits + Deserialize<'de> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de> {
BitBox::deserialize(deserializer).map(Into::into)
}
}
impl<C, T> Serialize for BitSlice<C, T>
where C: Cursor, T: Bits + Serialize {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer {
let (e, h, t) = self.bitptr().region_data();
let mut state = serializer.serialize_struct("BitSet", 4)?;
state.serialize_field("elts", &(e as u64))?;
state.serialize_field("head", &*h)?;
state.serialize_field("tail", &*t)?;
state.serialize_field("data", self.as_ref())?;
state.end()
}
}
#[cfg(feature = "alloc")]
impl<C, T> Serialize for BitBox<C, T>
where C: Cursor, T: Bits + Serialize {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer {
BitSlice::serialize(&*self, serializer)
}
}
#[cfg(feature = "alloc")]
impl<C, T> Serialize for BitVec<C, T>
where C: Cursor, T: Bits + Serialize {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer {
BitSlice::serialize(&*self, serializer)
}
}
#[cfg(test)]
mod tests {
use crate::prelude::*;
use serde_test::{
Token,
assert_de_tokens,
assert_ser_tokens,
assert_tokens,
};
macro_rules! bvtok {
( s $elts:expr, $head:expr, $tail:expr, $len:expr, $ty:ident $( , $data:expr )* ) => {
&[
Token::Struct { name: "BitSet", len: 4, },
Token::Str("elts"), Token::U64( $elts ),
Token::Str("head"), Token::U8( $head ),
Token::Str("tail"), Token::U8( $tail ),
Token::Str("data"), Token::Seq { len: Some( $len ) },
$( Token:: $ty ( $data ), )*
Token::SeqEnd,
Token::StructEnd,
]
};
( d $elts:expr, $head:expr, $tail:expr, $len:expr, $ty:ident $( , $data:expr )* ) => {
&[
Token::Struct { name: "BitSet", len: 4, },
Token::BorrowedStr("elts"), Token::U64( $elts ),
Token::BorrowedStr("head"), Token::U8( $head ),
Token::BorrowedStr("tail"), Token::U8( $tail ),
Token::BorrowedStr("data"), Token::Seq { len: Some( $len ) },
$( Token:: $ty ( $data ), )*
Token::SeqEnd,
Token::StructEnd,
]
};
}
#[test]
fn empty() {
let slice = BitSlice::<BigEndian, u8>::empty();
// TODO(myrrlyn): Refactor BitPtr impl so the empty slice is 0/0
assert_ser_tokens(&slice, bvtok![s 0, 0, 8, 0, U8]);
assert_de_tokens(&bitvec![], bvtok![ d 0, 0, 8, 0, U8 ]);
}
#[test]
fn small() {
let bv = bitvec![1; 5];
eprintln!("made vec");
let bs = &bv[1 ..];
assert_ser_tokens(&bs, bvtok![s 1, 1, 5, 1, U8, 0b1111_1000]);
let bv = bitvec![LittleEndian, u16; 1; 12];
assert_ser_tokens(&bv, bvtok![s 1, 0, 12, 1, U16, 0b00001111_11111111]);
let bb: BitBox<_, _> = bitvec![LittleEndian, u32; 1; 10].into();
assert_ser_tokens(&bb, bvtok![s 1, 0, 10, 1, U32, 0x00_00_03_FF]);
}
#[test]
fn wide() {
let src: &[u8] = &[0, !0];
let bs: &BitSlice = src.into();
assert_ser_tokens(&(&bs[1 .. 15]), bvtok![s 2, 1, 7, 2, U8, 0, !0]);
}
#[test]
fn deser() {
let bv = bitvec![0, 1, 1, 0, 1, 0];
assert_de_tokens(&bv, bvtok![d 1, 0, 6, 1, U8, 0b0110_1000]);
// test that the bits outside the bits domain don't matter in deser
assert_de_tokens(&bv, bvtok![d 1, 0, 6, 1, U8, 0b0110_1010]);
assert_de_tokens(&bv, bvtok![d 1, 0, 6, 1, U8, 0b0110_1001]);
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1 +1 @@
{"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"}
{"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"}

View File

@ -1,46 +1,3 @@
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,

View File

@ -12,9 +12,8 @@
[package]
name = "byteorder"
version = "1.3.1"
version = "1.2.7"
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"
@ -31,11 +30,11 @@ opt-level = 3
name = "byteorder"
bench = false
[dev-dependencies.quickcheck]
version = "0.8"
version = "0.7"
default-features = false
[dev-dependencies.rand]
version = "0.6"
version = "0.5"
[features]
default = ["std"]

View File

@ -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(byteorder_i128)]
#[cfg(feature = "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(byteorder_i128)]
#[cfg(feature = "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(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(uint128_1, read_uint128,
1, [1]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(uint128_2, read_uint128,
2, [1, 2]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(uint128_3, read_uint128,
3, [1, 2, 3]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(uint128_4, read_uint128,
4, [1, 2, 3, 4]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(uint128_5, read_uint128,
5, [1, 2, 3, 4, 5]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(uint128_6, read_uint128,
6, [1, 2, 3, 4, 5, 6]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(uint128_7, read_uint128,
7, [1, 2, 3, 4, 5, 6, 7]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(uint128_8, read_uint128,
8, [1, 2, 3, 4, 5, 6, 7, 8]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(uint128_9, read_uint128,
9, [1, 2, 3, 4, 5, 6, 7, 8, 9]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(uint128_10, read_uint128,
10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(uint128_11, read_uint128,
11, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(uint128_12, read_uint128,
12, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(uint128_13, read_uint128,
13, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(uint128_14, read_uint128,
14, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(uint128_15, read_uint128,
15, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
#[cfg(byteorder_i128)]
#[cfg(feature = "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(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(int128_1, read_int128,
1, [1]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(int128_2, read_int128,
2, [1, 2]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(int128_3, read_int128,
3, [1, 2, 3]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(int128_4, read_int128,
4, [1, 2, 3, 4]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(int128_5, read_int128,
5, [1, 2, 3, 4, 5]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(int128_6, read_int128,
6, [1, 2, 3, 4, 5, 6]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(int128_7, read_int128,
7, [1, 2, 3, 4, 5, 6, 7]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(int128_8, read_int128,
8, [1, 2, 3, 4, 5, 6, 7, 8]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(int128_9, read_int128,
9, [1, 2, 3, 4, 5, 6, 7, 8, 9]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(int128_10, read_int128,
10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(int128_11, read_int128,
11, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(int128_12, read_int128,
12, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(int128_13, read_int128,
13, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(int128_14, read_int128,
14, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(int128_15, read_int128,
15, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
bench_num!(int128_16, read_int128,
16, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);

View File

@ -1,87 +0,0 @@
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 })
}
}

View File

@ -370,7 +370,7 @@ pub trait ReadBytesExt: io::Read {
/// ]);
/// assert_eq!(16947640962301618749969007319746179, rdr.read_u128::<BigEndian>().unwrap());
/// ```
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
#[inline]
fn read_u128<T: ByteOrder>(&mut self) -> Result<u128> {
let mut buf = [0; 16];
@ -391,13 +391,14 @@ 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(byteorder_i128)]
#[cfg(feature = "i128")]
#[inline]
fn read_i128<T: ByteOrder>(&mut self) -> Result<i128> {
let mut buf = [0; 16];
@ -456,7 +457,7 @@ pub trait ReadBytesExt: io::Read {
}
/// Reads an unsigned n-bytes integer from the underlying reader.
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
#[inline]
fn read_uint128<T: ByteOrder>(&mut self, nbytes: usize) -> Result<u128> {
let mut buf = [0; 16];
@ -465,7 +466,7 @@ pub trait ReadBytesExt: io::Read {
}
/// Reads a signed n-bytes integer from the underlying reader.
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
#[inline]
fn read_int128<T: ByteOrder>(&mut self, nbytes: usize) -> Result<i128> {
let mut buf = [0; 16];
@ -671,7 +672,7 @@ pub trait ReadBytesExt: io::Read {
/// rdr.read_u128_into::<BigEndian>(&mut dst).unwrap();
/// assert_eq!([517, 768], dst);
/// ```
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
#[inline]
fn read_u128_into<T: ByteOrder>(
&mut self,
@ -821,7 +822,7 @@ pub trait ReadBytesExt: io::Read {
/// rdr.read_i128_into::<BigEndian>(&mut dst).unwrap();
/// assert_eq!([517, 768], dst);
/// ```
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
#[inline]
fn read_i128_into<T: ByteOrder>(
&mut self,
@ -1372,7 +1373,7 @@ pub trait WriteBytesExt: io::Write {
}
/// Writes an unsigned 128 bit integer to the underlying writer.
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
#[inline]
fn write_u128<T: ByteOrder>(&mut self, n: u128) -> Result<()> {
let mut buf = [0; 16];
@ -1381,7 +1382,7 @@ pub trait WriteBytesExt: io::Write {
}
/// Writes a signed 128 bit integer to the underlying writer.
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
#[inline]
fn write_i128<T: ByteOrder>(&mut self, n: i128) -> Result<()> {
let mut buf = [0; 16];
@ -1465,7 +1466,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(byteorder_i128)]
#[cfg(feature = "i128")]
#[inline]
fn write_uint128<T: ByteOrder>(
&mut self,
@ -1481,7 +1482,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(byteorder_i128)]
#[cfg(feature = "i128")]
#[inline]
fn write_int128<T: ByteOrder>(
&mut self,

View File

@ -84,7 +84,7 @@ fn extend_sign(val: u64, nbytes: usize) -> i64 {
(val << shift) as i64 >> shift
}
#[cfg(byteorder_i128)]
#[cfg(feature = "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(byteorder_i128)]
#[cfg(feature = "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(byteorder_i128)]
#[cfg(feature = "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(byteorder_i128)]
#[cfg(feature = "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(byteorder_i128)]
#[cfg(feature = "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(byteorder_i128)]
#[cfg(feature = "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(byteorder_i128)]
#[cfg(feature = "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(byteorder_i128)]
#[cfg(feature = "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(byteorder_i128)]
#[cfg(feature = "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(byteorder_i128)]
#[cfg(feature = "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(byteorder_i128)]
#[cfg(feature = "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(byteorder_i128)]
#[cfg(feature = "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(byteorder_i128)]
#[cfg(feature = "i128")]
#[inline]
fn read_i128_into(src: &[u8], dst: &mut [i128]) {
let dst = unsafe {
@ -1197,40 +1197,7 @@ pub trait ByteOrder
/// 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];
/// 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];
/// let numbers_given = [1.0, 2.0, 31.312e311, -11.32e91];
/// LittleEndian::write_f32_into(&numbers_given, &mut bytes);
///
/// let mut numbers_got = [0.0; 4];
@ -1238,45 +1205,13 @@ 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]) {
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())
slice::from_raw_parts_mut(dst.as_mut_ptr() as *mut u32, dst.len())
};
Self::read_u64_into(src, dst);
Self::read_u32_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`.
///
@ -1300,9 +1235,11 @@ 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]) {
Self::read_f64_into(src, dst);
let dst = unsafe {
slice::from_raw_parts_mut(dst.as_mut_ptr() as *mut u64, dst.len())
};
Self::read_u64_into(src, dst);
}
/// Writes unsigned 16 bit integers from `src` into `dst`.
@ -1395,7 +1332,7 @@ pub trait ByteOrder
/// LittleEndian::read_u128_into(&bytes, &mut numbers_got);
/// assert_eq!(numbers_given, numbers_got);
/// ```
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
fn write_u128_into(src: &[u128], dst: &mut [u8]);
/// Writes signed 16 bit integers from `src` into `dst`.
@ -1503,7 +1440,7 @@ pub trait ByteOrder
/// LittleEndian::read_i128_into(&bytes, &mut numbers_got);
/// assert_eq!(numbers_given, numbers_got);
/// ```
#[cfg(byteorder_i128)]
#[cfg(feature = "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())
@ -1526,12 +1463,12 @@ pub trait ByteOrder
/// use byteorder::{ByteOrder, LittleEndian};
///
/// let mut bytes = [0; 16];
/// let numbers_given = [1.0, 2.0, 31.312e31, -11.32e19];
/// let numbers_given = [1.0, 2.0, 31.312e311, -11.32e91];
/// LittleEndian::write_f32_into(&numbers_given, &mut bytes);
///
/// let mut numbers_got = [0.0; 4];
/// unsafe {
/// LittleEndian::read_f32_into(&bytes, &mut numbers_got);
/// LittleEndian::read_f32_into_unchecked(&bytes, &mut numbers_got);
/// }
/// assert_eq!(numbers_given, numbers_got);
/// ```
@ -1562,7 +1499,7 @@ pub trait ByteOrder
///
/// let mut numbers_got = [0.0; 4];
/// unsafe {
/// LittleEndian::read_f64_into(&bytes, &mut numbers_got);
/// LittleEndian::read_f64_into_unchecked(&bytes, &mut numbers_got);
/// }
/// assert_eq!(numbers_given, numbers_got);
/// ```
@ -1647,7 +1584,7 @@ pub trait ByteOrder
/// BigEndian::from_slice_u128(&mut numbers);
/// assert_eq!(numbers, [5u128.to_be(), 65000u128.to_be()]);
/// ```
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
fn from_slice_u128(numbers: &mut [u128]);
/// Converts the given slice of signed 16 bit integers to a particular
@ -1742,7 +1679,7 @@ pub trait ByteOrder
/// BigEndian::from_slice_i128(&mut numbers);
/// assert_eq!(numbers, [5i128.to_be(), 65000i128.to_be()]);
/// ```
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
#[inline]
fn from_slice_i128(src: &mut [i128]) {
let src = unsafe {
@ -1957,7 +1894,7 @@ impl ByteOrder for BigEndian {
read_num_bytes!(u64, 8, buf, to_be)
}
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
#[inline]
fn read_u128(buf: &[u8]) -> u128 {
read_num_bytes!(u128, 16, buf, to_be)
@ -1975,7 +1912,7 @@ impl ByteOrder for BigEndian {
}
}
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
#[inline]
fn read_uint128(buf: &[u8], nbytes: usize) -> u128 {
assert!(1 <= nbytes && nbytes <= 16 && nbytes <= buf.len());
@ -2003,7 +1940,7 @@ impl ByteOrder for BigEndian {
write_num_bytes!(u64, 8, n, buf, to_be);
}
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
#[inline]
fn write_u128(buf: &mut [u8], n: u128) {
write_num_bytes!(u128, 16, n, buf, to_be);
@ -2022,7 +1959,7 @@ impl ByteOrder for BigEndian {
}
}
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
#[inline]
fn write_uint128(buf: &mut [u8], n: u128, nbytes: usize) {
assert!(pack_size128(n) <= nbytes && nbytes <= 16);
@ -2051,7 +1988,7 @@ impl ByteOrder for BigEndian {
read_slice!(src, dst, 8, to_be);
}
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
#[inline]
fn read_u128_into(src: &[u8], dst: &mut [u128]) {
read_slice!(src, dst, 16, to_be);
@ -2084,7 +2021,7 @@ impl ByteOrder for BigEndian {
}
}
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
#[inline]
fn write_u128_into(src: &[u128], dst: &mut [u8]) {
if cfg!(target_endian = "big") {
@ -2121,7 +2058,7 @@ impl ByteOrder for BigEndian {
}
}
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
#[inline]
fn from_slice_u128(numbers: &mut [u128]) {
if cfg!(target_endian = "little") {
@ -2172,7 +2109,7 @@ impl ByteOrder for LittleEndian {
read_num_bytes!(u64, 8, buf, to_le)
}
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
#[inline]
fn read_u128(buf: &[u8]) -> u128 {
read_num_bytes!(u128, 16, buf, to_le)
@ -2189,7 +2126,7 @@ impl ByteOrder for LittleEndian {
}
}
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
#[inline]
fn read_uint128(buf: &[u8], nbytes: usize) -> u128 {
assert!(1 <= nbytes && nbytes <= 16 && nbytes <= buf.len());
@ -2216,7 +2153,7 @@ impl ByteOrder for LittleEndian {
write_num_bytes!(u64, 8, n, buf, to_le);
}
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
#[inline]
fn write_u128(buf: &mut [u8], n: u128) {
write_num_bytes!(u128, 16, n, buf, to_le);
@ -2232,7 +2169,7 @@ impl ByteOrder for LittleEndian {
}
}
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
#[inline]
fn write_uint128(buf: &mut [u8], n: u128, nbytes: usize) {
assert!(pack_size128(n as u128) <= nbytes && nbytes <= 16);
@ -2258,7 +2195,7 @@ impl ByteOrder for LittleEndian {
read_slice!(src, dst, 8, to_le);
}
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
#[inline]
fn read_u128_into(src: &[u8], dst: &mut [u128]) {
read_slice!(src, dst, 16, to_le);
@ -2291,7 +2228,7 @@ impl ByteOrder for LittleEndian {
}
}
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
#[inline]
fn write_u128_into(src: &[u128], dst: &mut [u8]) {
if cfg!(target_endian = "little") {
@ -2328,7 +2265,7 @@ impl ByteOrder for LittleEndian {
}
}
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
#[inline]
fn from_slice_u128(numbers: &mut [u128]) {
if cfg!(target_endian = "big") {
@ -2369,11 +2306,8 @@ mod test {
extern crate rand;
use self::quickcheck::{QuickCheck, StdGen, Testable};
use self::rand::thread_rng;
#[cfg(byteorder_i128)]
use self::rand::Rng;
#[cfg(byteorder_i128)]
use self::quickcheck::{Arbitrary, Gen};
use self::rand::{Rng, thread_rng};
#[cfg(feature = "i128")] use self::quickcheck::{Arbitrary, Gen};
pub const U24_MAX: u32 = 16_777_215;
pub const I24_MAX: i32 = 8_388_607;
@ -2393,7 +2327,7 @@ mod test {
#[derive(Clone, Debug)]
pub struct Wi128<T>(pub T);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
impl<T: Clone> Wi128<T> {
pub fn clone(&self) -> T {
self.0.clone()
@ -2406,7 +2340,7 @@ mod test {
}
}
#[cfg(byteorder_i128)]
#[cfg(feature = "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);
@ -2417,7 +2351,7 @@ mod test {
}
}
#[cfg(byteorder_i128)]
#[cfg(feature = "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);
@ -2530,9 +2464,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(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_u128, Wi128<u128>, 16 + 1, read_u128, write_u128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_i128, Wi128<i128>, 16 + 1, read_i128, write_i128);
qc_byte_order!(prop_uint_1,
@ -2552,52 +2486,52 @@ mod test {
qc_byte_order!(prop_uint_8,
u64, calc_max!(super::U64_MAX, 8), 8, read_uint, write_uint);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_uint128_1,
Wi128<u128>, 1, 1, read_uint128, write_uint128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_uint128_2,
Wi128<u128>, 2, 2, read_uint128, write_uint128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_uint128_3,
Wi128<u128>, 3, 3, read_uint128, write_uint128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_uint128_4,
Wi128<u128>, 4, 4, read_uint128, write_uint128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_uint128_5,
Wi128<u128>, 5, 5, read_uint128, write_uint128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_uint128_6,
Wi128<u128>, 6, 6, read_uint128, write_uint128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_uint128_7,
Wi128<u128>, 7, 7, read_uint128, write_uint128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_uint128_8,
Wi128<u128>, 8, 8, read_uint128, write_uint128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_uint128_9,
Wi128<u128>, 9, 9, read_uint128, write_uint128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_uint128_10,
Wi128<u128>, 10, 10, read_uint128, write_uint128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_uint128_11,
Wi128<u128>, 11, 11, read_uint128, write_uint128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_uint128_12,
Wi128<u128>, 12, 12, read_uint128, write_uint128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_uint128_13,
Wi128<u128>, 13, 13, read_uint128, write_uint128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_uint128_14,
Wi128<u128>, 14, 14, read_uint128, write_uint128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_uint128_15,
Wi128<u128>, 15, 15, read_uint128, write_uint128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_uint128_16,
Wi128<u128>, 16, 16, read_uint128, write_uint128);
@ -2618,52 +2552,52 @@ mod test {
qc_byte_order!(prop_int_8,
i64, calc_max!(super::I64_MAX, 8), 8, read_int, write_int);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_int128_1,
Wi128<i128>, 1, 1, read_int128, write_int128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_int128_2,
Wi128<i128>, 2, 2, read_int128, write_int128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_int128_3,
Wi128<i128>, 3, 3, read_int128, write_int128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_int128_4,
Wi128<i128>, 4, 4, read_int128, write_int128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_int128_5,
Wi128<i128>, 5, 5, read_int128, write_int128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_int128_6,
Wi128<i128>, 6, 6, read_int128, write_int128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_int128_7,
Wi128<i128>, 7, 7, read_int128, write_int128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_int128_8,
Wi128<i128>, 8, 8, read_int128, write_int128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_int128_9,
Wi128<i128>, 9, 9, read_int128, write_int128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_int128_10,
Wi128<i128>, 10, 10, read_int128, write_int128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_int128_11,
Wi128<i128>, 11, 11, read_int128, write_int128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_int128_12,
Wi128<i128>, 12, 12, read_int128, write_int128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_int128_13,
Wi128<i128>, 13, 13, read_int128, write_int128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_int128_14,
Wi128<i128>, 14, 14, read_int128, write_int128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_int128_15,
Wi128<i128>, 15, 15, read_int128, write_int128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_byte_order!(prop_int128_16,
Wi128<i128>, 16, 16, read_int128, write_int128);
@ -2758,9 +2692,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(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_u128, 15, 0, read_u128, write_u128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_i128, 15, 0, read_i128, write_i128);
too_small!(small_uint_1, 1, read_uint);
@ -2771,35 +2705,35 @@ mod test {
too_small!(small_uint_6, 6, read_uint);
too_small!(small_uint_7, 7, read_uint);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_uint128_1, 1, read_uint128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_uint128_2, 2, read_uint128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_uint128_3, 3, read_uint128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_uint128_4, 4, read_uint128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_uint128_5, 5, read_uint128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_uint128_6, 6, read_uint128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_uint128_7, 7, read_uint128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_uint128_8, 8, read_uint128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_uint128_9, 9, read_uint128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_uint128_10, 10, read_uint128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_uint128_11, 11, read_uint128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_uint128_12, 12, read_uint128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_uint128_13, 13, read_uint128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_uint128_14, 14, read_uint128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_uint128_15, 15, read_uint128);
too_small!(small_int_1, 1, read_int);
@ -2810,35 +2744,35 @@ mod test {
too_small!(small_int_6, 6, read_int);
too_small!(small_int_7, 7, read_int);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_int128_1, 1, read_int128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_int128_2, 2, read_int128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_int128_3, 3, read_int128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_int128_4, 4, read_int128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_int128_5, 5, read_int128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_int128_6, 6, read_int128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_int128_7, 7, read_int128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_int128_8, 8, read_int128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_int128_9, 9, read_int128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_int128_10, 10, read_int128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_int128_11, 11, read_int128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_int128_12, 12, read_int128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_int128_13, 13, read_int128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_int128_14, 14, read_int128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
too_small!(small_int128_15, 15, read_int128);
// Test that reading/writing slices enforces the correct lengths.
@ -2926,16 +2860,16 @@ mod test {
slice_lengths!(
slice_len_too_big_i64, read_i64_into, write_i64_into, 17, [0, 0]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
slice_lengths!(
slice_len_too_small_u128, read_u128_into, write_u128_into, 31, [0, 0]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
slice_lengths!(
slice_len_too_big_u128, read_u128_into, write_u128_into, 33, [0, 0]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
slice_lengths!(
slice_len_too_small_i128, read_i128_into, write_i128_into, 31, [0, 0]);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
slice_lengths!(
slice_len_too_big_i128, read_i128_into, write_i128_into, 33, [0, 0]);
@ -3082,9 +3016,9 @@ mod stdtests {
qc_bytes_ext!(prop_ext_f64,
f64, ::std::i64::MAX as u64, read_f64, write_f64);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_u128, Wi128<u128>, 16 + 1, read_u128, write_u128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_i128, Wi128<i128>, 16 + 1, read_i128, write_i128);
qc_bytes_ext!(prop_ext_uint_1,
@ -3104,52 +3038,52 @@ mod stdtests {
qc_bytes_ext!(prop_ext_uint_8,
u64, calc_max!(::test::U64_MAX, 8), 8, read_uint, write_u64);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_uint128_1,
Wi128<u128>, 1, 1, read_uint128, write_u128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_uint128_2,
Wi128<u128>, 2, 2, read_uint128, write_u128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_uint128_3,
Wi128<u128>, 3, 3, read_uint128, write_u128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_uint128_4,
Wi128<u128>, 4, 4, read_uint128, write_u128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_uint128_5,
Wi128<u128>, 5, 5, read_uint128, write_u128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_uint128_6,
Wi128<u128>, 6, 6, read_uint128, write_u128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_uint128_7,
Wi128<u128>, 7, 7, read_uint128, write_u128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_uint128_8,
Wi128<u128>, 8, 8, read_uint128, write_u128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_uint128_9,
Wi128<u128>, 9, 9, read_uint128, write_u128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_uint128_10,
Wi128<u128>, 10, 10, read_uint128, write_u128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_uint128_11,
Wi128<u128>, 11, 11, read_uint128, write_u128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_uint128_12,
Wi128<u128>, 12, 12, read_uint128, write_u128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_uint128_13,
Wi128<u128>, 13, 13, read_uint128, write_u128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_uint128_14,
Wi128<u128>, 14, 14, read_uint128, write_u128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_uint128_15,
Wi128<u128>, 15, 15, read_uint128, write_u128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_uint128_16,
Wi128<u128>, 16, 16, read_uint128, write_u128);
@ -3170,52 +3104,52 @@ mod stdtests {
qc_bytes_ext!(prop_ext_int_8,
i64, calc_max!(::test::I64_MAX, 8), 8, read_int, write_i64);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_int128_1,
Wi128<i128>, 1, 1, read_int128, write_i128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_int128_2,
Wi128<i128>, 2, 2, read_int128, write_i128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_int128_3,
Wi128<i128>, 3, 3, read_int128, write_i128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_int128_4,
Wi128<i128>, 4, 4, read_int128, write_i128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_int128_5,
Wi128<i128>, 5, 5, read_int128, write_i128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_int128_6,
Wi128<i128>, 6, 6, read_int128, write_i128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_int128_7,
Wi128<i128>, 7, 7, read_int128, write_i128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_int128_8,
Wi128<i128>, 8, 8, read_int128, write_i128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_int128_9,
Wi128<i128>, 9, 9, read_int128, write_i128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_int128_10,
Wi128<i128>, 10, 10, read_int128, write_i128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_int128_11,
Wi128<i128>, 11, 11, read_int128, write_i128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_int128_12,
Wi128<i128>, 12, 12, read_int128, write_i128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_int128_13,
Wi128<i128>, 13, 13, read_int128, write_i128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_int128_14,
Wi128<i128>, 14, 14, read_int128, write_i128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_int128_15,
Wi128<i128>, 15, 15, read_int128, write_i128);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_bytes_ext!(prop_ext_int128_16,
Wi128<i128>, 16, 16, read_int128, write_i128);
@ -3301,15 +3235,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(byteorder_i128)]
#[cfg(feature = "i128")]
qc_slice!(
prop_slice_u128, Wi128<u128>, read_u128_into, write_u128_into, 0);
#[cfg(byteorder_i128)]
#[cfg(feature = "i128")]
qc_slice!(
prop_slice_i128, Wi128<i128>, read_i128_into, write_i128_into, 0);
qc_slice!(
prop_slice_f32, f32, read_f32_into, write_f32_into, 0.0);
prop_slice_f32, f32, read_f32_into_unchecked, write_f32_into, 0.0);
qc_slice!(
prop_slice_f64, f64, read_f64_into, write_f64_into, 0.0);
prop_slice_f64, f64, read_f64_into_unchecked, write_f64_into, 0.0);
}

View File

@ -1 +0,0 @@
{"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"}

View File

@ -1,24 +0,0 @@
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

View File

@ -1,19 +0,0 @@
[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 = []

View File

@ -1,21 +0,0 @@
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.

View File

@ -1,50 +0,0 @@
**************
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

View File

@ -1,61 +0,0 @@
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);
}
}

View File

@ -1,15 +0,0 @@
#![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;

View File

@ -1,181 +0,0 @@
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);
}
}
}

View File

@ -1,115 +0,0 @@
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);
}
}
}

View File

@ -1 +0,0 @@
{"files":{"Cargo.toml":"36dc9de00443082a361c4ad88b194afb069f83fc8867b45ef17851f10819d33e","README.md":"2813bf88a5c407c6883f173fac430072f0007f730615366983f59e6d5e6950de","license.txt":"c76f740d1521b9bed9ca7a04ad526c310493c62621b1341d623b431736533b30","src/lib.rs":"74b8e2cd9beeaccf6d8233ab45def8a49a4a13f364d99bbbc4850836d24300c5","test_data/test_bf":"afa0b9e6b9244522302aa8d153e92e25d7fd16388f34c06497487fc0332a4d34","test_data/test_mlbf":"2c6a5f13ad459f1bcf88d91c2eaab94eda84a60fc123b9914203dee725d70ba0","test_data/test_short_mlbf":"55f0d1361acb4f4ec25dba6bfa92a777d49dcc2e71f623a9ec2a70c6ff5f61eb"},"package":null}

View File

@ -1,13 +0,0 @@
[package]
name = "rust_cascade"
description = "A simple mmh3 based bloom filter cascade implementation in Rust."
license = "MPL-2.0"
version = "0.3.2"
authors = ["Mark Goodwin <mgoodwin@mozilla.com>"]
[dependencies]
murmurhash3="0.0.5"
bitvec = { git = "https://github.com/mozmark/bitvec", branch = "20190426-bitvec-vendor-issues" }
byteorder="1.3.1"
rand="0.*"
digest="0.8.0"

View File

@ -1,4 +0,0 @@
# rust-cascade
A filter cascade implementation in rust
See tests in src/lib.js to get an idea of usage.

View File

@ -1,373 +0,0 @@
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.

View File

@ -1,326 +0,0 @@
extern crate bitvec;
extern crate byteorder;
extern crate digest;
extern crate murmurhash3;
extern crate rand;
use bitvec::prelude::{bitvec, BitVec, LittleEndian,};
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<LittleEndian>,
}
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<LittleEndian> = bitvec![LittleEndian; 0; size];
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)?;
Ok(Bloom {
level,
n_hash_funcs,
size,
bitvec: bitvec_buf.into(),
})
}
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");
}
}

Binary file not shown.

Binary file not shown.