third_party/cargo: update

master
q3k 2021-04-03 16:13:10 +00:00
parent ae5dbbceac
commit 07436668f4
1666 changed files with 28052 additions and 17945 deletions

View File

@ -41,7 +41,7 @@ alias(
alias( alias(
name = "image", name = "image",
actual = "//third_party/cargo/vendor/image-0.23.12:image", actual = "//third_party/cargo/vendor/image-0.23.14:image",
tags = [ tags = [
"cargo-raze", "cargo-raze",
"manual", "manual",
@ -50,7 +50,7 @@ alias(
alias( alias(
name = "log", name = "log",
actual = "//third_party/cargo/vendor/log-0.4.11:log", actual = "//third_party/cargo/vendor/log-0.4.14:log",
tags = [ tags = [
"cargo-raze", "cargo-raze",
"manual", "manual",
@ -59,7 +59,7 @@ alias(
alias( alias(
name = "proc_macro2", name = "proc_macro2",
actual = "//third_party/cargo/vendor/proc-macro2-1.0.24:proc_macro2", actual = "//third_party/cargo/vendor/proc-macro2-1.0.26:proc_macro2",
tags = [ tags = [
"cargo-raze", "cargo-raze",
"manual", "manual",
@ -68,7 +68,7 @@ alias(
alias( alias(
name = "quote", name = "quote",
actual = "//third_party/cargo/vendor/quote-1.0.8:quote", actual = "//third_party/cargo/vendor/quote-1.0.9:quote",
tags = [ tags = [
"cargo-raze", "cargo-raze",
"manual", "manual",
@ -77,7 +77,7 @@ alias(
alias( alias(
name = "syn", name = "syn",
actual = "//third_party/cargo/vendor/syn-1.0.58:syn", actual = "//third_party/cargo/vendor/syn-1.0.68:syn",
tags = [ tags = [
"cargo-raze", "cargo-raze",
"manual", "manual",

240
third_party/cargo/Cargo.lock generated vendored
View File

@ -8,9 +8,9 @@ checksum = "d9fe5e32de01730eb1f6b7f5b51c17e03e2325bf40a74f754f04f130043affff"
[[package]] [[package]]
name = "adler" name = "adler"
version = "0.2.3" version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]] [[package]]
name = "adler32" name = "adler32"
@ -80,15 +80,15 @@ checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
[[package]] [[package]]
name = "bytemuck" name = "bytemuck"
version = "1.4.1" version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41aa2ec95ca3b5c54cf73c91acf06d24f4495d5f1b1c12506ae3483d646177ac" checksum = "bed57e2090563b83ba8f83366628ce535a7584c9afa4c9fc0612a03925c6df58"
[[package]] [[package]]
name = "byteorder" name = "byteorder"
version = "1.3.4" version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]] [[package]]
name = "calloop" name = "calloop"
@ -102,9 +102,9 @@ dependencies = [
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.66" version = "1.0.67"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48" checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
@ -189,18 +189,14 @@ dependencies = [
"flatbuffers", "flatbuffers",
"image", "image",
"log", "log",
"nix 0.19.1", "proc-macro2",
"quote",
"syn",
"vulkano", "vulkano",
"vulkano-win", "vulkano-win",
"winit", "winit",
] ]
[[package]]
name = "const_fn"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6"
[[package]] [[package]]
name = "core-foundation" name = "core-foundation"
version = "0.7.0" version = "0.7.0"
@ -323,7 +319,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"crossbeam-utils 0.8.1", "crossbeam-utils 0.8.3",
] ]
[[package]] [[package]]
@ -344,8 +340,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"crossbeam-epoch 0.9.1", "crossbeam-epoch 0.9.3",
"crossbeam-utils 0.8.1", "crossbeam-utils 0.8.3",
] ]
[[package]] [[package]]
@ -365,15 +361,14 @@ dependencies = [
[[package]] [[package]]
name = "crossbeam-epoch" name = "crossbeam-epoch"
version = "0.9.1" version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d" checksum = "2584f639eb95fea8c798496315b297cf81b9b58b6d30ab066a75455333cf4b12"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"const_fn", "crossbeam-utils 0.8.3",
"crossbeam-utils 0.8.1",
"lazy_static", "lazy_static",
"memoffset 0.6.1", "memoffset 0.6.3",
"scopeguard", "scopeguard",
] ]
@ -401,9 +396,9 @@ dependencies = [
[[package]] [[package]]
name = "crossbeam-utils" name = "crossbeam-utils"
version = "0.8.1" version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d" checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"cfg-if 1.0.0", "cfg-if 1.0.0",
@ -457,9 +452,9 @@ dependencies = [
[[package]] [[package]]
name = "derivative" name = "derivative"
version = "2.1.3" version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eaed5874effa6cde088c644ddcdcb4ffd1511391c5be4fdd7a5ccd02c7e4a183" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -478,7 +473,16 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b11f15d1e3268f140f68d390637d5e76d849782d971ae7063e0da69fe9709a76" checksum = "b11f15d1e3268f140f68d390637d5e76d849782d971ae7063e0da69fe9709a76"
dependencies = [ dependencies = [
"libloading", "libloading 0.6.7",
]
[[package]]
name = "dlib"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac1b7517328c04c2aa68422fc60a41b92208182142ed04a25879c26c8f878794"
dependencies = [
"libloading 0.7.0",
] ]
[[package]] [[package]]
@ -554,9 +558,9 @@ checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
[[package]] [[package]]
name = "gif" name = "gif"
version = "0.11.1" version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02efba560f227847cb41463a7395c514d127d4f74fff12ef0137fff1b84b96c4" checksum = "5a668f699973d0f573d15749b7002a9ac9e1f9c6b220e7b165601334c173d8de"
dependencies = [ dependencies = [
"color_quant", "color_quant",
"weezl", "weezl",
@ -564,15 +568,15 @@ dependencies = [
[[package]] [[package]]
name = "half" name = "half"
version = "1.6.0" version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d36fab90f82edc3c747f9d438e06cf0a491055896f2a279638bb5beed6c40177" checksum = "62aca2aba2d62b4a7f5b33f3712cb1b0692779a56fb510499d5c0aa594daeaf3"
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.1.17" version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8" checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
dependencies = [ dependencies = [
"libc", "libc",
] ]
@ -594,9 +598,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]] [[package]]
name = "image" name = "image"
version = "0.23.12" version = "0.23.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ce04077ead78e39ae8610ad26216aed811996b043d47beed5090db674f9e9b5" checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1"
dependencies = [ dependencies = [
"bytemuck", "bytemuck",
"byteorder", "byteorder",
@ -637,11 +641,10 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
[[package]] [[package]]
name = "jpeg-decoder" name = "jpeg-decoder"
version = "0.1.20" version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc797adac5f083b8ff0ca6f6294a999393d76e197c36488e2ef732c4715f6fa3" checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2"
dependencies = [ dependencies = [
"byteorder",
"rayon", "rayon",
] ]
@ -669,15 +672,25 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.82" version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929" checksum = "56d855069fafbb9b344c0f962150cd2c1187975cb1c22c1522c240d8c4986714"
[[package]] [[package]]
name = "libloading" name = "libloading"
version = "0.6.6" version = "0.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9367bdfa836b7e3cf895867f7a570283444da90562980ec2263d6e1569b16bc" checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883"
dependencies = [
"cfg-if 1.0.0",
"winapi 0.3.9",
]
[[package]]
name = "libloading"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f84d96438c15fcd6c3f244c8fce01d1e2b9c6b5623e9c711dc9286d8fc92d6a"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"winapi 0.3.9", "winapi 0.3.9",
@ -685,20 +698,20 @@ dependencies = [
[[package]] [[package]]
name = "lock_api" name = "lock_api"
version = "0.4.2" version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312" checksum = "5a3c91c24eae6777794bb1997ad98bbb87daf92890acab859f7eaa4320333176"
dependencies = [ dependencies = [
"scopeguard", "scopeguard",
] ]
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.11" version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [ dependencies = [
"cfg-if 0.1.10", "cfg-if 1.0.0",
] ]
[[package]] [[package]]
@ -742,9 +755,9 @@ dependencies = [
[[package]] [[package]]
name = "memoffset" name = "memoffset"
version = "0.6.1" version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87" checksum = "f83fb6581e8ed1f85fd45c116db8405483899489e38406156c25eb743554361d"
dependencies = [ dependencies = [
"autocfg", "autocfg",
] ]
@ -775,9 +788,9 @@ dependencies = [
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.4.3" version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d" checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
dependencies = [ dependencies = [
"adler", "adler",
"autocfg", "autocfg",
@ -896,9 +909,9 @@ dependencies = [
[[package]] [[package]]
name = "nix" name = "nix"
version = "0.19.1" version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2ccba0cfe4fdf15982d1674c69b1fd80bad427d293849982668dfe454bd61f2" checksum = "fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"cc", "cc",
@ -908,9 +921,9 @@ dependencies = [
[[package]] [[package]]
name = "nom" name = "nom"
version = "6.0.1" version = "6.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88034cfd6b4a0d54dd14f4a507eceee36c0b70e5a02236c4e4df571102be17f0" checksum = "e7413f999671bd4745a7b624bd370a569fb6bc574b23c83a3c5ed2e453f3d5e2"
dependencies = [ dependencies = [
"memchr", "memchr",
"version_check", "version_check",
@ -1010,9 +1023,9 @@ dependencies = [
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.5.2" version = "1.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0" checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
[[package]] [[package]]
name = "owned_ttf_parser" name = "owned_ttf_parser"
@ -1036,9 +1049,9 @@ dependencies = [
[[package]] [[package]]
name = "parking_lot_core" name = "parking_lot_core"
version = "0.8.2" version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ccb628cad4f84851442432c60ad8e1f607e29752d0bf072cbd0baf28aa34272" checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"instant", "instant",
@ -1083,9 +1096,9 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.24" version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
dependencies = [ dependencies = [
"unicode-xid", "unicode-xid",
] ]
@ -1098,9 +1111,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.8" version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df" checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -1134,34 +1147,36 @@ checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a"
dependencies = [ dependencies = [
"crossbeam-channel 0.5.0", "crossbeam-channel 0.5.0",
"crossbeam-deque 0.8.0", "crossbeam-deque 0.8.0",
"crossbeam-utils 0.8.1", "crossbeam-utils 0.8.3",
"lazy_static", "lazy_static",
"num_cpus", "num_cpus",
] ]
[[package]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.1.57" version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9"
dependencies = [
"bitflags",
]
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.4.2" version = "1.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c" checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
"regex-syntax", "regex-syntax",
"thread_local",
] ]
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.6.21" version = "0.6.23"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189" checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
[[package]] [[package]]
name = "rusttype" name = "rusttype"
@ -1202,9 +1217,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.118" version = "1.0.125"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800" checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171"
[[package]] [[package]]
name = "shared_library" name = "shared_library"
@ -1224,20 +1239,20 @@ checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.6.0" version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a55ca5f3b68e41c979bf8c46a6f1da892ca4db8f94023ce0bd32407573b1ac0" checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
[[package]] [[package]]
name = "smithay-client-toolkit" name = "smithay-client-toolkit"
version = "0.12.2" version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "316e13a3eb853ce7bf72ad3530dc186cb2005c57c521ef5f4ada5ee4eed74de6" checksum = "4750c76fd5d3ac95fa3ed80fe667d6a3d8590a960e5b575b98eea93339a80b80"
dependencies = [ dependencies = [
"andrew", "andrew",
"bitflags", "bitflags",
"calloop", "calloop",
"dlib", "dlib 0.4.2",
"lazy_static", "lazy_static",
"log", "log",
"memmap2", "memmap2",
@ -1255,9 +1270,9 @@ checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.58" version = "1.0.68"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc60a3d73ea6594cd712d830cc1f0390fd71542d8c8cd24e70cc54cdfd5e05d5" checksum = "3ce15dd3ed8aa2f8eeac4716d6ef5ab58b6b9256db41d7e1a0224c2788e8fd87"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1275,33 +1290,24 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.23" version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76cc616c6abf8c8928e2fdcc0dbfab37175edd8fb49a4641066ad1364fdab146" checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.23" version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9be73a2caec27583d0046ef3796c3794f868a5bc813db689eed00c7631275cd1" checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn",
] ]
[[package]]
name = "thread_local"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb9bc092d0d51e76b2b19d9d85534ffc9ec2db959a2523cdae0697e2972cd447"
dependencies = [
"lazy_static",
]
[[package]] [[package]]
name = "tiff" name = "tiff"
version = "0.6.1" version = "0.6.1"
@ -1309,7 +1315,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a53f4706d65497df0c4349241deddf35f84cee19c87ed86ea8ca590f4464437" checksum = "9a53f4706d65497df0c4349241deddf35f84cee19c87ed86ea8ca590f4464437"
dependencies = [ dependencies = [
"jpeg-decoder", "jpeg-decoder",
"miniz_oxide 0.4.3", "miniz_oxide 0.4.4",
"weezl", "weezl",
] ]
@ -1336,9 +1342,9 @@ checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]] [[package]]
name = "version_check" name = "version_check"
version = "0.9.2" version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
[[package]] [[package]]
name = "vk-sys" name = "vk-sys"
@ -1378,9 +1384,9 @@ dependencies = [
[[package]] [[package]]
name = "walkdir" name = "walkdir"
version = "2.3.1" version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
dependencies = [ dependencies = [
"same-file", "same-file",
"winapi 0.3.9", "winapi 0.3.9",
@ -1389,14 +1395,14 @@ dependencies = [
[[package]] [[package]]
name = "wayland-client" name = "wayland-client"
version = "0.28.3" version = "0.28.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bdbdbe01d03b2267809f3ed99495b37395387fde789e0f2ebb78e8b43f75b6d7" checksum = "06ca44d86554b85cf449f1557edc6cc7da935cc748c8e4bf1c507cbd43bae02c"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"downcast-rs", "downcast-rs",
"libc", "libc",
"nix 0.18.0", "nix 0.20.0",
"scoped-tls", "scoped-tls",
"wayland-commons", "wayland-commons",
"wayland-scanner", "wayland-scanner",
@ -1405,11 +1411,11 @@ dependencies = [
[[package]] [[package]]
name = "wayland-commons" name = "wayland-commons"
version = "0.28.3" version = "0.28.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "480450f76717edd64ad04a4426280d737fc3d10a236b982df7b1aee19f0e2d56" checksum = "8bd75ae380325dbcff2707f0cd9869827ea1d2d6d534cff076858d3f0460fd5a"
dependencies = [ dependencies = [
"nix 0.18.0", "nix 0.20.0",
"once_cell", "once_cell",
"smallvec", "smallvec",
"wayland-sys", "wayland-sys",
@ -1417,20 +1423,20 @@ dependencies = [
[[package]] [[package]]
name = "wayland-cursor" name = "wayland-cursor"
version = "0.28.3" version = "0.28.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6eb122c160223a7660feeaf949d0100281d1279acaaed3720eb3c9894496e5f" checksum = "b37e5455ec72f5de555ec39b5c3704036ac07c2ecd50d0bffe02d5fe2d4e65ab"
dependencies = [ dependencies = [
"nix 0.18.0", "nix 0.20.0",
"wayland-client", "wayland-client",
"xcursor", "xcursor",
] ]
[[package]] [[package]]
name = "wayland-protocols" name = "wayland-protocols"
version = "0.28.3" version = "0.28.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "319a82b4d3054dd25acc32d9aee0f84fa95b63bc983fffe4703b6b8d47e01a30" checksum = "95df3317872bcf9eec096c864b69aa4769a1d5d6291a5b513f8ba0af0efbd52c"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"wayland-client", "wayland-client",
@ -1440,9 +1446,9 @@ dependencies = [
[[package]] [[package]]
name = "wayland-scanner" name = "wayland-scanner"
version = "0.28.3" version = "0.28.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7010ba5767b3fcd350decc59055390b4ebe6bd1b9279a9feb1f1888987f1133d" checksum = "389d680d7bd67512dc9c37f39560224327038deb0f0e8d33f870900441b68720"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1451,20 +1457,20 @@ dependencies = [
[[package]] [[package]]
name = "wayland-sys" name = "wayland-sys"
version = "0.28.3" version = "0.28.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6793834e0c35d11fd96a97297abe03d37be627e1847da52e17d7e0e3b51cc099" checksum = "2907bd297eef464a95ba9349ea771611771aa285b932526c633dc94d5400a8e2"
dependencies = [ dependencies = [
"dlib", "dlib 0.5.0",
"lazy_static", "lazy_static",
"pkg-config", "pkg-config",
] ]
[[package]] [[package]]
name = "weezl" name = "weezl"
version = "0.1.3" version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e2bb9fc8309084dd7cd651336673844c1d47f8ef6d2091ec160b27f5c4aa277" checksum = "4a32b378380f4e9869b22f0b5177c68a5519f03b3454fde0b291455ddbae266c"
[[package]] [[package]]
name = "winapi" name = "winapi"

View File

@ -18,6 +18,7 @@ cgmath = "0.18.0"
flatbuffers = "0.6.1" flatbuffers = "0.6.1"
quote = "1.0.8" quote = "1.0.8"
syn = "1.0.58" syn = "1.0.58"
proc-macro2 = "1"
[workspace.metadata.raze] [workspace.metadata.raze]
workspace_path = "//third_party/cargo" workspace_path = "//third_party/cargo"
@ -30,50 +31,44 @@ rust_rules_workspace_name = "rules_rust"
package_aliases_dir = "." package_aliases_dir = "."
default_gen_buildrs = false default_gen_buildrs = false
[workspace.metadata.raze.crates.andrew.'0.2.1'] [workspace.metadata.raze.crates.andrew.'0.3.1']
skipped_deps = ['rusttype-0.7.9'] skipped_deps = ['rusttype-0.9.2']
additional_deps = ['//third_party/cargo/vendor/rusttype-0.8.3:rusttype'] additional_deps = ['//third_party/cargo/vendor/rusttype-0.9.2:rusttype']
[workspace.metadata.raze.crates.x11-dl.'2.18.5'] [workspace.metadata.raze.crates.x11-dl.'2.18.5']
gen_buildrs = true gen_buildrs = true
[workspace.metadata.raze.crates.wayland-client.'0.23.6'] [workspace.metadata.raze.crates.wayland-client.'0.28.5']
gen_buildrs = true gen_buildrs = true
[workspace.metadata.raze.crates.wayland-protocols.'0.23.6'] [workspace.metadata.raze.crates.wayland-protocols.'0.28.5']
gen_buildrs = true gen_buildrs = true
[workspace.metadata.raze.crates.log.'0.4.8'] [workspace.metadata.raze.crates.log.'0.4.14']
additional_flags = [ additional_flags = [
"--cfg=atomic_cas" "--cfg=atomic_cas"
] ]
[workspace.metadata.raze.crates.libloading.'0.6.6'] [workspace.metadata.raze.crates.libloading.'0.7.0']
additional_deps = ['//third_party/cargo/patches:libloading_global_static'] additional_deps = ['//third_party/cargo/patches:libloading_global_static']
[workspace.metadata.raze.crates.cgmath.'0.18.0'] [workspace.metadata.raze.crates.cgmath.'0.18.0']
gen_buildrs = true gen_buildrs = true
[workspace.metadata.raze.crates.image.'0.23.12'] [workspace.metadata.raze.crates.image.'0.23.14']
gen_buildrs = true gen_buildrs = true
[workspace.metadata.raze.crates.num-rational.'0.3.2'] [workspace.metadata.raze.crates.num-rational.'0.3.2']
gen_buildrs = true gen_buildrs = true
[workspace.metadata.raze.crates.libc.'0.2.82'] [workspace.metadata.raze.crates.libc.'0.2.92']
gen_buildrs = true
[workspace.metadata.raze.crates.wayland-client.'0.28.3']
gen_buildrs = true
[workspace.metadata.raze.crates.wayland-protocols.'0.28.3']
gen_buildrs = true gen_buildrs = true
[workspace.metadata.raze.crates.maybe-uninit.'2.0.0'] [workspace.metadata.raze.crates.maybe-uninit.'2.0.0']
gen_buildrs = true gen_buildrs = true
[workspace.metadata.raze.crates.winapi.'0.3.9'] [workspace.metadata.raze.crates.winapi.'0.4.0']
gen_buildrs = true gen_buildrs = true
[workspace.metadata.raze.crates.proc-macro2.'1.0.24'] [workspace.metadata.raze.crates.proc-macro2.'1.0.26']
gen_buildrs = true gen_buildrs = true

View File

@ -2,5 +2,5 @@ cc_library(
name = "libloading_global_static", name = "libloading_global_static",
srcs = ["libloading/global_static.c"], srcs = ["libloading/global_static.c"],
copts = ["-fPIC"], copts = ["-fPIC"],
visibility = ["//third_party/cargo/vendor/libloading-0.6.6:__pkg__"], visibility = ["//third_party/cargo/vendor:__subpackages__"],
) )

View File

@ -1 +0,0 @@
{"files":{"CHANGELOG.md":"042ed3158af7000c88a6617d775f11456bd30f6c7c8b5b586978faa1e11b1e24","Cargo.toml":"107d13689eecfa82a8b5ae35bf835b9d2775337226630e4bdb35f22d0dd52e18","LICENSE-0BSD":"861399f8c21c042b110517e76dc6b63a2b334276c8cf17412fc3c8908ca8dc17","LICENSE-APACHE":"8ada45cd9f843acf64e4722ae262c622a2b3b3007c7310ef36ac1061a30f6adb","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"fa83fd5ee10b61827de382e496bf66296a526e3d2c3b2aa5ad672aa15e8d2d7f","RELEASE_PROCESS.md":"a86cd10fc70f167f8d00e9e4ce0c6b4ebdfa1865058390dffd1e0ad4d3e68d9d","benches/bench.rs":"c07ce370e3680c602e415f8d1ec4e543ea2163ab22a09b6b82d93e8a30adca82","src/algo.rs":"b664b131f724a809591394a10b9023f40ab5963e32a83fa3163c2668e59c8b66","src/lib.rs":"67f3ca5b6333e22745b178b70f472514162cea2890344724f0f66995fcf19806"},"package":"ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"}

View File

@ -0,0 +1 @@
{"files":{"CHANGELOG.md":"737088e45fdf27fe2cfedce163332d8ce08c58fd86ca287de2de34c0fbaf63e7","Cargo.toml":"f410869f0f1a5697f65a8a77be03da7aeecc0be26e7cf3a1feb1acaa4f518770","LICENSE-0BSD":"861399f8c21c042b110517e76dc6b63a2b334276c8cf17412fc3c8908ca8dc17","LICENSE-APACHE":"8ada45cd9f843acf64e4722ae262c622a2b3b3007c7310ef36ac1061a30f6adb","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"308c50cdb42b9573743068158339570b45ca3f895015ca3b87ba983edb0a21e6","RELEASE_PROCESS.md":"a86cd10fc70f167f8d00e9e4ce0c6b4ebdfa1865058390dffd1e0ad4d3e68d9d","benches/bench.rs":"c07ce370e3680c602e415f8d1ec4e543ea2163ab22a09b6b82d93e8a30adca82","src/algo.rs":"b664b131f724a809591394a10b9023f40ab5963e32a83fa3163c2668e59c8b66","src/lib.rs":"b55ba9c629b30360d08168b2ca0c96275432856a539737a105a6d6ae6bf7e88f"},"package":"f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"}

View File

@ -48,7 +48,7 @@ rust_library(
"cargo-raze", "cargo-raze",
"manual", "manual",
], ],
version = "0.2.3", version = "1.0.2",
# buildifier: leave-alone # buildifier: leave-alone
deps = [ deps = [
], ],

View File

@ -4,6 +4,35 @@
No changes. No changes.
## [1.0.2 - 2021-02-26](https://github.com/jonas-schievink/adler/releases/tag/v1.0.2)
- Fix doctest on big-endian systems ([#9]).
[#9]: https://github.com/jonas-schievink/adler/pull/9
## [1.0.1 - 2020-11-08](https://github.com/jonas-schievink/adler/releases/tag/v1.0.1)
### Fixes
- Fix documentation on docs.rs.
## [1.0.0 - 2020-11-08](https://github.com/jonas-schievink/adler/releases/tag/v1.0.0)
### Fixes
- Fix `cargo test --no-default-features` ([#5]).
### Improvements
- Extended and clarified documentation.
- Added more rustdoc examples.
- Extended CI to test the crate with `--no-default-features`.
### Breaking Changes
- `adler32_reader` now takes its generic argument by value instead of as a `&mut`.
- Renamed `adler32_reader` to `adler32`.
## [0.2.3 - 2020-07-11](https://github.com/jonas-schievink/adler/releases/tag/v0.2.3) ## [0.2.3 - 2020-07-11](https://github.com/jonas-schievink/adler/releases/tag/v0.2.3)
- Process 4 Bytes at a time, improving performance by up to 50% ([#2]). - Process 4 Bytes at a time, improving performance by up to 50% ([#2]).
@ -31,3 +60,4 @@ Initial release.
[#2]: https://github.com/jonas-schievink/adler/pull/2 [#2]: https://github.com/jonas-schievink/adler/pull/2
[#5]: https://github.com/jonas-schievink/adler/pull/5

View File

@ -12,17 +12,17 @@
[package] [package]
name = "adler" name = "adler"
version = "0.2.3" version = "1.0.2"
authors = ["Jonas Schievink <jonasschievink@gmail.com>"] authors = ["Jonas Schievink <jonasschievink@gmail.com>"]
description = "A simple clean-room implementation of the Adler-32 checksum" description = "A simple clean-room implementation of the Adler-32 checksum"
documentation = "https://docs.rs/adler/" documentation = "https://docs.rs/adler/"
readme = "README.md" readme = "README.md"
keywords = ["checksum", "integrity", "hash", "adler32"] keywords = ["checksum", "integrity", "hash", "adler32", "zlib"]
categories = ["algorithms"] categories = ["algorithms"]
license = "0BSD OR MIT OR Apache-2.0" license = "0BSD OR MIT OR Apache-2.0"
repository = "https://github.com/jonas-schievink/adler.git" repository = "https://github.com/jonas-schievink/adler.git"
[package.metadata.docs.rs] [package.metadata.docs.rs]
rustdoc-args = ["--cfg docsrs"] rustdoc-args = ["--cfg=docsrs"]
[package.metadata.release] [package.metadata.release]
no-dev-version = true no-dev-version = true
@ -62,8 +62,3 @@ version = "0.3.2"
default = ["std"] default = ["std"]
rustc-dep-of-std = ["core", "compiler_builtins"] rustc-dep-of-std = ["core", "compiler_builtins"]
std = [] std = []
[badges.maintenance]
status = "actively-developed"
[badges.travis-ci]
repository = "jonas-schievink/adler"

View File

@ -5,7 +5,7 @@
![CI](https://github.com/jonas-schievink/adler/workflows/CI/badge.svg) ![CI](https://github.com/jonas-schievink/adler/workflows/CI/badge.svg)
This crate provides a simple implementation of the Adler-32 checksum, used in This crate provides a simple implementation of the Adler-32 checksum, used in
zlib, rsync, and other software. the zlib compression format.
Please refer to the [changelog](CHANGELOG.md) to see what changed in the last Please refer to the [changelog](CHANGELOG.md) to see what changed in the last
releases. releases.
@ -14,6 +14,7 @@ releases.
- Permissively licensed (0BSD) clean-room implementation. - Permissively licensed (0BSD) clean-room implementation.
- Zero dependencies. - Zero dependencies.
- Zero `unsafe`.
- Decent performance (3-4 GB/s). - Decent performance (3-4 GB/s).
- Supports `#![no_std]` (with `default-features = false`). - Supports `#![no_std]` (with `default-features = false`).
@ -23,7 +24,7 @@ Add an entry to your `Cargo.toml`:
```toml ```toml
[dependencies] [dependencies]
adler = "0.2.3" adler = "1.0.2"
``` ```
Check the [API Documentation](https://docs.rs/adler/) for how to use the Check the [API Documentation](https://docs.rs/adler/) for how to use the

View File

@ -4,10 +4,11 @@
//! //!
//! - Permissively licensed (0BSD) clean-room implementation. //! - Permissively licensed (0BSD) clean-room implementation.
//! - Zero dependencies. //! - Zero dependencies.
//! - Zero `unsafe`.
//! - Decent performance (3-4 GB/s). //! - Decent performance (3-4 GB/s).
//! - `#![no_std]` support (with `default-features = false`). //! - `#![no_std]` support (with `default-features = false`).
#![doc(html_root_url = "https://docs.rs/adler/0.2.3")] #![doc(html_root_url = "https://docs.rs/adler/1.0.2")]
// Deny a few warnings in doctests, since rustdoc `allow`s many warnings by default // Deny a few warnings in doctests, since rustdoc `allow`s many warnings by default
#![doc(test(attr(deny(unused_imports, unused_must_use))))] #![doc(test(attr(deny(unused_imports, unused_must_use))))]
#![cfg_attr(docsrs, feature(doc_cfg))] #![cfg_attr(docsrs, feature(doc_cfg))]
@ -33,8 +34,51 @@ use std::io::{self, BufRead};
/// ///
/// This type also implements `Hasher`, which makes it easy to calculate Adler-32 checksums of any /// This type also implements `Hasher`, which makes it easy to calculate Adler-32 checksums of any
/// type that implements or derives `Hash`. This also allows using Adler-32 in a `HashMap`, although /// type that implements or derives `Hash`. This also allows using Adler-32 in a `HashMap`, although
/// that is not recommended (while every checksum is a hash, they are not necessarily good at being /// that is not recommended (while every checksum is a hash function, they are not necessarily a
/// one). /// good one).
///
/// # Examples
///
/// Basic, piecewise checksum calculation:
///
/// ```
/// use adler::Adler32;
///
/// let mut adler = Adler32::new();
///
/// adler.write_slice(&[0, 1, 2]);
/// adler.write_slice(&[3, 4, 5]);
///
/// assert_eq!(adler.checksum(), 0x00290010);
/// ```
///
/// Using `Hash` to process structures:
///
/// ```
/// use std::hash::Hash;
/// use adler::Adler32;
///
/// #[derive(Hash)]
/// struct Data {
/// byte: u8,
/// word: u16,
/// big: u64,
/// }
///
/// let mut adler = Adler32::new();
///
/// let data = Data { byte: 0x1F, word: 0xABCD, big: !0 };
/// data.hash(&mut adler);
///
/// // hash value depends on architecture endianness
/// if cfg!(target_endian = "little") {
/// assert_eq!(adler.checksum(), 0x33410990);
/// }
/// if cfg!(target_endian = "big") {
/// assert_eq!(adler.checksum(), 0x331F0990);
/// }
///
/// ```
/// ///
/// [`new`]: #method.new /// [`new`]: #method.new
/// [`from_checksum`]: #method.from_checksum /// [`from_checksum`]: #method.from_checksum
@ -119,6 +163,10 @@ impl Hasher for Adler32 {
} }
/// Calculates the Adler-32 checksum of a byte slice. /// Calculates the Adler-32 checksum of a byte slice.
///
/// This is a convenience function around the [`Adler32`] type.
///
/// [`Adler32`]: struct.Adler32.html
pub fn adler32_slice(data: &[u8]) -> u32 { pub fn adler32_slice(data: &[u8]) -> u32 {
let mut h = Adler32::new(); let mut h = Adler32::new();
h.write_slice(data); h.write_slice(data);
@ -127,12 +175,35 @@ pub fn adler32_slice(data: &[u8]) -> u32 {
/// Calculates the Adler-32 checksum of a `BufRead`'s contents. /// Calculates the Adler-32 checksum of a `BufRead`'s contents.
/// ///
/// The passed `BufRead` implementor will be read until it reaches EOF. /// The passed `BufRead` implementor will be read until it reaches EOF (or until it reports an
/// error).
/// ///
/// If you only have a `Read` implementor, wrap it in `std::io::BufReader`. /// If you only have a `Read` implementor, you can wrap it in `std::io::BufReader` before calling
/// this function.
///
/// # Errors
///
/// Any error returned by the reader are bubbled up by this function.
///
/// # Examples
///
/// ```no_run
/// # fn run() -> Result<(), Box<dyn std::error::Error>> {
/// use adler::adler32;
///
/// use std::fs::File;
/// use std::io::BufReader;
///
/// let file = File::open("input.txt")?;
/// let mut file = BufReader::new(file);
///
/// adler32(&mut file)?;
/// # Ok(()) }
/// # fn main() { run().unwrap() }
/// ```
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))] #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
pub fn adler32_reader<R: BufRead>(reader: &mut R) -> io::Result<u32> { pub fn adler32<R: BufRead>(mut reader: R) -> io::Result<u32> {
let mut h = Adler32::new(); let mut h = Adler32::new();
loop { loop {
let len = { let len = {
@ -151,7 +222,6 @@ pub fn adler32_reader<R: BufRead>(reader: &mut R) -> io::Result<u32> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use std::io::BufReader;
#[test] #[test]
fn zeroes() { fn zeroes() {
@ -198,12 +268,14 @@ mod tests {
assert_eq!(adler.checksum(), 0x8e88ef11); // from above assert_eq!(adler.checksum(), 0x8e88ef11); // from above
} }
#[cfg(feature = "std")]
#[test] #[test]
fn bufread() { fn bufread() {
use std::io::BufReader;
fn test(data: &[u8], checksum: u32) { fn test(data: &[u8], checksum: u32) {
// `BufReader` uses an 8 KB buffer, so this will test buffer refilling. // `BufReader` uses an 8 KB buffer, so this will test buffer refilling.
let mut buf = BufReader::new(data); let mut buf = BufReader::new(data);
let real_sum = adler32_reader(&mut buf).unwrap(); let real_sum = adler32(&mut buf).unwrap();
assert_eq!(checksum, real_sum); assert_eq!(checksum, real_sum);
} }

View File

@ -52,9 +52,9 @@ rust_library(
# buildifier: leave-alone # buildifier: leave-alone
deps = [ deps = [
"//third_party/cargo/vendor/bitflags-1.2.1:bitflags", "//third_party/cargo/vendor/bitflags-1.2.1:bitflags",
"//third_party/cargo/vendor/rusttype-0.9.2:rusttype", "//third_party/cargo/vendor/walkdir-2.3.2:walkdir",
"//third_party/cargo/vendor/walkdir-2.3.1:walkdir",
"//third_party/cargo/vendor/xdg-2.2.0:xdg", "//third_party/cargo/vendor/xdg-2.2.0:xdg",
"//third_party/cargo/vendor/xml-rs-0.8.3:xml_rs", "//third_party/cargo/vendor/xml-rs-0.8.3:xml_rs",
"//third_party/cargo/vendor/rusttype-0.9.2:rusttype",
], ],
) )

View File

@ -58,7 +58,7 @@ rust_library(
( (
"@rules_rust//rust/platform:x86_64-unknown-linux-gnu", "@rules_rust//rust/platform:x86_64-unknown-linux-gnu",
): [ ): [
"//third_party/cargo/vendor/libc-0.2.82:libc", "//third_party/cargo/vendor/libc-0.2.92:libc",
], ],
"//conditions:default": [], "//conditions:default": [],
}) + selects.with_or({ }) + selects.with_or({

View File

@ -1 +0,0 @@
{"files":{"Cargo.toml":"6513cb751f90bc8cb94ecc29bcaaecbe4299e4d90f7d3ee207ff6b4504820ee5","LICENSE-APACHE":"e3ba223bb1423f0aad8c3dfce0fe3148db48926d41e6fbc3afbbf5ff9e1c89cb","LICENSE-MIT":"9df9ba60a11af705f2e451b53762686e615d86f76b169cf075c3237730dbd7e2","LICENSE-ZLIB":"84b34dd7608f7fb9b17bd588a6bf392bf7de504e2716f024a77d89f1b145a151","README.md":"d4c58e84661f23490ef8662cc6309b6eacf42ab939b19eaeae032c12febdd823","changelog.md":"b3592fcef45a96b2442ed1dfb2a00ffbf11578c9186be8177a3633d44a76fb9e","rustfmt.toml":"eeb0dc37ccf6e6a628fc0144cb8e7a9ebb197552cb739f9c75d6ab79ebee15db","src/allocation.rs":"c5f74c27d785cbf138159d80eb943fb16de4ff3ec0041da4fe23384b4578de16","src/contiguous.rs":"288aa77eca807f47d28c4372f6eb3fd87d885dcaf886fb725c10fdbaf1fd27d0","src/lib.rs":"ad43ebca9480fb8a68e8173d7d8949d2c38d95b746d0bd5e9b3c2d9208925aa1","src/offset_of.rs":"5d98aacb37ec5ce7df3809e15b2682ee1972248b1fb1c444bbb013bbd6d98bf1","src/pod.rs":"b64399dac0d0dcc6179b4da48c02a15dee881afe858d27aed58253775016f4da","src/transparent.rs":"f0475aaf00daf458ddd4f28e049ed72d46b8a86f9a9244a5aa1a0eb019657e21","src/zeroable.rs":"1fc0b80cee39b7171b8b9627c7e4fc4b369a17237910353feb6dbf9662944450","tests/cast_slice_tests.rs":"f1cacfc4ceeacafdc3acc1694c5579793c8f7c0908c5b2bde17a347453368657","tests/derive.rs":"0e5f4637fb11ab087e8b9cf76212caafa37e01cedba71cf4f51356187691b46a","tests/doc_tests.rs":"0008789fc7281f581c8c91eac13ea4683f82cdeadadc4119c7b21b38f7d41577","tests/offset_of_tests.rs":"bd9690a817b0ac36e07e4dce98e8de08f246d7f6d5ebd8df27a8a955c32db435","tests/std_tests.rs":"69661f26dc385c38d6c2bd37a62ba476e81ef88b4ed6565f3a47dd173133365c"},"package":"41aa2ec95ca3b5c54cf73c91acf06d24f4495d5f1b1c12506ae3483d646177ac"}

View File

@ -0,0 +1 @@
{"files":{"Cargo.toml":"24ed52e1c8b6f028a51cf36509153c48e47f668dcd2cbf03221511f97e715de9","LICENSE-APACHE":"870e20c217d15bcfcbe53d7c5867cd8fac44a4ca0b41fc1eb843557e16063eba","LICENSE-MIT":"0b2d108c9c686a74ac312990ee8377902756a2a081a7af3b0f9d68abf0a8f1a1","LICENSE-ZLIB":"682b4c81b85e83ce6cc6e1ace38fdd97aeb4de0e972bd2b44aa0916c54af8c96","README.md":"dc60ed213002ac5c27c1dd753090832d3b882ea1c9b6ce9962891572830bcfb4","changelog.md":"29d25e2c3c7b357ca1451eaf04a3241547845e8e5d7858b8dc80f2adfdda078b","rustfmt.toml":"917eca93a0f65d5a2e76cde5813a76c088012fdebb41ac331a96181c82cdf6d5","src/allocation.rs":"1f7f937d3ef6c08d982a6385d85efd236c2d1d248986bec9123af067df677696","src/contiguous.rs":"af81aeb8ec7859a685348964f883b85c3aef1e2a38358d51b3a64252fade2bcd","src/lib.rs":"afdb84f8bc9a202f9a07c4a8897ec4284239fe907d273fda4a50576843020f4f","src/offset_of.rs":"db97a5018a8d56ad5382895593c3e44935356749646419b42524cdeeb25871df","src/pod.rs":"d1a87bc2d249dcfbf3566d2a81997e79b8c948b89d551d678174a77d98d69401","src/transparent.rs":"eb723ae91c57e3119b02af46b70e8b9028a905323112deb0f73db72f3f52c3f1","src/zeroable.rs":"5f381abadb2b0d48dd5629d5566d705e0f1d50d2f977d46b3bc3f258c689e730","tests/cast_slice_tests.rs":"aaf14cf6830ee38e659356e6b46c22d805f1c6b4aa0f494cf4fbde98f834fedb","tests/derive.rs":"ffd24f95388cd02493753112acb6522010667f54d1c60dd15fba64e2b40adc33","tests/doc_tests.rs":"eb4ce9cb167dbc1d6742b7d5c518c0636c77ce020c7cde28802d8dd67961bd15","tests/offset_of_tests.rs":"435a92c321865ddba9f29b81fc27c23f268e1dc12955a3c8b01ff2cc0c4f5615","tests/std_tests.rs":"ba0936ed2508b109bb4d3edda1294f61cda28118f511f9909dc6916be4e59207"},"package":"bed57e2090563b83ba8f83366628ce535a7584c9afa4c9fc0612a03925c6df58"}

View File

@ -46,7 +46,7 @@ rust_library(
"cargo-raze", "cargo-raze",
"manual", "manual",
], ],
version = "1.4.1", version = "1.5.1",
# buildifier: leave-alone # buildifier: leave-alone
deps = [ deps = [
], ],

View File

@ -13,7 +13,7 @@
[package] [package]
edition = "2018" edition = "2018"
name = "bytemuck" name = "bytemuck"
version = "1.4.1" version = "1.5.1"
authors = ["Lokathor <zefria@gmail.com>"] authors = ["Lokathor <zefria@gmail.com>"]
exclude = ["/pedantic.bat"] exclude = ["/pedantic.bat"]
description = "A crate for mucking around with piles of bytes." description = "A crate for mucking around with piles of bytes."

View File

@ -1,61 +1,61 @@
Apache License Apache License
Version 2.0, January 2004 Version 2.0, January 2004
http://www.apache.org/licenses/ http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions. 1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
(a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices stating that You changed the files; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work. APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
Copyright [yyyy] [name of copyright owner] Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.

View File

@ -1,9 +1,9 @@
MIT License MIT License
Copyright (c) 2019 Daniel "Lokathor" Gee. Copyright (c) 2019 Daniel "Lokathor" Gee.
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: 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 (including the next paragraph) shall be included in all copies or substantial portions of the Software. The above copyright notice and this permission notice (including the next paragraph) 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. 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,11 +1,11 @@
Copyright (c) 2019 Daniel "Lokathor" Gee. Copyright (c) 2019 Daniel "Lokathor" Gee.
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution. 3. This notice may not be removed or altered from any source distribution.

View File

@ -1,27 +1,27 @@
[![License:Zlib](https://img.shields.io/badge/License-Zlib-brightgreen.svg)](https://opensource.org/licenses/Zlib) [![License:Zlib](https://img.shields.io/badge/License-Zlib-brightgreen.svg)](https://opensource.org/licenses/Zlib)
![Minimum Rust Version](https://img.shields.io/badge/Min%20Rust-1.34-green.svg) ![Minimum Rust Version](https://img.shields.io/badge/Min%20Rust-1.34-green.svg)
[![crates.io](https://img.shields.io/crates/v/bytemuck.svg)](https://crates.io/crates/bytemuck) [![crates.io](https://img.shields.io/crates/v/bytemuck.svg)](https://crates.io/crates/bytemuck)
[![docs.rs](https://docs.rs/bytemuck/badge.svg)](https://docs.rs/bytemuck/) [![docs.rs](https://docs.rs/bytemuck/badge.svg)](https://docs.rs/bytemuck/)
# bytemuck # bytemuck
A crate for mucking around with piles of bytes. A crate for mucking around with piles of bytes.
## Extensions ## Extensions
There is experimental support for the `Zeroable` trait being derived through a There is experimental support for the `Zeroable` trait being derived through a
proc-macro. I'm not the author of that crate, please file bugs with that crate proc-macro. I'm not the author of that crate, please file bugs with that crate
in the other repo. in the other repo.
* https://github.com/rodrimati1992/zeroable_crates * https://github.com/rodrimati1992/zeroable_crates
## Stability ## Stability
The goal is to stay at 1.y.z until _at least_ the next edition of Rust. The goal is to stay at 1.y.z until _at least_ the next edition of Rust.
I consider any increase of the Minimum Rust Version to be a semver breaking change, I consider any increase of the Minimum Rust Version to be a semver breaking change,
so `rustc-1.34` will continue to be supported for at least the rest of the so `rustc-1.34` will continue to be supported for at least the rest of the
`bytemuck-1.y.z` series of the crate. `bytemuck-1.y.z` series of the crate.
(The secret goal is to get all of this functionality into the standard library (The secret goal is to get all of this functionality into the standard library
some day so that we don't even need to import a crate to do all this fun stuff.) some day so that we don't even need to import a crate to do all this fun stuff.)

View File

@ -1,62 +1,84 @@
# `bytemuck` changelog # `bytemuck` changelog
## 1.4 ## 1.5.1
* [icewind1991](https://github.com/icewind1991) has contributed the proc-macros * Fix `bytes_of` failing on zero sized types.
for deriving impls of `Pod`, `TransparentWrapper`, `Zeroable`!! Everyone has [PR 53](https://github.com/Lokathor/bytemuck/pull/53)
been waiting for this one folks! It's a big deal. Just enable the `derive`
cargo feature and then you'll be able to derive the traits on your types. It ## 1.5
generates all the appropriate tests for you.
* The `zeroable_maybe_uninit` feature now adds a `Zeroable` impl to the * Added `pod_collect_to_vec`, which will gather a slice into a vec,
`MaybeUninit` type. This is only behind a feature flag because `MaybeUninit` allowing you to change the pod type while also safely ignoring alignment.
didn't exist back in `1.34.0` (the minimum rust version of `bytemuck`). [PR 50](https://github.com/Lokathor/bytemuck/pull/50)
## 1.3.1 ## 1.4.2
* The entire crate is now available under the `Apache-2.0 OR MIT` license as * [Kimundi](https://github.com/Kimundi) fixed an issue that could make `try_zeroed_box`
well as the previous `Zlib` license stack overflow for large values at low optimization levels.
[#24](https://github.com/Lokathor/bytemuck/pull/24). [PR 43](https://github.com/Lokathor/bytemuck/pull/43)
* [HeroicKatora](https://github.com/HeroicKatora) added the
`try_zeroed_slice_box` function ## 1.4.1
[#10](https://github.com/Lokathor/bytemuck/pull/17). `zeroed_slice_box` is
also available. * [thomcc](https://github.com/thomcc) fixed up the CI and patched over a soundness hole in `offset_of!`.
* The `offset_of!` macro now supports a 2-arg version. For types that impl [PR 38](https://github.com/Lokathor/bytemuck/pull/38)
Default, it'll just make an instance using `default` and then call over to the
3-arg version. ## 1.4
* The `PodCastError` type now supports `Hash` and `Display`. Also if you enable
the `extern_crate_std` feature then it will support `std::error::Error`. * [icewind1991](https://github.com/icewind1991) has contributed the proc-macros
* We now provide a `TransparentWrapper<T>` impl for `core::num::Wrapper<T>`. for deriving impls of `Pod`, `TransparentWrapper`, `Zeroable`!! Everyone has
* The error type of `try_from_bytes` and `try_from_bytes_mut` when the input been waiting for this one folks! It's a big deal. Just enable the `derive`
isn't aligned has been corrected from being `AlignmentMismatch` (intended for cargo feature and then you'll be able to derive the traits on your types. It
allocation casting only) to `TargetAlignmentGreaterAndInputNotAligned`. generates all the appropriate tests for you.
* The `zeroable_maybe_uninit` feature now adds a `Zeroable` impl to the
## 1.3.0 `MaybeUninit` type. This is only behind a feature flag because `MaybeUninit`
didn't exist back in `1.34.0` (the minimum rust version of `bytemuck`).
* Had a bug because the CI was messed up! It wasn't soundness related, because
it prevented the crate from building entirely if the `extern_crate_alloc` ## 1.3.1
feature was used. Still, this is yanked, sorry.
* The entire crate is now available under the `Apache-2.0 OR MIT` license as
## 1.2.0 well as the previous `Zlib` license
[#24](https://github.com/Lokathor/bytemuck/pull/24).
* [thomcc](https://github.com/thomcc) added many things: * [HeroicKatora](https://github.com/HeroicKatora) added the
* A fully sound `offset_of!` macro `try_zeroed_slice_box` function
[#10](https://github.com/Lokathor/bytemuck/pull/10) [#10](https://github.com/Lokathor/bytemuck/pull/17). `zeroed_slice_box` is
* A `Contiguous` trait for when you've got enums with declared values also available.
all in a row [#12](https://github.com/Lokathor/bytemuck/pull/12) * The `offset_of!` macro now supports a 2-arg version. For types that impl
* A `TransparentWrapper` marker trait for when you want to more clearly Default, it'll just make an instance using `default` and then call over to the
enable adding and removing a wrapper struct to its inner value 3-arg version.
[#15](https://github.com/Lokathor/bytemuck/pull/15) * The `PodCastError` type now supports `Hash` and `Display`. Also if you enable
* Now MIRI is run on CI in every single push! the `extern_crate_std` feature then it will support `std::error::Error`.
[#16](https://github.com/Lokathor/bytemuck/pull/16) * We now provide a `TransparentWrapper<T>` impl for `core::num::Wrapper<T>`.
* The error type of `try_from_bytes` and `try_from_bytes_mut` when the input
## 1.1.0 isn't aligned has been corrected from being `AlignmentMismatch` (intended for
allocation casting only) to `TargetAlignmentGreaterAndInputNotAligned`.
* [SimonSapin](https://github.com/SimonSapin) added `from_bytes`,
`from_bytes_mut`, `try_from_bytes`, and `try_from_bytes_mut` ([PR ## 1.3.0
Link](https://github.com/Lokathor/bytemuck/pull/8))
* Had a bug because the CI was messed up! It wasn't soundness related, because
## 1.0.1 it prevented the crate from building entirely if the `extern_crate_alloc`
feature was used. Still, this is yanked, sorry.
* Changed to the [zlib](https://opensource.org/licenses/Zlib) license.
* Added much more proper documentation. ## 1.2.0
* Reduced the minimum Rust version to 1.34
* [thomcc](https://github.com/thomcc) added many things:
* A fully sound `offset_of!` macro
[#10](https://github.com/Lokathor/bytemuck/pull/10)
* A `Contiguous` trait for when you've got enums with declared values
all in a row [#12](https://github.com/Lokathor/bytemuck/pull/12)
* A `TransparentWrapper` marker trait for when you want to more clearly
enable adding and removing a wrapper struct to its inner value
[#15](https://github.com/Lokathor/bytemuck/pull/15)
* Now MIRI is run on CI in every single push!
[#16](https://github.com/Lokathor/bytemuck/pull/16)
## 1.1.0
* [SimonSapin](https://github.com/SimonSapin) added `from_bytes`,
`from_bytes_mut`, `try_from_bytes`, and `try_from_bytes_mut` ([PR
Link](https://github.com/Lokathor/bytemuck/pull/8))
## 1.0.1
* Changed to the [zlib](https://opensource.org/licenses/Zlib) license.
* Added much more proper documentation.
* Reduced the minimum Rust version to 1.34

View File

@ -1,16 +1,16 @@
# Based on # Based on
# https://github.com/rust-lang/rustfmt/blob/rustfmt-1.4.19/Configurations.md # https://github.com/rust-lang/rustfmt/blob/rustfmt-1.4.19/Configurations.md
# Stable # Stable
edition = "2018" edition = "2018"
fn_args_layout = "Compressed" fn_args_layout = "Compressed"
max_width = 80 max_width = 80
tab_spaces = 2 tab_spaces = 2
use_field_init_shorthand = true use_field_init_shorthand = true
use_try_shorthand = true use_try_shorthand = true
use_small_heuristics = "Max" use_small_heuristics = "Max"
# Unstable # Unstable
format_code_in_doc_comments = true format_code_in_doc_comments = true
merge_imports = true merge_imports = true
wrap_comments = true wrap_comments = true

View File

@ -1,166 +1,212 @@
#![cfg(feature = "extern_crate_alloc")] #![cfg(feature = "extern_crate_alloc")]
//! Stuff to boost things in the `alloc` crate. //! Stuff to boost things in the `alloc` crate.
//! //!
//! * You must enable the `extern_crate_alloc` feature of `bytemuck` or you will //! * You must enable the `extern_crate_alloc` feature of `bytemuck` or you will
//! not be able to use this module! //! not be able to use this module!
use super::*; use super::*;
use alloc::{ use alloc::{
alloc::{alloc_zeroed, Layout}, alloc::{alloc_zeroed, Layout},
boxed::Box, boxed::Box,
vec::Vec, vec,
}; vec::Vec,
};
/// As [`try_cast_box`](try_cast_box), but unwraps for you. use core::convert::TryInto;
#[inline]
pub fn cast_box<A: Pod, B: Pod>(input: Box<A>) -> Box<B> { /// As [`try_cast_box`](try_cast_box), but unwraps for you.
try_cast_box(input).map_err(|(e, _v)| e).unwrap() #[inline]
} pub fn cast_box<A: Pod, B: Pod>(input: Box<A>) -> Box<B> {
try_cast_box(input).map_err(|(e, _v)| e).unwrap()
/// Attempts to cast the content type of a [`Box`](alloc::boxed::Box). }
///
/// On failure you get back an error along with the starting `Box`. /// Attempts to cast the content type of a [`Box`](alloc::boxed::Box).
/// ///
/// ## Failure /// On failure you get back an error along with the starting `Box`.
/// ///
/// * The start and end content type of the `Box` must have the exact same /// ## Failure
/// alignment. ///
/// * The start and end size of the `Box` must have the exact same size. /// * The start and end content type of the `Box` must have the exact same
#[inline] /// alignment.
pub fn try_cast_box<A: Pod, B: Pod>( /// * The start and end size of the `Box` must have the exact same size.
input: Box<A>, #[inline]
) -> Result<Box<B>, (PodCastError, Box<A>)> { pub fn try_cast_box<A: Pod, B: Pod>(
if align_of::<A>() != align_of::<B>() { input: Box<A>,
Err((PodCastError::AlignmentMismatch, input)) ) -> Result<Box<B>, (PodCastError, Box<A>)> {
} else if size_of::<A>() != size_of::<B>() { if align_of::<A>() != align_of::<B>() {
Err((PodCastError::SizeMismatch, input)) Err((PodCastError::AlignmentMismatch, input))
} else { } else if size_of::<A>() != size_of::<B>() {
// Note(Lokathor): This is much simpler than with the Vec casting! Err((PodCastError::SizeMismatch, input))
let ptr: *mut B = Box::into_raw(input) as *mut B; } else {
Ok(unsafe { Box::from_raw(ptr) }) // Note(Lokathor): This is much simpler than with the Vec casting!
} let ptr: *mut B = Box::into_raw(input) as *mut B;
} Ok(unsafe { Box::from_raw(ptr) })
}
/// Allocates a `Box<T>` with all of the contents being zeroed out. }
///
/// This uses the global allocator to create a zeroed allocation and _then_ /// Allocates a `Box<T>` with all of the contents being zeroed out.
/// turns it into a Box. In other words, it's 100% assured that the zeroed data ///
/// won't be put temporarily on the stack. You can make a box of any size /// This uses the global allocator to create a zeroed allocation and _then_
/// without fear of a stack overflow. /// turns it into a Box. In other words, it's 100% assured that the zeroed data
/// /// won't be put temporarily on the stack. You can make a box of any size
/// ## Failure /// without fear of a stack overflow.
/// ///
/// This fails if the allocation fails. /// ## Failure
#[inline] ///
pub fn try_zeroed_box<T: Zeroable>() -> Result<Box<T>, ()> { /// This fails if the allocation fails.
if size_of::<T>() == 0 { #[inline]
return Ok(Box::new(T::zeroed())); pub fn try_zeroed_box<T: Zeroable>() -> Result<Box<T>, ()> {
} if size_of::<T>() == 0 {
let layout = // This will not allocate but simple create a dangling slice pointer.
Layout::from_size_align(size_of::<T>(), align_of::<T>()).unwrap(); // NB: We go the way via a push to `Vec<T>` to ensure the compiler
let ptr = unsafe { alloc_zeroed(layout) }; // does not allocate space for T on the stack even if the branch
if ptr.is_null() { // would not be taken.
// we don't know what the error is because `alloc_zeroed` is a dumb API let mut vec = Vec::with_capacity(1);
Err(()) vec.resize_with(1, || T::zeroed());
} else { let ptr: Box<[T; 1]> = vec.into_boxed_slice().try_into().ok().unwrap();
Ok(unsafe { Box::<T>::from_raw(ptr as *mut T) }) debug_assert!(
} align_of::<[T; 1]>() == align_of::<T>()
} && size_of::<[T; 1]>() == size_of::<T>()
);
/// As [`try_zeroed_box`], but unwraps for you. // NB: We basically do the same as in try_cast_box here:
#[inline] let ptr: Box<T> = unsafe { Box::from_raw(Box::into_raw(ptr) as *mut _) };
pub fn zeroed_box<T: Zeroable>() -> Box<T> { return Ok(ptr);
try_zeroed_box().unwrap() }
} let layout =
Layout::from_size_align(size_of::<T>(), align_of::<T>()).unwrap();
/// Allocates a `Box<[T]>` with all contents being zeroed out. let ptr = unsafe { alloc_zeroed(layout) };
/// if ptr.is_null() {
/// This uses the global allocator to create a zeroed allocation and _then_ // we don't know what the error is because `alloc_zeroed` is a dumb API
/// turns it into a Box. In other words, it's 100% assured that the zeroed data Err(())
/// won't be put temporarily on the stack. You can make a box of any size } else {
/// without fear of a stack overflow. Ok(unsafe { Box::<T>::from_raw(ptr as *mut T) })
/// }
/// ## Failure }
///
/// This fails if the allocation fails. /// As [`try_zeroed_box`], but unwraps for you.
#[inline] #[inline]
pub fn try_zeroed_slice_box<T: Zeroable>( pub fn zeroed_box<T: Zeroable>() -> Box<T> {
length: usize, try_zeroed_box().unwrap()
) -> Result<Box<[T]>, ()> { }
if size_of::<T>() == 0 {
// This will not allocate but simple create a dangling slice pointer. /// Allocates a `Box<[T]>` with all contents being zeroed out.
let mut vec = Vec::with_capacity(length); ///
vec.resize_with(length, || T::zeroed()); /// This uses the global allocator to create a zeroed allocation and _then_
return Ok(vec.into_boxed_slice()); /// turns it into a Box. In other words, it's 100% assured that the zeroed data
} /// won't be put temporarily on the stack. You can make a box of any size
if length == 0 { /// without fear of a stack overflow.
// This will also not allocate. ///
return Ok(Vec::new().into_boxed_slice()); /// ## Failure
} ///
// For Pod types, the layout of the array/slice is equivalent to repeating the type. /// This fails if the allocation fails.
let layout_length = size_of::<T>().checked_mul(length).ok_or(())?; #[inline]
assert!(layout_length != 0); pub fn try_zeroed_slice_box<T: Zeroable>(
let layout = length: usize,
Layout::from_size_align(layout_length, align_of::<T>()).map_err(|_| ())?; ) -> Result<Box<[T]>, ()> {
let ptr = unsafe { alloc_zeroed(layout) }; if size_of::<T>() == 0 {
if ptr.is_null() { // This will not allocate but simple create a dangling slice pointer.
// we don't know what the error is because `alloc_zeroed` is a dumb API let mut vec = Vec::with_capacity(length);
Err(()) vec.resize_with(length, || T::zeroed());
} else { return Ok(vec.into_boxed_slice());
let slice = }
unsafe { core::slice::from_raw_parts_mut(ptr as *mut T, length) }; if length == 0 {
Ok(unsafe { Box::<[T]>::from_raw(slice) }) // This will also not allocate.
} return Ok(Vec::new().into_boxed_slice());
} }
// For Pod types, the layout of the array/slice is equivalent to repeating the
/// As [`try_zeroed_slice_box`](try_zeroed_slice_box), but unwraps for you. // type.
pub fn zeroed_slice_box<T: Zeroable>(length: usize) -> Box<[T]> { let layout_length = size_of::<T>().checked_mul(length).ok_or(())?;
try_zeroed_slice_box(length).unwrap() assert!(layout_length != 0);
} let layout =
Layout::from_size_align(layout_length, align_of::<T>()).map_err(|_| ())?;
/// As [`try_cast_vec`](try_cast_vec), but unwraps for you. let ptr = unsafe { alloc_zeroed(layout) };
#[inline] if ptr.is_null() {
pub fn cast_vec<A: Pod, B: Pod>(input: Vec<A>) -> Vec<B> { // we don't know what the error is because `alloc_zeroed` is a dumb API
try_cast_vec(input).map_err(|(e, _v)| e).unwrap() Err(())
} } else {
let slice =
/// Attempts to cast the content type of a [`Vec`](alloc::vec::Vec). unsafe { core::slice::from_raw_parts_mut(ptr as *mut T, length) };
/// Ok(unsafe { Box::<[T]>::from_raw(slice) })
/// On failure you get back an error along with the starting `Vec`. }
/// }
/// ## Failure
/// /// As [`try_zeroed_slice_box`](try_zeroed_slice_box), but unwraps for you.
/// * The start and end content type of the `Vec` must have the exact same pub fn zeroed_slice_box<T: Zeroable>(length: usize) -> Box<[T]> {
/// alignment. try_zeroed_slice_box(length).unwrap()
/// * The start and end size of the `Vec` must have the exact same size. }
/// * In the future this second restriction might be lessened by having the
/// capacity and length get adjusted during transmutation, but for now it's /// As [`try_cast_vec`](try_cast_vec), but unwraps for you.
/// absolute. #[inline]
#[inline] pub fn cast_vec<A: Pod, B: Pod>(input: Vec<A>) -> Vec<B> {
pub fn try_cast_vec<A: Pod, B: Pod>( try_cast_vec(input).map_err(|(e, _v)| e).unwrap()
input: Vec<A>, }
) -> Result<Vec<B>, (PodCastError, Vec<A>)> {
if align_of::<A>() != align_of::<B>() { /// Attempts to cast the content type of a [`Vec`](alloc::vec::Vec).
Err((PodCastError::AlignmentMismatch, input)) ///
} else if size_of::<A>() != size_of::<B>() { /// On failure you get back an error along with the starting `Vec`.
// Note(Lokathor): Under some conditions it would be possible to cast ///
// between Vec content types of the same alignment but different sizes by /// ## Failure
// changing the capacity and len values in the output Vec. However, we will ///
// not attempt that for now. /// * The start and end content type of the `Vec` must have the exact same
Err((PodCastError::SizeMismatch, input)) /// alignment.
} else { /// * The start and end size of the `Vec` must have the exact same size.
// Note(Lokathor): First we record the length and capacity, which don't have /// * In the future this second restriction might be lessened by having the
// any secret provenance metadata. /// capacity and length get adjusted during transmutation, but for now it's
let length: usize = input.len(); /// absolute.
let capacity: usize = input.capacity(); #[inline]
// Note(Lokathor): Next we "pre-forget" the old Vec by wrapping with pub fn try_cast_vec<A: Pod, B: Pod>(
// ManuallyDrop, because if we used `core::mem::forget` after taking the input: Vec<A>,
// pointer then that would invalidate our pointer. In nightly there's a ) -> Result<Vec<B>, (PodCastError, Vec<A>)> {
// "into raw parts" method, which we can switch this too eventually. if align_of::<A>() != align_of::<B>() {
let mut manual_drop_vec = ManuallyDrop::new(input); Err((PodCastError::AlignmentMismatch, input))
let vec_ptr: *mut A = manual_drop_vec.as_mut_ptr(); } else if size_of::<A>() != size_of::<B>() {
let ptr: *mut B = vec_ptr as *mut B; // Note(Lokathor): Under some conditions it would be possible to cast
Ok(unsafe { Vec::from_raw_parts(ptr, length, capacity) }) // between Vec content types of the same alignment but different sizes by
} // changing the capacity and len values in the output Vec. However, we will
} // not attempt that for now.
Err((PodCastError::SizeMismatch, input))
} else {
// Note(Lokathor): First we record the length and capacity, which don't have
// any secret provenance metadata.
let length: usize = input.len();
let capacity: usize = input.capacity();
// Note(Lokathor): Next we "pre-forget" the old Vec by wrapping with
// ManuallyDrop, because if we used `core::mem::forget` after taking the
// pointer then that would invalidate our pointer. In nightly there's a
// "into raw parts" method, which we can switch this too eventually.
let mut manual_drop_vec = ManuallyDrop::new(input);
let vec_ptr: *mut A = manual_drop_vec.as_mut_ptr();
let ptr: *mut B = vec_ptr as *mut B;
Ok(unsafe { Vec::from_raw_parts(ptr, length, capacity) })
}
}
/// This "collects" a slice of pod data into a vec of a different pod type.
///
/// Unlike with [`cast_slice`] and [`cast_slice_mut`], this will always work.
///
/// The output vec will be of a minimal size/capacity to hold the slice given.
///
/// ```rust
/// # use bytemuck::*;
/// let halfwords: [u16; 4] = [5, 6, 7, 8];
/// let vec_of_words: Vec<u32> = pod_collect_to_vec(&halfwords);
/// if cfg!(target_endian = "little") {
/// assert_eq!(&vec_of_words[..], &[0x0006_0005, 0x0008_0007][..])
/// } else {
/// assert_eq!(&vec_of_words[..], &[0x0005_0006, 0x0007_0008][..])
/// }
/// ```
pub fn pod_collect_to_vec<A: Pod, B: Pod>(src: &[A]) -> Vec<B> {
let src_size = size_of_val(src);
// Note(Lokathor): dst_count is rounded up so that the dest will always be at
// least as many bytes as the src.
let dst_count = src_size / size_of::<B>()
+ if src_size % size_of::<B>() != 0 { 1 } else { 0 };
let mut dst = vec![B::zeroed(); dst_count];
let src_bytes: &[u8] = cast_slice(src);
let dst_bytes: &mut [u8] = cast_slice_mut(&mut dst[..]);
dst_bytes[..src_size].copy_from_slice(src_bytes);
dst
}

View File

@ -1,203 +1,203 @@
use super::*; use super::*;
use core::mem::{size_of, transmute_copy}; use core::mem::{size_of, transmute_copy};
/// A trait indicating that: /// A trait indicating that:
/// ///
/// 1. A type has an equivalent representation to some known integral type. /// 1. A type has an equivalent representation to some known integral type.
/// 2. All instances of this type fall in a fixed range of values. /// 2. All instances of this type fall in a fixed range of values.
/// 3. Within that range, there are no gaps. /// 3. Within that range, there are no gaps.
/// ///
/// This is generally useful for fieldless enums (aka "c-style" enums), however /// This is generally useful for fieldless enums (aka "c-style" enums), however
/// it's important that it only be used for those with an explicit `#[repr]`, as /// it's important that it only be used for those with an explicit `#[repr]`, as
/// `#[repr(Rust)]` fieldess enums have an unspecified layout. /// `#[repr(Rust)]` fieldess enums have an unspecified layout.
/// ///
/// Additionally, you shouldn't assume that all implementations are enums. Any /// Additionally, you shouldn't assume that all implementations are enums. Any
/// type which meets the requirements above while following the rules under /// type which meets the requirements above while following the rules under
/// "Safety" below is valid. /// "Safety" below is valid.
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```
/// # use bytemuck::Contiguous; /// # use bytemuck::Contiguous;
/// #[repr(u8)] /// #[repr(u8)]
/// #[derive(Debug, Copy, Clone, PartialEq)] /// #[derive(Debug, Copy, Clone, PartialEq)]
/// enum Foo { /// enum Foo {
/// A = 0, /// A = 0,
/// B = 1, /// B = 1,
/// C = 2, /// C = 2,
/// D = 3, /// D = 3,
/// E = 4, /// E = 4,
/// } /// }
/// unsafe impl Contiguous for Foo { /// unsafe impl Contiguous for Foo {
/// type Int = u8; /// type Int = u8;
/// const MIN_VALUE: u8 = Foo::A as u8; /// const MIN_VALUE: u8 = Foo::A as u8;
/// const MAX_VALUE: u8 = Foo::E as u8; /// const MAX_VALUE: u8 = Foo::E as u8;
/// } /// }
/// assert_eq!(Foo::from_integer(3).unwrap(), Foo::D); /// assert_eq!(Foo::from_integer(3).unwrap(), Foo::D);
/// assert_eq!(Foo::from_integer(8), None); /// assert_eq!(Foo::from_integer(8), None);
/// assert_eq!(Foo::C.into_integer(), 2); /// assert_eq!(Foo::C.into_integer(), 2);
/// ``` /// ```
/// # Safety /// # Safety
/// ///
/// This is an unsafe trait, and incorrectly implementing it is undefined /// This is an unsafe trait, and incorrectly implementing it is undefined
/// behavior. /// behavior.
/// ///
/// Informally, by implementing it, you're asserting that `C` is identical to /// Informally, by implementing it, you're asserting that `C` is identical to
/// the integral type `C::Int`, and that every `C` falls between `C::MIN_VALUE` /// the integral type `C::Int`, and that every `C` falls between `C::MIN_VALUE`
/// and `C::MAX_VALUE` exactly once, without any gaps. /// and `C::MAX_VALUE` exactly once, without any gaps.
/// ///
/// Precisely, the guarantees you must uphold when implementing `Contiguous` for /// Precisely, the guarantees you must uphold when implementing `Contiguous` for
/// some type `C` are: /// some type `C` are:
/// ///
/// 1. The size of `C` and `C::Int` must be the same, and neither may be a ZST. /// 1. The size of `C` and `C::Int` must be the same, and neither may be a ZST.
/// (Note: alignment is explicitly allowed to differ) /// (Note: alignment is explicitly allowed to differ)
/// ///
/// 2. `C::Int` must be a primitive integer, and not a wrapper type. In the /// 2. `C::Int` must be a primitive integer, and not a wrapper type. In the
/// future, this may be lifted to include cases where the behavior is /// future, this may be lifted to include cases where the behavior is
/// identical for a relevant set of traits (Ord, arithmetic, ...). /// identical for a relevant set of traits (Ord, arithmetic, ...).
/// ///
/// 3. All `C::Int`s which are in the *inclusive* range between `C::MIN_VALUE` /// 3. All `C::Int`s which are in the *inclusive* range between `C::MIN_VALUE`
/// and `C::MAX_VALUE` are bitwise identical to unique valid instances of /// and `C::MAX_VALUE` are bitwise identical to unique valid instances of
/// `C`. /// `C`.
/// ///
/// 4. There exist no instances of `C` such that their bitpatterns, when /// 4. There exist no instances of `C` such that their bitpatterns, when
/// interpreted as instances of `C::Int`, fall outside of the `MAX_VALUE` / /// interpreted as instances of `C::Int`, fall outside of the `MAX_VALUE` /
/// `MIN_VALUE` range -- It is legal for unsafe code to assume that if it /// `MIN_VALUE` range -- It is legal for unsafe code to assume that if it
/// gets a `C` that implements `Contiguous`, it is in the appropriate range. /// gets a `C` that implements `Contiguous`, it is in the appropriate range.
/// ///
/// 5. Finally, you promise not to provide overridden implementations of /// 5. Finally, you promise not to provide overridden implementations of
/// `Contiguous::from_integer` and `Contiguous::into_integer`. /// `Contiguous::from_integer` and `Contiguous::into_integer`.
/// ///
/// For clarity, the following rules could be derived from the above, but are /// For clarity, the following rules could be derived from the above, but are
/// listed explicitly: /// listed explicitly:
/// ///
/// - `C::MAX_VALUE` must be greater or equal to `C::MIN_VALUE` (therefore, `C` /// - `C::MAX_VALUE` must be greater or equal to `C::MIN_VALUE` (therefore, `C`
/// must be an inhabited type). /// must be an inhabited type).
/// ///
/// - There exist no two values between `MIN_VALUE` and `MAX_VALUE` such that /// - There exist no two values between `MIN_VALUE` and `MAX_VALUE` such that
/// when interpreted as a `C` they are considered identical (by, say, match). /// when interpreted as a `C` they are considered identical (by, say, match).
pub unsafe trait Contiguous: Copy + 'static { pub unsafe trait Contiguous: Copy + 'static {
/// The primitive integer type with an identical representation to this /// The primitive integer type with an identical representation to this
/// type. /// type.
/// ///
/// Contiguous is broadly intended for use with fieldless enums, and for /// Contiguous is broadly intended for use with fieldless enums, and for
/// these the correct integer type is easy: The enum should have a /// these the correct integer type is easy: The enum should have a
/// `#[repr(Int)]` or `#[repr(C)]` attribute, (if it does not, it is /// `#[repr(Int)]` or `#[repr(C)]` attribute, (if it does not, it is
/// *unsound* to implement `Contiguous`!). /// *unsound* to implement `Contiguous`!).
/// ///
/// - For `#[repr(Int)]`, use the listed `Int`. e.g. `#[repr(u8)]` should /// - For `#[repr(Int)]`, use the listed `Int`. e.g. `#[repr(u8)]` should
/// use `type Int = u8`. /// use `type Int = u8`.
/// ///
/// - For `#[repr(C)]`, use whichever type the C compiler will use to /// - For `#[repr(C)]`, use whichever type the C compiler will use to
/// represent the given enum. This is usually `c_int` (from `std::os::raw` /// represent the given enum. This is usually `c_int` (from `std::os::raw`
/// or `libc`), but it's up to you to make the determination as the /// or `libc`), but it's up to you to make the determination as the
/// implementer of the unsafe trait. /// implementer of the unsafe trait.
/// ///
/// For precise rules, see the list under "Safety" above. /// For precise rules, see the list under "Safety" above.
type Int: Copy + Ord; type Int: Copy + Ord;
/// The upper *inclusive* bound for valid instances of this type. /// The upper *inclusive* bound for valid instances of this type.
const MAX_VALUE: Self::Int; const MAX_VALUE: Self::Int;
/// The lower *inclusive* bound for valid instances of this type. /// The lower *inclusive* bound for valid instances of this type.
const MIN_VALUE: Self::Int; const MIN_VALUE: Self::Int;
/// If `value` is within the range for valid instances of this type, /// If `value` is within the range for valid instances of this type,
/// returns `Some(converted_value)`, otherwise, returns `None`. /// returns `Some(converted_value)`, otherwise, returns `None`.
/// ///
/// This is a trait method so that you can write `value.into_integer()` in /// This is a trait method so that you can write `value.into_integer()` in
/// your code. It is a contract of this trait that if you implement /// your code. It is a contract of this trait that if you implement
/// `Contiguous` on your type you **must not** override this method. /// `Contiguous` on your type you **must not** override this method.
/// ///
/// # Panics /// # Panics
/// ///
/// We will not panic for any correct implementation of `Contiguous`, but /// We will not panic for any correct implementation of `Contiguous`, but
/// *may* panic if we detect an incorrect one. /// *may* panic if we detect an incorrect one.
/// ///
/// This is undefined behavior regardless, so it could have been the nasal /// This is undefined behavior regardless, so it could have been the nasal
/// demons at that point anyway ;). /// demons at that point anyway ;).
#[inline] #[inline]
fn from_integer(value: Self::Int) -> Option<Self> { fn from_integer(value: Self::Int) -> Option<Self> {
// Guard against an illegal implementation of Contiguous. Annoyingly we // Guard against an illegal implementation of Contiguous. Annoyingly we
// can't rely on `transmute` to do this for us (see below), but // can't rely on `transmute` to do this for us (see below), but
// whatever, this gets compiled into nothing in release. // whatever, this gets compiled into nothing in release.
assert!(size_of::<Self>() == size_of::<Self::Int>()); assert!(size_of::<Self>() == size_of::<Self::Int>());
if Self::MIN_VALUE <= value && value <= Self::MAX_VALUE { if Self::MIN_VALUE <= value && value <= Self::MAX_VALUE {
// SAFETY: We've checked their bounds (and their size, even though // SAFETY: We've checked their bounds (and their size, even though
// they've sworn under the Oath Of Unsafe Rust that that already // they've sworn under the Oath Of Unsafe Rust that that already
// matched) so this is allowed by `Contiguous`'s unsafe contract. // matched) so this is allowed by `Contiguous`'s unsafe contract.
// //
// So, the `transmute_copy`. ideally we'd use transmute here, which // So, the `transmute_copy`. ideally we'd use transmute here, which
// is more obviously safe. Sadly, we can't, as these types still // is more obviously safe. Sadly, we can't, as these types still
// have unspecified sizes. // have unspecified sizes.
Some(unsafe { transmute_copy::<Self::Int, Self>(&value) }) Some(unsafe { transmute_copy::<Self::Int, Self>(&value) })
} else { } else {
None None
} }
} }
/// Perform the conversion from `C` into the underlying integral type. This /// Perform the conversion from `C` into the underlying integral type. This
/// mostly exists otherwise generic code would need unsafe for the `value as /// mostly exists otherwise generic code would need unsafe for the `value as
/// integer` /// integer`
/// ///
/// This is a trait method so that you can write `value.into_integer()` in /// This is a trait method so that you can write `value.into_integer()` in
/// your code. It is a contract of this trait that if you implement /// your code. It is a contract of this trait that if you implement
/// `Contiguous` on your type you **must not** override this method. /// `Contiguous` on your type you **must not** override this method.
/// ///
/// # Panics /// # Panics
/// ///
/// We will not panic for any correct implementation of `Contiguous`, but /// We will not panic for any correct implementation of `Contiguous`, but
/// *may* panic if we detect an incorrect one. /// *may* panic if we detect an incorrect one.
/// ///
/// This is undefined behavior regardless, so it could have been the nasal /// This is undefined behavior regardless, so it could have been the nasal
/// demons at that point anyway ;). /// demons at that point anyway ;).
#[inline] #[inline]
fn into_integer(self) -> Self::Int { fn into_integer(self) -> Self::Int {
// Guard against an illegal implementation of Contiguous. Annoyingly we // Guard against an illegal implementation of Contiguous. Annoyingly we
// can't rely on `transmute` to do the size check for us (see // can't rely on `transmute` to do the size check for us (see
// `from_integer's comment`), but whatever, this gets compiled into // `from_integer's comment`), but whatever, this gets compiled into
// nothing in release. Note that we don't check the result of cast // nothing in release. Note that we don't check the result of cast
assert!(size_of::<Self>() == size_of::<Self::Int>()); assert!(size_of::<Self>() == size_of::<Self::Int>());
// SAFETY: The unsafe contract requires that these have identical // SAFETY: The unsafe contract requires that these have identical
// representations, and that the range be entirely valid. Using // representations, and that the range be entirely valid. Using
// transmute_copy instead of transmute here is annoying, but is required // transmute_copy instead of transmute here is annoying, but is required
// as `Self` and `Self::Int` have unspecified sizes still. // as `Self` and `Self::Int` have unspecified sizes still.
unsafe { transmute_copy::<Self, Self::Int>(&self) } unsafe { transmute_copy::<Self, Self::Int>(&self) }
} }
} }
macro_rules! impl_contiguous { macro_rules! impl_contiguous {
($($src:ty as $repr:ident in [$min:expr, $max:expr];)*) => {$( ($($src:ty as $repr:ident in [$min:expr, $max:expr];)*) => {$(
unsafe impl Contiguous for $src { unsafe impl Contiguous for $src {
type Int = $repr; type Int = $repr;
const MAX_VALUE: $repr = $max; const MAX_VALUE: $repr = $max;
const MIN_VALUE: $repr = $min; const MIN_VALUE: $repr = $min;
} }
)*}; )*};
} }
impl_contiguous! { impl_contiguous! {
bool as u8 in [0, 1]; bool as u8 in [0, 1];
u8 as u8 in [0, u8::max_value()]; u8 as u8 in [0, u8::max_value()];
u16 as u16 in [0, u16::max_value()]; u16 as u16 in [0, u16::max_value()];
u32 as u32 in [0, u32::max_value()]; u32 as u32 in [0, u32::max_value()];
u64 as u64 in [0, u64::max_value()]; u64 as u64 in [0, u64::max_value()];
u128 as u128 in [0, u128::max_value()]; u128 as u128 in [0, u128::max_value()];
usize as usize in [0, usize::max_value()]; usize as usize in [0, usize::max_value()];
i8 as i8 in [i8::min_value(), i8::max_value()]; i8 as i8 in [i8::min_value(), i8::max_value()];
i16 as i16 in [i16::min_value(), i16::max_value()]; i16 as i16 in [i16::min_value(), i16::max_value()];
i32 as i32 in [i32::min_value(), i32::max_value()]; i32 as i32 in [i32::min_value(), i32::max_value()];
i64 as i64 in [i64::min_value(), i64::max_value()]; i64 as i64 in [i64::min_value(), i64::max_value()];
i128 as i128 in [i128::min_value(), i128::max_value()]; i128 as i128 in [i128::min_value(), i128::max_value()];
isize as isize in [isize::min_value(), isize::max_value()]; isize as isize in [isize::min_value(), isize::max_value()];
NonZeroU8 as u8 in [1, u8::max_value()]; NonZeroU8 as u8 in [1, u8::max_value()];
NonZeroU16 as u16 in [1, u16::max_value()]; NonZeroU16 as u16 in [1, u16::max_value()];
NonZeroU32 as u32 in [1, u32::max_value()]; NonZeroU32 as u32 in [1, u32::max_value()];
NonZeroU64 as u64 in [1, u64::max_value()]; NonZeroU64 as u64 in [1, u64::max_value()];
NonZeroU128 as u128 in [1, u128::max_value()]; NonZeroU128 as u128 in [1, u128::max_value()];
NonZeroUsize as usize in [1, usize::max_value()]; NonZeroUsize as usize in [1, usize::max_value()];
} }

View File

@ -1,442 +1,450 @@
#![no_std] #![no_std]
#![warn(missing_docs)] #![warn(missing_docs)]
//! This crate gives small utilities for casting between plain data types. //! This crate gives small utilities for casting between plain data types.
//! //!
//! ## Basics //! ## Basics
//! //!
//! Data comes in five basic forms in Rust, so we have five basic casting //! Data comes in five basic forms in Rust, so we have five basic casting
//! functions: //! functions:
//! //!
//! * `T` uses [`cast`] //! * `T` uses [`cast`]
//! * `&T` uses [`cast_ref`] //! * `&T` uses [`cast_ref`]
//! * `&mut T` uses [`cast_mut`] //! * `&mut T` uses [`cast_mut`]
//! * `&[T]` uses [`cast_slice`] //! * `&[T]` uses [`cast_slice`]
//! * `&mut [T]` uses [`cast_slice_mut`] //! * `&mut [T]` uses [`cast_slice_mut`]
//! //!
//! Some casts will never fail (eg: `cast::<u32, f32>` always works), other //! Some casts will never fail (eg: `cast::<u32, f32>` always works), other
//! casts might fail (eg: `cast_ref::<[u8; 4], u32>` will fail if the reference //! casts might fail (eg: `cast_ref::<[u8; 4], u32>` will fail if the reference
//! isn't already aligned to 4). Each casting function has a "try" version which //! isn't already aligned to 4). Each casting function has a "try" version which
//! will return a `Result`, and the "normal" version which will simply panic on //! will return a `Result`, and the "normal" version which will simply panic on
//! invalid input. //! invalid input.
//! //!
//! ## Using Your Own Types //! ## Using Your Own Types
//! //!
//! All the functions here are guarded by the [`Pod`] trait, which is a //! All the functions here are guarded by the [`Pod`] trait, which is a
//! sub-trait of the [`Zeroable`] trait. //! sub-trait of the [`Zeroable`] trait.
//! //!
//! If you're very sure that your type is eligible, you can implement those //! If you're very sure that your type is eligible, you can implement those
//! traits for your type and then they'll have full casting support. However, //! traits for your type and then they'll have full casting support. However,
//! these traits are `unsafe`, and you should carefully read the requirements //! these traits are `unsafe`, and you should carefully read the requirements
//! before adding the them to your own types. //! before adding the them to your own types.
//! //!
//! ## Features //! ## Features
//! //!
//! * This crate is core only by default, but if you're using Rust 1.36 or later //! * This crate is core only by default, but if you're using Rust 1.36 or later
//! you can enable the `extern_crate_alloc` cargo feature for some additional //! you can enable the `extern_crate_alloc` cargo feature for some additional
//! methods related to `Box` and `Vec`. Note that the `docs.rs` documentation //! methods related to `Box` and `Vec`. Note that the `docs.rs` documentation
//! is always built with `extern_crate_alloc` cargo feature enabled. //! is always built with `extern_crate_alloc` cargo feature enabled.
#[cfg(target_arch = "x86")] #[cfg(target_arch = "x86")]
use core::arch::x86; use core::arch::x86;
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
use core::arch::x86_64; use core::arch::x86_64;
// //
use core::{marker::*, mem::*, num::*, ptr::*}; use core::{marker::*, mem::*, num::*, ptr::*};
// Used from macros to ensure we aren't using some locally defined name and // Used from macros to ensure we aren't using some locally defined name and
// actually are referencing libcore. This also would allow pre-2018 edition // actually are referencing libcore. This also would allow pre-2018 edition
// crates to use our macros, but I'm not sure how important that is. // crates to use our macros, but I'm not sure how important that is.
#[doc(hidden)] #[doc(hidden)]
pub use ::core as __core; pub use ::core as __core;
macro_rules! impl_unsafe_marker_for_array { macro_rules! impl_unsafe_marker_for_array {
( $marker:ident , $( $n:expr ),* ) => { ( $marker:ident , $( $n:expr ),* ) => {
$(unsafe impl<T> $marker for [T; $n] where T: $marker {})* $(unsafe impl<T> $marker for [T; $n] where T: $marker {})*
} }
} }
#[cfg(feature = "extern_crate_std")] #[cfg(feature = "extern_crate_std")]
extern crate std; extern crate std;
#[cfg(feature = "extern_crate_alloc")] #[cfg(feature = "extern_crate_alloc")]
extern crate alloc; extern crate alloc;
#[cfg(feature = "extern_crate_alloc")] #[cfg(feature = "extern_crate_alloc")]
pub mod allocation; pub mod allocation;
#[cfg(feature = "extern_crate_alloc")] #[cfg(feature = "extern_crate_alloc")]
pub use allocation::*; pub use allocation::*;
mod zeroable; mod zeroable;
pub use zeroable::*; pub use zeroable::*;
mod pod; mod pod;
pub use pod::*; pub use pod::*;
mod contiguous; mod contiguous;
pub use contiguous::*; pub use contiguous::*;
mod offset_of; mod offset_of;
pub use offset_of::*; pub use offset_of::*;
mod transparent; mod transparent;
pub use transparent::*; pub use transparent::*;
#[cfg(feature = "derive")] #[cfg(feature = "derive")]
pub use bytemuck_derive::{Zeroable, Pod, TransparentWrapper, Contiguous}; pub use bytemuck_derive::{Contiguous, Pod, TransparentWrapper, Zeroable};
/* /*
Note(Lokathor): We've switched all of the `unwrap` to `match` because there is Note(Lokathor): We've switched all of the `unwrap` to `match` because there is
apparently a bug: https://github.com/rust-lang/rust/issues/68667 apparently a bug: https://github.com/rust-lang/rust/issues/68667
and it doesn't seem to show up in simple godbolt examples but has been reported and it doesn't seem to show up in simple godbolt examples but has been reported
as having an impact when there's a cast mixed in with other more complicated as having an impact when there's a cast mixed in with other more complicated
code around it. Rustc/LLVM ends up missing that the `Err` can't ever happen for code around it. Rustc/LLVM ends up missing that the `Err` can't ever happen for
particular type combinations, and then it doesn't fully eliminated the panic particular type combinations, and then it doesn't fully eliminated the panic
possibility code branch. possibility code branch.
*/ */
/// Immediately panics. /// Immediately panics.
#[cold] #[cold]
#[inline(never)] #[inline(never)]
fn something_went_wrong(src: &str, err: PodCastError) -> ! { fn something_went_wrong(src: &str, err: PodCastError) -> ! {
// Note(Lokathor): Keeping the panic here makes the panic _formatting_ go // Note(Lokathor): Keeping the panic here makes the panic _formatting_ go
// here too, which helps assembly readability and also helps keep down // here too, which helps assembly readability and also helps keep down
// the inline pressure. // the inline pressure.
panic!("{src}>{err:?}", src = src, err = err) panic!("{src}>{err:?}", src = src, err = err)
} }
/// Re-interprets `&T` as `&[u8]`. /// Re-interprets `&T` as `&[u8]`.
/// ///
/// Any ZST becomes an empty slice, and in that case the pointer value of that /// Any ZST becomes an empty slice, and in that case the pointer value of that
/// empty slice might not match the pointer value of the input reference. /// empty slice might not match the pointer value of the input reference.
#[inline] #[inline]
pub fn bytes_of<T: Pod>(t: &T) -> &[u8] { pub fn bytes_of<T: Pod>(t: &T) -> &[u8] {
match try_cast_slice::<T, u8>(core::slice::from_ref(t)) { if size_of::<T>() == 0 {
Ok(s) => s, &[]
Err(_) => unreachable!(), } else {
} match try_cast_slice::<T, u8>(core::slice::from_ref(t)) {
} Ok(s) => s,
Err(_) => unreachable!(),
/// Re-interprets `&mut T` as `&mut [u8]`. }
/// }
/// Any ZST becomes an empty slice, and in that case the pointer value of that }
/// empty slice might not match the pointer value of the input reference.
#[inline] /// Re-interprets `&mut T` as `&mut [u8]`.
pub fn bytes_of_mut<T: Pod>(t: &mut T) -> &mut [u8] { ///
match try_cast_slice_mut::<T, u8>(core::slice::from_mut(t)) { /// Any ZST becomes an empty slice, and in that case the pointer value of that
Ok(s) => s, /// empty slice might not match the pointer value of the input reference.
Err(_) => unreachable!(), #[inline]
} pub fn bytes_of_mut<T: Pod>(t: &mut T) -> &mut [u8] {
} if size_of::<T>() == 0 {
&mut []
/// Re-interprets `&[u8]` as `&T`. } else {
/// match try_cast_slice_mut::<T, u8>(core::slice::from_mut(t)) {
/// ## Panics Ok(s) => s,
/// Err(_) => unreachable!(),
/// This is [`try_from_bytes`] but will panic on error. }
#[inline] }
pub fn from_bytes<T: Pod>(s: &[u8]) -> &T { }
match try_from_bytes(s) {
Ok(t) => t, /// Re-interprets `&[u8]` as `&T`.
Err(e) => something_went_wrong("from_bytes", e), ///
} /// ## Panics
} ///
/// This is [`try_from_bytes`] but will panic on error.
/// Re-interprets `&mut [u8]` as `&mut T`. #[inline]
/// pub fn from_bytes<T: Pod>(s: &[u8]) -> &T {
/// ## Panics match try_from_bytes(s) {
/// Ok(t) => t,
/// This is [`try_from_bytes_mut`] but will panic on error. Err(e) => something_went_wrong("from_bytes", e),
#[inline] }
pub fn from_bytes_mut<T: Pod>(s: &mut [u8]) -> &mut T { }
match try_from_bytes_mut(s) {
Ok(t) => t, /// Re-interprets `&mut [u8]` as `&mut T`.
Err(e) => something_went_wrong("from_bytes_mut", e), ///
} /// ## Panics
} ///
/// This is [`try_from_bytes_mut`] but will panic on error.
/// Re-interprets `&[u8]` as `&T`. #[inline]
/// pub fn from_bytes_mut<T: Pod>(s: &mut [u8]) -> &mut T {
/// ## Failure match try_from_bytes_mut(s) {
/// Ok(t) => t,
/// * If the slice isn't aligned for the new type Err(e) => something_went_wrong("from_bytes_mut", e),
/// * If the slice's length isnt exactly the size of the new type }
#[inline] }
pub fn try_from_bytes<T: Pod>(s: &[u8]) -> Result<&T, PodCastError> {
if s.len() != size_of::<T>() { /// Re-interprets `&[u8]` as `&T`.
Err(PodCastError::SizeMismatch) ///
} else if (s.as_ptr() as usize) % align_of::<T>() != 0 { /// ## Failure
Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned) ///
} else { /// * If the slice isn't aligned for the new type
Ok(unsafe { &*(s.as_ptr() as *const T) }) /// * If the slice's length isnt exactly the size of the new type
} #[inline]
} pub fn try_from_bytes<T: Pod>(s: &[u8]) -> Result<&T, PodCastError> {
if s.len() != size_of::<T>() {
/// Re-interprets `&mut [u8]` as `&mut T`. Err(PodCastError::SizeMismatch)
/// } else if (s.as_ptr() as usize) % align_of::<T>() != 0 {
/// ## Failure Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned)
/// } else {
/// * If the slice isn't aligned for the new type Ok(unsafe { &*(s.as_ptr() as *const T) })
/// * If the slice's length isnt exactly the size of the new type }
#[inline] }
pub fn try_from_bytes_mut<T: Pod>(
s: &mut [u8], /// Re-interprets `&mut [u8]` as `&mut T`.
) -> Result<&mut T, PodCastError> { ///
if s.len() != size_of::<T>() { /// ## Failure
Err(PodCastError::SizeMismatch) ///
} else if (s.as_ptr() as usize) % align_of::<T>() != 0 { /// * If the slice isn't aligned for the new type
Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned) /// * If the slice's length isnt exactly the size of the new type
} else { #[inline]
Ok(unsafe { &mut *(s.as_mut_ptr() as *mut T) }) pub fn try_from_bytes_mut<T: Pod>(
} s: &mut [u8],
} ) -> Result<&mut T, PodCastError> {
if s.len() != size_of::<T>() {
/// The things that can go wrong when casting between [`Pod`] data forms. Err(PodCastError::SizeMismatch)
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] } else if (s.as_ptr() as usize) % align_of::<T>() != 0 {
pub enum PodCastError { Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned)
/// You tried to cast a slice to an element type with a higher alignment } else {
/// requirement but the slice wasn't aligned. Ok(unsafe { &mut *(s.as_mut_ptr() as *mut T) })
TargetAlignmentGreaterAndInputNotAligned, }
/// If the element size changes then the output slice changes length }
/// accordingly. If the output slice wouldn't be a whole number of elements
/// then the conversion fails. /// The things that can go wrong when casting between [`Pod`] data forms.
OutputSliceWouldHaveSlop, #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
/// When casting a slice you can't convert between ZST elements and non-ZST pub enum PodCastError {
/// elements. When casting an individual `T`, `&T`, or `&mut T` value the /// You tried to cast a slice to an element type with a higher alignment
/// source size and destination size must be an exact match. /// requirement but the slice wasn't aligned.
SizeMismatch, TargetAlignmentGreaterAndInputNotAligned,
/// For this type of cast the alignments must be exactly the same and they /// If the element size changes then the output slice changes length
/// were not so now you're sad. /// accordingly. If the output slice wouldn't be a whole number of elements
/// /// then the conversion fails.
/// This error is generated **only** by operations that cast allocated types OutputSliceWouldHaveSlop,
/// (such as `Box` and `Vec`), because in that case the alignment must stay /// When casting a slice you can't convert between ZST elements and non-ZST
/// exact. /// elements. When casting an individual `T`, `&T`, or `&mut T` value the
AlignmentMismatch, /// source size and destination size must be an exact match.
} SizeMismatch,
impl core::fmt::Display for PodCastError { /// For this type of cast the alignments must be exactly the same and they
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { /// were not so now you're sad.
write!(f, "{:?}", self) ///
} /// This error is generated **only** by operations that cast allocated types
} /// (such as `Box` and `Vec`), because in that case the alignment must stay
#[cfg(feature = "extern_crate_std")] /// exact.
impl std::error::Error for PodCastError {} AlignmentMismatch,
}
/// Cast `T` into `U` impl core::fmt::Display for PodCastError {
/// fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
/// ## Panics write!(f, "{:?}", self)
/// }
/// * This is like [`try_cast`](try_cast), but will panic on a size mismatch. }
#[inline] #[cfg(feature = "extern_crate_std")]
pub fn cast<A: Pod, B: Pod>(a: A) -> B { impl std::error::Error for PodCastError {}
if size_of::<A>() == size_of::<B>() {
unsafe { core::mem::transmute_copy(&a) } /// Cast `T` into `U`
} else { ///
something_went_wrong("cast", PodCastError::SizeMismatch) /// ## Panics
} ///
} /// * This is like [`try_cast`](try_cast), but will panic on a size mismatch.
#[inline]
/// Cast `&mut T` into `&mut U`. pub fn cast<A: Pod, B: Pod>(a: A) -> B {
/// if size_of::<A>() == size_of::<B>() {
/// ## Panics unsafe { core::mem::transmute_copy(&a) }
/// } else {
/// This is [`try_cast_mut`] but will panic on error. something_went_wrong("cast", PodCastError::SizeMismatch)
#[inline] }
pub fn cast_mut<A: Pod, B: Pod>(a: &mut A) -> &mut B { }
if size_of::<A>() == size_of::<B>() && align_of::<A>() >= align_of::<B>() {
// Plz mr compiler, just notice that we can't ever hit Err in this case. /// Cast `&mut T` into `&mut U`.
match try_cast_mut(a) { ///
Ok(b) => b, /// ## Panics
Err(_) => unreachable!(), ///
} /// This is [`try_cast_mut`] but will panic on error.
} else { #[inline]
match try_cast_mut(a) { pub fn cast_mut<A: Pod, B: Pod>(a: &mut A) -> &mut B {
Ok(b) => b, if size_of::<A>() == size_of::<B>() && align_of::<A>() >= align_of::<B>() {
Err(e) => something_went_wrong("cast_mut", e), // Plz mr compiler, just notice that we can't ever hit Err in this case.
} match try_cast_mut(a) {
} Ok(b) => b,
} Err(_) => unreachable!(),
}
/// Cast `&T` into `&U`. } else {
/// match try_cast_mut(a) {
/// ## Panics Ok(b) => b,
/// Err(e) => something_went_wrong("cast_mut", e),
/// This is [`try_cast_ref`] but will panic on error. }
#[inline] }
pub fn cast_ref<A: Pod, B: Pod>(a: &A) -> &B { }
if size_of::<A>() == size_of::<B>() && align_of::<A>() >= align_of::<B>() {
// Plz mr compiler, just notice that we can't ever hit Err in this case. /// Cast `&T` into `&U`.
match try_cast_ref(a) { ///
Ok(b) => b, /// ## Panics
Err(_) => unreachable!(), ///
} /// This is [`try_cast_ref`] but will panic on error.
} else { #[inline]
match try_cast_ref(a) { pub fn cast_ref<A: Pod, B: Pod>(a: &A) -> &B {
Ok(b) => b, if size_of::<A>() == size_of::<B>() && align_of::<A>() >= align_of::<B>() {
Err(e) => something_went_wrong("cast_ref", e), // Plz mr compiler, just notice that we can't ever hit Err in this case.
} match try_cast_ref(a) {
} Ok(b) => b,
} Err(_) => unreachable!(),
}
/// Cast `&[A]` into `&[B]`. } else {
/// match try_cast_ref(a) {
/// ## Panics Ok(b) => b,
/// Err(e) => something_went_wrong("cast_ref", e),
/// This is [`try_cast_slice`] but will panic on error. }
#[inline] }
pub fn cast_slice<A: Pod, B: Pod>(a: &[A]) -> &[B] { }
match try_cast_slice(a) {
Ok(b) => b, /// Cast `&[A]` into `&[B]`.
Err(e) => something_went_wrong("cast_slice", e), ///
} /// ## Panics
} ///
/// This is [`try_cast_slice`] but will panic on error.
/// Cast `&mut [T]` into `&mut [U]`. #[inline]
/// pub fn cast_slice<A: Pod, B: Pod>(a: &[A]) -> &[B] {
/// ## Panics match try_cast_slice(a) {
/// Ok(b) => b,
/// This is [`try_cast_slice_mut`] but will panic on error. Err(e) => something_went_wrong("cast_slice", e),
#[inline] }
pub fn cast_slice_mut<A: Pod, B: Pod>(a: &mut [A]) -> &mut [B] { }
match try_cast_slice_mut(a) {
Ok(b) => b, /// Cast `&mut [T]` into `&mut [U]`.
Err(e) => something_went_wrong("cast_slice_mut", e), ///
} /// ## Panics
} ///
/// This is [`try_cast_slice_mut`] but will panic on error.
/// As `align_to`, but safe because of the [`Pod`] bound. #[inline]
#[inline] pub fn cast_slice_mut<A: Pod, B: Pod>(a: &mut [A]) -> &mut [B] {
pub fn pod_align_to<T: Pod, U: Pod>(vals: &[T]) -> (&[T], &[U], &[T]) { match try_cast_slice_mut(a) {
unsafe { vals.align_to::<U>() } Ok(b) => b,
} Err(e) => something_went_wrong("cast_slice_mut", e),
}
/// As `align_to_mut`, but safe because of the [`Pod`] bound. }
#[inline]
pub fn pod_align_to_mut<T: Pod, U: Pod>( /// As `align_to`, but safe because of the [`Pod`] bound.
vals: &mut [T], #[inline]
) -> (&mut [T], &mut [U], &mut [T]) { pub fn pod_align_to<T: Pod, U: Pod>(vals: &[T]) -> (&[T], &[U], &[T]) {
unsafe { vals.align_to_mut::<U>() } unsafe { vals.align_to::<U>() }
} }
/// Try to cast `T` into `U`. /// As `align_to_mut`, but safe because of the [`Pod`] bound.
/// #[inline]
/// Note that for this particular type of cast, alignment isn't a factor. The pub fn pod_align_to_mut<T: Pod, U: Pod>(
/// input value is semantically copied into the function and then returned to a vals: &mut [T],
/// new memory location which will have whatever the required alignment of the ) -> (&mut [T], &mut [U], &mut [T]) {
/// output type is. unsafe { vals.align_to_mut::<U>() }
/// }
/// ## Failure
/// /// Try to cast `T` into `U`.
/// * If the types don't have the same size this fails. ///
#[inline] /// Note that for this particular type of cast, alignment isn't a factor. The
pub fn try_cast<A: Pod, B: Pod>(a: A) -> Result<B, PodCastError> { /// input value is semantically copied into the function and then returned to a
if size_of::<A>() == size_of::<B>() { /// new memory location which will have whatever the required alignment of the
Ok(unsafe { core::mem::transmute_copy(&a) }) /// output type is.
} else { ///
Err(PodCastError::SizeMismatch) /// ## Failure
} ///
} /// * If the types don't have the same size this fails.
#[inline]
/// Try to convert a `&T` into `&U`. pub fn try_cast<A: Pod, B: Pod>(a: A) -> Result<B, PodCastError> {
/// if size_of::<A>() == size_of::<B>() {
/// ## Failure Ok(unsafe { core::mem::transmute_copy(&a) })
/// } else {
/// * If the reference isn't aligned in the new type Err(PodCastError::SizeMismatch)
/// * If the source type and target type aren't the same size. }
#[inline] }
pub fn try_cast_ref<A: Pod, B: Pod>(a: &A) -> Result<&B, PodCastError> {
// Note(Lokathor): everything with `align_of` and `size_of` will optimize away /// Try to convert a `&T` into `&U`.
// after monomorphization. ///
if align_of::<B>() > align_of::<A>() /// ## Failure
&& (a as *const A as usize) % align_of::<B>() != 0 ///
{ /// * If the reference isn't aligned in the new type
Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned) /// * If the source type and target type aren't the same size.
} else if size_of::<B>() == size_of::<A>() { #[inline]
Ok(unsafe { &*(a as *const A as *const B) }) pub fn try_cast_ref<A: Pod, B: Pod>(a: &A) -> Result<&B, PodCastError> {
} else { // Note(Lokathor): everything with `align_of` and `size_of` will optimize away
Err(PodCastError::SizeMismatch) // after monomorphization.
} if align_of::<B>() > align_of::<A>()
} && (a as *const A as usize) % align_of::<B>() != 0
{
/// Try to convert a `&mut T` into `&mut U`. Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned)
/// } else if size_of::<B>() == size_of::<A>() {
/// As [`try_cast_ref`], but `mut`. Ok(unsafe { &*(a as *const A as *const B) })
#[inline] } else {
pub fn try_cast_mut<A: Pod, B: Pod>(a: &mut A) -> Result<&mut B, PodCastError> { Err(PodCastError::SizeMismatch)
// Note(Lokathor): everything with `align_of` and `size_of` will optimize away }
// after monomorphization. }
if align_of::<B>() > align_of::<A>()
&& (a as *mut A as usize) % align_of::<B>() != 0 /// Try to convert a `&mut T` into `&mut U`.
{ ///
Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned) /// As [`try_cast_ref`], but `mut`.
} else if size_of::<B>() == size_of::<A>() { #[inline]
Ok(unsafe { &mut *(a as *mut A as *mut B) }) pub fn try_cast_mut<A: Pod, B: Pod>(a: &mut A) -> Result<&mut B, PodCastError> {
} else { // Note(Lokathor): everything with `align_of` and `size_of` will optimize away
Err(PodCastError::SizeMismatch) // after monomorphization.
} if align_of::<B>() > align_of::<A>()
} && (a as *mut A as usize) % align_of::<B>() != 0
{
/// Try to convert `&[A]` into `&[B]` (possibly with a change in length). Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned)
/// } else if size_of::<B>() == size_of::<A>() {
/// * `input.as_ptr() as usize == output.as_ptr() as usize` Ok(unsafe { &mut *(a as *mut A as *mut B) })
/// * `input.len() * size_of::<A>() == output.len() * size_of::<B>()` } else {
/// Err(PodCastError::SizeMismatch)
/// ## Failure }
/// }
/// * If the target type has a greater alignment requirement and the input slice
/// isn't aligned. /// Try to convert `&[A]` into `&[B]` (possibly with a change in length).
/// * If the target element type is a different size from the current element ///
/// type, and the output slice wouldn't be a whole number of elements when /// * `input.as_ptr() as usize == output.as_ptr() as usize`
/// accounting for the size change (eg: 3 `u16` values is 1.5 `u32` values, so /// * `input.len() * size_of::<A>() == output.len() * size_of::<B>()`
/// that's a failure). ///
/// * Similarly, you can't convert between a [ZST](https://doc.rust-lang.org/nomicon/exotic-sizes.html#zero-sized-types-zsts) /// ## Failure
/// and a non-ZST. ///
#[inline] /// * If the target type has a greater alignment requirement and the input slice
pub fn try_cast_slice<A: Pod, B: Pod>(a: &[A]) -> Result<&[B], PodCastError> { /// isn't aligned.
// Note(Lokathor): everything with `align_of` and `size_of` will optimize away /// * If the target element type is a different size from the current element
// after monomorphization. /// type, and the output slice wouldn't be a whole number of elements when
if align_of::<B>() > align_of::<A>() /// accounting for the size change (eg: 3 `u16` values is 1.5 `u32` values, so
&& (a.as_ptr() as usize) % align_of::<B>() != 0 /// that's a failure).
{ /// * Similarly, you can't convert between a [ZST](https://doc.rust-lang.org/nomicon/exotic-sizes.html#zero-sized-types-zsts)
Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned) /// and a non-ZST.
} else if size_of::<B>() == size_of::<A>() { #[inline]
Ok(unsafe { core::slice::from_raw_parts(a.as_ptr() as *const B, a.len()) }) pub fn try_cast_slice<A: Pod, B: Pod>(a: &[A]) -> Result<&[B], PodCastError> {
} else if size_of::<A>() == 0 || size_of::<B>() == 0 { // Note(Lokathor): everything with `align_of` and `size_of` will optimize away
Err(PodCastError::SizeMismatch) // after monomorphization.
} else if core::mem::size_of_val(a) % size_of::<B>() == 0 { if align_of::<B>() > align_of::<A>()
let new_len = core::mem::size_of_val(a) / size_of::<B>(); && (a.as_ptr() as usize) % align_of::<B>() != 0
Ok(unsafe { core::slice::from_raw_parts(a.as_ptr() as *const B, new_len) }) {
} else { Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned)
Err(PodCastError::OutputSliceWouldHaveSlop) } else if size_of::<B>() == size_of::<A>() {
} Ok(unsafe { core::slice::from_raw_parts(a.as_ptr() as *const B, a.len()) })
} } else if size_of::<A>() == 0 || size_of::<B>() == 0 {
Err(PodCastError::SizeMismatch)
/// Try to convert `&mut [A]` into `&mut [B]` (possibly with a change in } else if core::mem::size_of_val(a) % size_of::<B>() == 0 {
/// length). let new_len = core::mem::size_of_val(a) / size_of::<B>();
/// Ok(unsafe { core::slice::from_raw_parts(a.as_ptr() as *const B, new_len) })
/// As [`try_cast_slice`], but `&mut`. } else {
#[inline] Err(PodCastError::OutputSliceWouldHaveSlop)
pub fn try_cast_slice_mut<A: Pod, B: Pod>( }
a: &mut [A], }
) -> Result<&mut [B], PodCastError> {
// Note(Lokathor): everything with `align_of` and `size_of` will optimize away /// Try to convert `&mut [A]` into `&mut [B]` (possibly with a change in
// after monomorphization. /// length).
if align_of::<B>() > align_of::<A>() ///
&& (a.as_mut_ptr() as usize) % align_of::<B>() != 0 /// As [`try_cast_slice`], but `&mut`.
{ #[inline]
Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned) pub fn try_cast_slice_mut<A: Pod, B: Pod>(
} else if size_of::<B>() == size_of::<A>() { a: &mut [A],
Ok(unsafe { ) -> Result<&mut [B], PodCastError> {
core::slice::from_raw_parts_mut(a.as_mut_ptr() as *mut B, a.len()) // Note(Lokathor): everything with `align_of` and `size_of` will optimize away
}) // after monomorphization.
} else if size_of::<A>() == 0 || size_of::<B>() == 0 { if align_of::<B>() > align_of::<A>()
Err(PodCastError::SizeMismatch) && (a.as_mut_ptr() as usize) % align_of::<B>() != 0
} else if core::mem::size_of_val(a) % size_of::<B>() == 0 { {
let new_len = core::mem::size_of_val(a) / size_of::<B>(); Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned)
Ok(unsafe { } else if size_of::<B>() == size_of::<A>() {
core::slice::from_raw_parts_mut(a.as_mut_ptr() as *mut B, new_len) Ok(unsafe {
}) core::slice::from_raw_parts_mut(a.as_mut_ptr() as *mut B, a.len())
} else { })
Err(PodCastError::OutputSliceWouldHaveSlop) } else if size_of::<A>() == 0 || size_of::<B>() == 0 {
} Err(PodCastError::SizeMismatch)
} } else if core::mem::size_of_val(a) % size_of::<B>() == 0 {
let new_len = core::mem::size_of_val(a) / size_of::<B>();
Ok(unsafe {
core::slice::from_raw_parts_mut(a.as_mut_ptr() as *mut B, new_len)
})
} else {
Err(PodCastError::OutputSliceWouldHaveSlop)
}
}

View File

@ -1,132 +1,132 @@
#![forbid(unsafe_code)] #![forbid(unsafe_code)]
/// Find the offset in bytes of the given `$field` of `$Type`. Requires an /// Find the offset in bytes of the given `$field` of `$Type`. Requires an
/// already initialized `$instance` value to work with. /// already initialized `$instance` value to work with.
/// ///
/// This is similar to the macro from [`memoffset`](https://docs.rs/memoffset), /// This is similar to the macro from [`memoffset`](https://docs.rs/memoffset),
/// however it uses no `unsafe` code. /// however it uses no `unsafe` code.
/// ///
/// This macro has a 3-argument and 2-argument version. /// This macro has a 3-argument and 2-argument version.
/// * In the 3-arg version you specify an instance of the type, the type itself, /// * In the 3-arg version you specify an instance of the type, the type itself,
/// and the field name. /// and the field name.
/// * In the 2-arg version the macro will call the [`default`](Default::default) /// * In the 2-arg version the macro will call the [`default`](Default::default)
/// method to make a temporary instance of the type for you. /// method to make a temporary instance of the type for you.
/// ///
/// The output of this macro is the byte offset of the field (as a `usize`). The /// The output of this macro is the byte offset of the field (as a `usize`). The
/// calculations of the macro are fixed across the entire program, but if the /// calculations of the macro are fixed across the entire program, but if the
/// type used is `repr(Rust)` then they're *not* fixed across compilations or /// type used is `repr(Rust)` then they're *not* fixed across compilations or
/// compilers. /// compilers.
/// ///
/// ## Examples /// ## Examples
/// ///
/// ### 3-arg Usage /// ### 3-arg Usage
/// ///
/// ```rust /// ```rust
/// # use bytemuck::offset_of; /// # use bytemuck::offset_of;
/// // enums can't derive default, and for this example we don't pick one /// // enums can't derive default, and for this example we don't pick one
/// enum MyExampleEnum { /// enum MyExampleEnum {
/// A, B, C, /// A, B, C,
/// } /// }
/// ///
/// // so now our struct here doesn't have Default /// // so now our struct here doesn't have Default
/// #[repr(C)] /// #[repr(C)]
/// struct MyNotDefaultType { /// struct MyNotDefaultType {
/// pub counter: i32, /// pub counter: i32,
/// pub some_field: MyExampleEnum, /// pub some_field: MyExampleEnum,
/// } /// }
/// ///
/// // but we provide an instance of the type and it's all good. /// // but we provide an instance of the type and it's all good.
/// let val = MyNotDefaultType { counter: 5, some_field: MyExampleEnum::A }; /// let val = MyNotDefaultType { counter: 5, some_field: MyExampleEnum::A };
/// assert_eq!(offset_of!(val, MyNotDefaultType, some_field), 4); /// assert_eq!(offset_of!(val, MyNotDefaultType, some_field), 4);
/// ``` /// ```
/// ///
/// ### 2-arg Usage /// ### 2-arg Usage
/// ///
/// ```rust /// ```rust
/// # use bytemuck::offset_of; /// # use bytemuck::offset_of;
/// #[derive(Default)] /// #[derive(Default)]
/// #[repr(C)] /// #[repr(C)]
/// struct Vertex { /// struct Vertex {
/// pub loc: [f32; 3], /// pub loc: [f32; 3],
/// pub color: [f32; 3], /// pub color: [f32; 3],
/// } /// }
/// // if the type impls Default the macro can make its own default instance. /// // if the type impls Default the macro can make its own default instance.
/// assert_eq!(offset_of!(Vertex, loc), 0); /// assert_eq!(offset_of!(Vertex, loc), 0);
/// assert_eq!(offset_of!(Vertex, color), 12); /// assert_eq!(offset_of!(Vertex, color), 12);
/// ``` /// ```
/// ///
/// # Usage with `#[repr(packed)]` structs /// # Usage with `#[repr(packed)]` structs
/// ///
/// Attempting to compute the offset of a `#[repr(packed)]` struct with /// Attempting to compute the offset of a `#[repr(packed)]` struct with
/// `bytemuck::offset_of!` requires an `unsafe` block. We hope to relax this in /// `bytemuck::offset_of!` requires an `unsafe` block. We hope to relax this in
/// the future, but currently it is required to work around a soundness hole in /// the future, but currently it is required to work around a soundness hole in
/// Rust (See [rust-lang/rust#27060]). /// Rust (See [rust-lang/rust#27060]).
/// ///
/// [rust-lang/rust#27060]: https://github.com/rust-lang/rust/issues/27060 /// [rust-lang/rust#27060]: https://github.com/rust-lang/rust/issues/27060
/// ///
/// <p style="background:rgba(255,181,77,0.16);padding:0.75em;"> /// <p style="background:rgba(255,181,77,0.16);padding:0.75em;">
/// <strong>Warning:</strong> This is only true for versions of bytemuck > 1.4.0. /// <strong>Warning:</strong> This is only true for versions of bytemuck > 1.4.0.
/// Previous versions of /// Previous versions of
/// <code style="background:rgba(41,24,0,0.1);">bytemuck::offset_of!</code> /// <code style="background:rgba(41,24,0,0.1);">bytemuck::offset_of!</code>
/// will only emit a warning when used on the field of a packed struct in safe code, /// will only emit a warning when used on the field of a packed struct in safe code,
/// which can lead to unsoundness. /// which can lead to unsoundness.
/// </p> /// </p>
/// ///
/// For example, the following will fail to compile: /// For example, the following will fail to compile:
/// ///
/// ```compile_fail /// ```compile_fail
/// #[repr(C, packed)] /// #[repr(C, packed)]
/// #[derive(Default)] /// #[derive(Default)]
/// struct Example { /// struct Example {
/// field: u32, /// field: u32,
/// } /// }
/// // Doesn't compile: /// // Doesn't compile:
/// let _offset = bytemuck::offset_of!(Example, field); /// let _offset = bytemuck::offset_of!(Example, field);
/// ``` /// ```
/// ///
/// While the error message this generates will mention the /// While the error message this generates will mention the
/// `safe_packed_borrows` lint, the macro will still fail to compile even if /// `safe_packed_borrows` lint, the macro will still fail to compile even if
/// that lint is `#[allow]`ed: /// that lint is `#[allow]`ed:
/// ///
/// ```compile_fail /// ```compile_fail
/// # #[repr(C, packed)] #[derive(Default)] struct Example { field: u32 } /// # #[repr(C, packed)] #[derive(Default)] struct Example { field: u32 }
/// // Still doesn't compile: /// // Still doesn't compile:
/// #[allow(safe_packed_borrows)] { /// #[allow(safe_packed_borrows)] {
/// let _offset = bytemuck::offset_of!(Example, field); /// let _offset = bytemuck::offset_of!(Example, field);
/// } /// }
/// ``` /// ```
/// ///
/// This *can* be worked around by using `unsafe`, but it is only sound to do so /// This *can* be worked around by using `unsafe`, but it is only sound to do so
/// if you can guarantee that taking a reference to the field is sound. /// if you can guarantee that taking a reference to the field is sound.
/// ///
/// In practice, this means it only works for fields of align(1) types, or if /// In practice, this means it only works for fields of align(1) types, or if
/// you know the field's offset in advance (defeating the point of `offset_of`) /// you know the field's offset in advance (defeating the point of `offset_of`)
/// and can prove that the struct's alignment and the field's offset are enough /// and can prove that the struct's alignment and the field's offset are enough
/// to prove the field's alignment. /// to prove the field's alignment.
/// ///
/// Once the `raw_ref` macros are available, a future version of this crate will /// Once the `raw_ref` macros are available, a future version of this crate will
/// use them to lift the limitations of packed structs. For the duration of the /// use them to lift the limitations of packed structs. For the duration of the
/// `1.x` version of this crate that will be behind an on-by-default cargo /// `1.x` version of this crate that will be behind an on-by-default cargo
/// feature (to maintain minimum rust version support). /// feature (to maintain minimum rust version support).
#[macro_export] #[macro_export]
macro_rules! offset_of { macro_rules! offset_of {
($instance:expr, $Type:path, $field:tt) => {{ ($instance:expr, $Type:path, $field:tt) => {{
#[forbid(safe_packed_borrows)] #[forbid(safe_packed_borrows)]
{ {
// This helps us guard against field access going through a Deref impl. // This helps us guard against field access going through a Deref impl.
#[allow(clippy::unneeded_field_pattern)] #[allow(clippy::unneeded_field_pattern)]
let $Type { $field: _, .. }; let $Type { $field: _, .. };
let reference: &$Type = &$instance; let reference: &$Type = &$instance;
let address = reference as *const _ as usize; let address = reference as *const _ as usize;
let field_pointer = &reference.$field as *const _ as usize; let field_pointer = &reference.$field as *const _ as usize;
// These asserts/unwraps are compiled away at release, and defend against // These asserts/unwraps are compiled away at release, and defend against
// the case where somehow a deref impl is still invoked. // the case where somehow a deref impl is still invoked.
let result = field_pointer.checked_sub(address).unwrap(); let result = field_pointer.checked_sub(address).unwrap();
assert!(result <= $crate::__core::mem::size_of::<$Type>()); assert!(result <= $crate::__core::mem::size_of::<$Type>());
result result
} }
}}; }};
($Type:path, $field:tt) => {{ ($Type:path, $field:tt) => {{
$crate::offset_of!(<$Type as Default>::default(), $Type, $field) $crate::offset_of!(<$Type as Default>::default(), $Type, $field)
}}; }};
} }

View File

@ -1,99 +1,99 @@
use super::*; use super::*;
/// Marker trait for "plain old data". /// Marker trait for "plain old data".
/// ///
/// The point of this trait is that once something is marked "plain old data" /// The point of this trait is that once something is marked "plain old data"
/// you can really go to town with the bit fiddling and bit casting. Therefore, /// you can really go to town with the bit fiddling and bit casting. Therefore,
/// it's a relatively strong claim to make about a type. Do not add this to your /// it's a relatively strong claim to make about a type. Do not add this to your
/// type casually. /// type casually.
/// ///
/// **Reminder:** The results of casting around bytes between data types are /// **Reminder:** The results of casting around bytes between data types are
/// _endian dependant_. Little-endian machines are the most common, but /// _endian dependant_. Little-endian machines are the most common, but
/// big-endian machines do exist (and big-endian is also used for "network /// big-endian machines do exist (and big-endian is also used for "network
/// order" bytes). /// order" bytes).
/// ///
/// ## Safety /// ## Safety
/// ///
/// * The type must be inhabited (eg: no /// * The type must be inhabited (eg: no
/// [Infallible](core::convert::Infallible)). /// [Infallible](core::convert::Infallible)).
/// * The type must allow any bit pattern (eg: no `bool` or `char`, which have /// * The type must allow any bit pattern (eg: no `bool` or `char`, which have
/// illegal bit patterns). /// illegal bit patterns).
/// * The type must not contain any padding bytes, either in the middle or on /// * The type must not contain any padding bytes, either in the middle or on
/// the end (eg: no `#[repr(C)] struct Foo(u8, u16)`, which has padding in the /// the end (eg: no `#[repr(C)] struct Foo(u8, u16)`, which has padding in the
/// middle, and also no `#[repr(C)] struct Foo(u16, u8)`, which has padding on /// middle, and also no `#[repr(C)] struct Foo(u16, u8)`, which has padding on
/// the end). /// the end).
/// * The type needs to have all fields also be `Pod`. /// * The type needs to have all fields also be `Pod`.
/// * The type needs to be `repr(C)` or `repr(transparent)`. In the case of /// * The type needs to be `repr(C)` or `repr(transparent)`. In the case of
/// `repr(C)`, the `packed` and `align` repr modifiers can be used as long as /// `repr(C)`, the `packed` and `align` repr modifiers can be used as long as
/// all other rules end up being followed. /// all other rules end up being followed.
pub unsafe trait Pod: Zeroable + Copy + 'static {} pub unsafe trait Pod: Zeroable + Copy + 'static {}
unsafe impl Pod for () {} unsafe impl Pod for () {}
unsafe impl Pod for u8 {} unsafe impl Pod for u8 {}
unsafe impl Pod for i8 {} unsafe impl Pod for i8 {}
unsafe impl Pod for u16 {} unsafe impl Pod for u16 {}
unsafe impl Pod for i16 {} unsafe impl Pod for i16 {}
unsafe impl Pod for u32 {} unsafe impl Pod for u32 {}
unsafe impl Pod for i32 {} unsafe impl Pod for i32 {}
unsafe impl Pod for u64 {} unsafe impl Pod for u64 {}
unsafe impl Pod for i64 {} unsafe impl Pod for i64 {}
unsafe impl Pod for usize {} unsafe impl Pod for usize {}
unsafe impl Pod for isize {} unsafe impl Pod for isize {}
unsafe impl Pod for u128 {} unsafe impl Pod for u128 {}
unsafe impl Pod for i128 {} unsafe impl Pod for i128 {}
unsafe impl Pod for f32 {} unsafe impl Pod for f32 {}
unsafe impl Pod for f64 {} unsafe impl Pod for f64 {}
unsafe impl<T: Pod> Pod for Wrapping<T> {} unsafe impl<T: Pod> Pod for Wrapping<T> {}
unsafe impl Pod for Option<NonZeroI8> {} unsafe impl Pod for Option<NonZeroI8> {}
unsafe impl Pod for Option<NonZeroI16> {} unsafe impl Pod for Option<NonZeroI16> {}
unsafe impl Pod for Option<NonZeroI32> {} unsafe impl Pod for Option<NonZeroI32> {}
unsafe impl Pod for Option<NonZeroI64> {} unsafe impl Pod for Option<NonZeroI64> {}
unsafe impl Pod for Option<NonZeroI128> {} unsafe impl Pod for Option<NonZeroI128> {}
unsafe impl Pod for Option<NonZeroIsize> {} unsafe impl Pod for Option<NonZeroIsize> {}
unsafe impl Pod for Option<NonZeroU8> {} unsafe impl Pod for Option<NonZeroU8> {}
unsafe impl Pod for Option<NonZeroU16> {} unsafe impl Pod for Option<NonZeroU16> {}
unsafe impl Pod for Option<NonZeroU32> {} unsafe impl Pod for Option<NonZeroU32> {}
unsafe impl Pod for Option<NonZeroU64> {} unsafe impl Pod for Option<NonZeroU64> {}
unsafe impl Pod for Option<NonZeroU128> {} unsafe impl Pod for Option<NonZeroU128> {}
unsafe impl Pod for Option<NonZeroUsize> {} unsafe impl Pod for Option<NonZeroUsize> {}
unsafe impl<T: 'static> Pod for *mut T {} unsafe impl<T: 'static> Pod for *mut T {}
unsafe impl<T: 'static> Pod for *const T {} unsafe impl<T: 'static> Pod for *const T {}
unsafe impl<T: 'static> Pod for Option<NonNull<T>> {} unsafe impl<T: 'static> Pod for Option<NonNull<T>> {}
unsafe impl<T: Pod> Pod for PhantomData<T> {} unsafe impl<T: Pod> Pod for PhantomData<T> {}
unsafe impl<T: Pod> Pod for ManuallyDrop<T> {} unsafe impl<T: Pod> Pod for ManuallyDrop<T> {}
// Note(Lokathor): MaybeUninit can NEVER be Pod. // Note(Lokathor): MaybeUninit can NEVER be Pod.
impl_unsafe_marker_for_array!( impl_unsafe_marker_for_array!(
Pod, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, Pod, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 48, 64, 96, 128, 256, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 48, 64, 96, 128, 256,
512, 1024, 2048, 4096 512, 1024, 2048, 4096
); );
#[cfg(target_arch = "x86")] #[cfg(target_arch = "x86")]
unsafe impl Pod for x86::__m128i {} unsafe impl Pod for x86::__m128i {}
#[cfg(target_arch = "x86")] #[cfg(target_arch = "x86")]
unsafe impl Pod for x86::__m128 {} unsafe impl Pod for x86::__m128 {}
#[cfg(target_arch = "x86")] #[cfg(target_arch = "x86")]
unsafe impl Pod for x86::__m128d {} unsafe impl Pod for x86::__m128d {}
#[cfg(target_arch = "x86")] #[cfg(target_arch = "x86")]
unsafe impl Pod for x86::__m256i {} unsafe impl Pod for x86::__m256i {}
#[cfg(target_arch = "x86")] #[cfg(target_arch = "x86")]
unsafe impl Pod for x86::__m256 {} unsafe impl Pod for x86::__m256 {}
#[cfg(target_arch = "x86")] #[cfg(target_arch = "x86")]
unsafe impl Pod for x86::__m256d {} unsafe impl Pod for x86::__m256d {}
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
unsafe impl Pod for x86_64::__m128i {} unsafe impl Pod for x86_64::__m128i {}
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
unsafe impl Pod for x86_64::__m128 {} unsafe impl Pod for x86_64::__m128 {}
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
unsafe impl Pod for x86_64::__m128d {} unsafe impl Pod for x86_64::__m128d {}
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
unsafe impl Pod for x86_64::__m256i {} unsafe impl Pod for x86_64::__m256i {}
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
unsafe impl Pod for x86_64::__m256 {} unsafe impl Pod for x86_64::__m256 {}
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
unsafe impl Pod for x86_64::__m256d {} unsafe impl Pod for x86_64::__m256d {}

View File

@ -1,135 +1,135 @@
use super::*; use super::*;
/// A trait which indicates that a type is a `repr(transparent)` wrapper around /// A trait which indicates that a type is a `repr(transparent)` wrapper around
/// the `Wrapped` value. /// the `Wrapped` value.
/// ///
/// This allows safely creating references to `T` from those to the `Wrapped` /// This allows safely creating references to `T` from those to the `Wrapped`
/// type, using the `wrap_ref` and `wrap_mut` functions. /// type, using the `wrap_ref` and `wrap_mut` functions.
/// ///
/// # Safety /// # Safety
/// ///
/// The safety contract of `TransparentWrapper` is relatively simple: /// The safety contract of `TransparentWrapper` is relatively simple:
/// ///
/// For a given `Wrapper` which implements `TransparentWrapper<Wrapped>`: /// For a given `Wrapper` which implements `TransparentWrapper<Wrapped>`:
/// ///
/// 1. Wrapper must be a `#[repr(transparent)]` wrapper around `Wrapped`. This /// 1. Wrapper must be a `#[repr(transparent)]` wrapper around `Wrapped`. This
/// either means that it must be a `#[repr(transparent)]` struct which /// either means that it must be a `#[repr(transparent)]` struct which
/// contains a either a field of type `Wrapped` (or a field of some other /// contains a either a field of type `Wrapped` (or a field of some other
/// transparent wrapper for `Wrapped`) as the only non-ZST field. /// transparent wrapper for `Wrapped`) as the only non-ZST field.
/// ///
/// 2. Any fields *other* than the `Wrapped` field must be trivially /// 2. Any fields *other* than the `Wrapped` field must be trivially
/// constructable ZSTs, for example `PhantomData`, `PhantomPinned`, etc. /// constructable ZSTs, for example `PhantomData`, `PhantomPinned`, etc.
/// ///
/// 3. The `Wrapper` may not impose additional alignment requirements over /// 3. The `Wrapper` may not impose additional alignment requirements over
/// `Wrapped`. /// `Wrapped`.
/// - Note: this is currently guaranteed by `repr(transparent)`, but there /// - Note: this is currently guaranteed by `repr(transparent)`, but there
/// have been discussions of lifting it, so it's stated here explicitly. /// have been discussions of lifting it, so it's stated here explicitly.
/// ///
/// 4. The `wrap_ref` and `wrap_mut` functions on `TransparentWrapper` may not /// 4. The `wrap_ref` and `wrap_mut` functions on `TransparentWrapper` may not
/// be overridden. /// be overridden.
/// ///
/// ## Caveats /// ## Caveats
/// ///
/// If the wrapper imposes additional constraints upon the wrapped type which /// If the wrapper imposes additional constraints upon the wrapped type which
/// are required for safety, it's responsible for ensuring those still hold -- /// are required for safety, it's responsible for ensuring those still hold --
/// this generally requires preventing access to instances of the wrapped type, /// this generally requires preventing access to instances of the wrapped type,
/// as implementing `TransparentWrapper<U> for T` means anybody can call /// as implementing `TransparentWrapper<U> for T` means anybody can call
/// `T::cast_ref(any_instance_of_u)`. /// `T::cast_ref(any_instance_of_u)`.
/// ///
/// For example, it would be invalid to implement TransparentWrapper for `str` /// For example, it would be invalid to implement TransparentWrapper for `str`
/// to implement `TransparentWrapper` around `[u8]` because of this. /// to implement `TransparentWrapper` around `[u8]` because of this.
/// ///
/// # Examples /// # Examples
/// ///
/// ## Basic /// ## Basic
/// ///
/// ``` /// ```
/// use bytemuck::TransparentWrapper; /// use bytemuck::TransparentWrapper;
/// # #[derive(Default)] /// # #[derive(Default)]
/// # struct SomeStruct(u32); /// # struct SomeStruct(u32);
/// ///
/// #[repr(transparent)] /// #[repr(transparent)]
/// struct MyWrapper(SomeStruct); /// struct MyWrapper(SomeStruct);
/// ///
/// unsafe impl TransparentWrapper<SomeStruct> for MyWrapper {} /// unsafe impl TransparentWrapper<SomeStruct> for MyWrapper {}
/// ///
/// // interpret a reference to &SomeStruct as a &MyWrapper /// // interpret a reference to &SomeStruct as a &MyWrapper
/// let thing = SomeStruct::default(); /// let thing = SomeStruct::default();
/// let wrapped_ref: &MyWrapper = MyWrapper::wrap_ref(&thing); /// let wrapped_ref: &MyWrapper = MyWrapper::wrap_ref(&thing);
/// ///
/// // Works with &mut too. /// // Works with &mut too.
/// let mut mut_thing = SomeStruct::default(); /// let mut mut_thing = SomeStruct::default();
/// let wrapped_mut: &mut MyWrapper = MyWrapper::wrap_mut(&mut mut_thing); /// let wrapped_mut: &mut MyWrapper = MyWrapper::wrap_mut(&mut mut_thing);
/// ///
/// # let _ = (wrapped_ref, wrapped_mut); // silence warnings /// # let _ = (wrapped_ref, wrapped_mut); // silence warnings
/// ``` /// ```
/// ///
/// ## Use with dynamically sized types /// ## Use with dynamically sized types
/// ///
/// ``` /// ```
/// use bytemuck::TransparentWrapper; /// use bytemuck::TransparentWrapper;
/// ///
/// #[repr(transparent)] /// #[repr(transparent)]
/// struct Slice<T>([T]); /// struct Slice<T>([T]);
/// ///
/// unsafe impl<T> TransparentWrapper<[T]> for Slice<T> {} /// unsafe impl<T> TransparentWrapper<[T]> for Slice<T> {}
/// ///
/// let s = Slice::wrap_ref(&[1u32, 2, 3]); /// let s = Slice::wrap_ref(&[1u32, 2, 3]);
/// assert_eq!(&s.0, &[1, 2, 3]); /// assert_eq!(&s.0, &[1, 2, 3]);
/// ///
/// let mut buf = [1, 2, 3u8]; /// let mut buf = [1, 2, 3u8];
/// let sm = Slice::wrap_mut(&mut buf); /// let sm = Slice::wrap_mut(&mut buf);
/// ``` /// ```
pub unsafe trait TransparentWrapper<Wrapped: ?Sized> { pub unsafe trait TransparentWrapper<Wrapped: ?Sized> {
/// Convert a reference to a wrapped type into a reference to the wrapper. /// Convert a reference to a wrapped type into a reference to the wrapper.
/// ///
/// This is a trait method so that you can write `MyType::wrap_ref(...)` in /// This is a trait method so that you can write `MyType::wrap_ref(...)` in
/// your code. It is part of the safety contract for this trait that if you /// your code. It is part of the safety contract for this trait that if you
/// implement `TransparentWrapper<_>` for your type you **must not** override /// implement `TransparentWrapper<_>` for your type you **must not** override
/// this method. /// this method.
#[inline] #[inline]
fn wrap_ref(s: &Wrapped) -> &Self { fn wrap_ref(s: &Wrapped) -> &Self {
unsafe { unsafe {
assert!(size_of::<*const Wrapped>() == size_of::<*const Self>()); assert!(size_of::<*const Wrapped>() == size_of::<*const Self>());
// Using a pointer cast doesn't work here because rustc can't tell that the // Using a pointer cast doesn't work here because rustc can't tell that the
// vtables match (if we lifted the ?Sized restriction, this would go away), // vtables match (if we lifted the ?Sized restriction, this would go away),
// and transmute doesn't work for the usual reasons it doesn't work inside // and transmute doesn't work for the usual reasons it doesn't work inside
// generic functions. // generic functions.
// //
// SAFETY: The unsafe contract requires that these have identical // SAFETY: The unsafe contract requires that these have identical
// representations. Using this transmute_copy instead of transmute here is // representations. Using this transmute_copy instead of transmute here is
// annoying, but is required as `Self` and `Wrapped` have unspecified // annoying, but is required as `Self` and `Wrapped` have unspecified
// sizes still. // sizes still.
let wrapped_ptr = s as *const Wrapped; let wrapped_ptr = s as *const Wrapped;
let wrapper_ptr: *const Self = transmute_copy(&wrapped_ptr); let wrapper_ptr: *const Self = transmute_copy(&wrapped_ptr);
&*wrapper_ptr &*wrapper_ptr
} }
} }
/// Convert a mut reference to a wrapped type into a mut reference to the /// Convert a mut reference to a wrapped type into a mut reference to the
/// wrapper. /// wrapper.
/// ///
/// This is a trait method so that you can write `MyType::wrap_mut(...)` in /// This is a trait method so that you can write `MyType::wrap_mut(...)` in
/// your code. It is part of the safety contract for this trait that if you implement /// your code. It is part of the safety contract for this trait that if you implement
/// `TransparentWrapper<_>` for your type you **must not** override this method. /// `TransparentWrapper<_>` for your type you **must not** override this method.
#[inline] #[inline]
fn wrap_mut(s: &mut Wrapped) -> &mut Self { fn wrap_mut(s: &mut Wrapped) -> &mut Self {
unsafe { unsafe {
assert!(size_of::<*mut Wrapped>() == size_of::<*mut Self>()); assert!(size_of::<*mut Wrapped>() == size_of::<*mut Self>());
// Using a pointer cast doesn't work here because rustc can't tell that the // Using a pointer cast doesn't work here because rustc can't tell that the
// vtables match (if we lifted the ?Sized restriction, this would go away), // vtables match (if we lifted the ?Sized restriction, this would go away),
// and transmute doesn't work for the usual reasons it doesn't work inside // and transmute doesn't work for the usual reasons it doesn't work inside
// generic functions. // generic functions.
// //
// SAFETY: The unsafe contract requires that these have identical // SAFETY: The unsafe contract requires that these have identical
// representations. Using this transmute_copy instead of transmute here is // representations. Using this transmute_copy instead of transmute here is
// annoying, but is required as `Self` and `Wrapped` have unspecified // annoying, but is required as `Self` and `Wrapped` have unspecified
// sizes still. // sizes still.
let wrapped_ptr = s as *mut Wrapped; let wrapped_ptr = s as *mut Wrapped;
let wrapper_ptr: *mut Self = transmute_copy(&wrapped_ptr); let wrapper_ptr: *mut Self = transmute_copy(&wrapped_ptr);
&mut *wrapper_ptr &mut *wrapper_ptr
} }
} }
} }
unsafe impl<T> TransparentWrapper<T> for core::num::Wrapping<T> {} unsafe impl<T> TransparentWrapper<T> for core::num::Wrapping<T> {}

View File

@ -1,142 +1,142 @@
use super::*; use super::*;
/// Trait for types that can be safely created with /// Trait for types that can be safely created with
/// [`zeroed`](core::mem::zeroed). /// [`zeroed`](core::mem::zeroed).
/// ///
/// An all-zeroes value may or may not be the same value as the /// An all-zeroes value may or may not be the same value as the
/// [Default](core::default::Default) value of the type. /// [Default](core::default::Default) value of the type.
/// ///
/// ## Safety /// ## Safety
/// ///
/// * Your type must be inhabited (eg: no /// * Your type must be inhabited (eg: no
/// [Infallible](core::convert::Infallible)). /// [Infallible](core::convert::Infallible)).
/// * Your type must be allowed to be an "all zeroes" bit pattern (eg: no /// * Your type must be allowed to be an "all zeroes" bit pattern (eg: no
/// [`NonNull<T>`](core::ptr::NonNull)). /// [`NonNull<T>`](core::ptr::NonNull)).
pub unsafe trait Zeroable: Sized { pub unsafe trait Zeroable: Sized {
/// Calls [`zeroed`](core::mem::zeroed). /// Calls [`zeroed`](core::mem::zeroed).
/// ///
/// This is a trait method so that you can write `MyType::zeroed()` in your /// This is a trait method so that you can write `MyType::zeroed()` in your
/// code. It is a contract of this trait that if you implement it on your type /// code. It is a contract of this trait that if you implement it on your type
/// you **must not** override this method. /// you **must not** override this method.
#[inline] #[inline]
fn zeroed() -> Self { fn zeroed() -> Self {
unsafe { core::mem::zeroed() } unsafe { core::mem::zeroed() }
} }
} }
unsafe impl Zeroable for () {} unsafe impl Zeroable for () {}
unsafe impl Zeroable for bool {} unsafe impl Zeroable for bool {}
unsafe impl Zeroable for char {} unsafe impl Zeroable for char {}
unsafe impl Zeroable for u8 {} unsafe impl Zeroable for u8 {}
unsafe impl Zeroable for i8 {} unsafe impl Zeroable for i8 {}
unsafe impl Zeroable for u16 {} unsafe impl Zeroable for u16 {}
unsafe impl Zeroable for i16 {} unsafe impl Zeroable for i16 {}
unsafe impl Zeroable for u32 {} unsafe impl Zeroable for u32 {}
unsafe impl Zeroable for i32 {} unsafe impl Zeroable for i32 {}
unsafe impl Zeroable for u64 {} unsafe impl Zeroable for u64 {}
unsafe impl Zeroable for i64 {} unsafe impl Zeroable for i64 {}
unsafe impl Zeroable for usize {} unsafe impl Zeroable for usize {}
unsafe impl Zeroable for isize {} unsafe impl Zeroable for isize {}
unsafe impl Zeroable for u128 {} unsafe impl Zeroable for u128 {}
unsafe impl Zeroable for i128 {} unsafe impl Zeroable for i128 {}
unsafe impl Zeroable for f32 {} unsafe impl Zeroable for f32 {}
unsafe impl Zeroable for f64 {} unsafe impl Zeroable for f64 {}
unsafe impl<T: Zeroable> Zeroable for Wrapping<T> {} unsafe impl<T: Zeroable> Zeroable for Wrapping<T> {}
unsafe impl Zeroable for Option<NonZeroI8> {} unsafe impl Zeroable for Option<NonZeroI8> {}
unsafe impl Zeroable for Option<NonZeroI16> {} unsafe impl Zeroable for Option<NonZeroI16> {}
unsafe impl Zeroable for Option<NonZeroI32> {} unsafe impl Zeroable for Option<NonZeroI32> {}
unsafe impl Zeroable for Option<NonZeroI64> {} unsafe impl Zeroable for Option<NonZeroI64> {}
unsafe impl Zeroable for Option<NonZeroI128> {} unsafe impl Zeroable for Option<NonZeroI128> {}
unsafe impl Zeroable for Option<NonZeroIsize> {} unsafe impl Zeroable for Option<NonZeroIsize> {}
unsafe impl Zeroable for Option<NonZeroU8> {} unsafe impl Zeroable for Option<NonZeroU8> {}
unsafe impl Zeroable for Option<NonZeroU16> {} unsafe impl Zeroable for Option<NonZeroU16> {}
unsafe impl Zeroable for Option<NonZeroU32> {} unsafe impl Zeroable for Option<NonZeroU32> {}
unsafe impl Zeroable for Option<NonZeroU64> {} unsafe impl Zeroable for Option<NonZeroU64> {}
unsafe impl Zeroable for Option<NonZeroU128> {} unsafe impl Zeroable for Option<NonZeroU128> {}
unsafe impl Zeroable for Option<NonZeroUsize> {} unsafe impl Zeroable for Option<NonZeroUsize> {}
unsafe impl<T> Zeroable for *mut T {} unsafe impl<T> Zeroable for *mut T {}
unsafe impl<T> Zeroable for *const T {} unsafe impl<T> Zeroable for *const T {}
unsafe impl<T> Zeroable for Option<NonNull<T>> {} unsafe impl<T> Zeroable for Option<NonNull<T>> {}
unsafe impl<T: Zeroable> Zeroable for PhantomData<T> {} unsafe impl<T: Zeroable> Zeroable for PhantomData<T> {}
unsafe impl<T: Zeroable> Zeroable for ManuallyDrop<T> {} unsafe impl<T: Zeroable> Zeroable for ManuallyDrop<T> {}
#[cfg(feature = "zeroable_maybe_uninit")] #[cfg(feature = "zeroable_maybe_uninit")]
unsafe impl<T> Zeroable for core::mem::MaybeUninit<T> {} unsafe impl<T> Zeroable for core::mem::MaybeUninit<T> {}
unsafe impl<A: Zeroable> Zeroable for (A,) {} unsafe impl<A: Zeroable> Zeroable for (A,) {}
unsafe impl<A: Zeroable, B: Zeroable> Zeroable for (A, B) {} unsafe impl<A: Zeroable, B: Zeroable> Zeroable for (A, B) {}
unsafe impl<A: Zeroable, B: Zeroable, C: Zeroable> Zeroable for (A, B, C) {} unsafe impl<A: Zeroable, B: Zeroable, C: Zeroable> Zeroable for (A, B, C) {}
unsafe impl<A: Zeroable, B: Zeroable, C: Zeroable, D: Zeroable> Zeroable unsafe impl<A: Zeroable, B: Zeroable, C: Zeroable, D: Zeroable> Zeroable
for (A, B, C, D) for (A, B, C, D)
{ {
} }
unsafe impl<A: Zeroable, B: Zeroable, C: Zeroable, D: Zeroable, E: Zeroable> unsafe impl<A: Zeroable, B: Zeroable, C: Zeroable, D: Zeroable, E: Zeroable>
Zeroable for (A, B, C, D, E) Zeroable for (A, B, C, D, E)
{ {
} }
unsafe impl< unsafe impl<
A: Zeroable, A: Zeroable,
B: Zeroable, B: Zeroable,
C: Zeroable, C: Zeroable,
D: Zeroable, D: Zeroable,
E: Zeroable, E: Zeroable,
F: Zeroable, F: Zeroable,
> Zeroable for (A, B, C, D, E, F) > Zeroable for (A, B, C, D, E, F)
{ {
} }
unsafe impl< unsafe impl<
A: Zeroable, A: Zeroable,
B: Zeroable, B: Zeroable,
C: Zeroable, C: Zeroable,
D: Zeroable, D: Zeroable,
E: Zeroable, E: Zeroable,
F: Zeroable, F: Zeroable,
G: Zeroable, G: Zeroable,
> Zeroable for (A, B, C, D, E, F, G) > Zeroable for (A, B, C, D, E, F, G)
{ {
} }
unsafe impl< unsafe impl<
A: Zeroable, A: Zeroable,
B: Zeroable, B: Zeroable,
C: Zeroable, C: Zeroable,
D: Zeroable, D: Zeroable,
E: Zeroable, E: Zeroable,
F: Zeroable, F: Zeroable,
G: Zeroable, G: Zeroable,
H: Zeroable, H: Zeroable,
> Zeroable for (A, B, C, D, E, F, G, H) > Zeroable for (A, B, C, D, E, F, G, H)
{ {
} }
impl_unsafe_marker_for_array!( impl_unsafe_marker_for_array!(
Zeroable, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, Zeroable, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 48, 64, 96, 128, 256, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 48, 64, 96, 128, 256,
512, 1024, 2048, 4096 512, 1024, 2048, 4096
); );
#[cfg(target_arch = "x86")] #[cfg(target_arch = "x86")]
unsafe impl Zeroable for x86::__m128i {} unsafe impl Zeroable for x86::__m128i {}
#[cfg(target_arch = "x86")] #[cfg(target_arch = "x86")]
unsafe impl Zeroable for x86::__m128 {} unsafe impl Zeroable for x86::__m128 {}
#[cfg(target_arch = "x86")] #[cfg(target_arch = "x86")]
unsafe impl Zeroable for x86::__m128d {} unsafe impl Zeroable for x86::__m128d {}
#[cfg(target_arch = "x86")] #[cfg(target_arch = "x86")]
unsafe impl Zeroable for x86::__m256i {} unsafe impl Zeroable for x86::__m256i {}
#[cfg(target_arch = "x86")] #[cfg(target_arch = "x86")]
unsafe impl Zeroable for x86::__m256 {} unsafe impl Zeroable for x86::__m256 {}
#[cfg(target_arch = "x86")] #[cfg(target_arch = "x86")]
unsafe impl Zeroable for x86::__m256d {} unsafe impl Zeroable for x86::__m256d {}
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
unsafe impl Zeroable for x86_64::__m128i {} unsafe impl Zeroable for x86_64::__m128i {}
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
unsafe impl Zeroable for x86_64::__m128 {} unsafe impl Zeroable for x86_64::__m128 {}
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
unsafe impl Zeroable for x86_64::__m128d {} unsafe impl Zeroable for x86_64::__m128d {}
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
unsafe impl Zeroable for x86_64::__m256i {} unsafe impl Zeroable for x86_64::__m256i {}
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
unsafe impl Zeroable for x86_64::__m256 {} unsafe impl Zeroable for x86_64::__m256 {}
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
unsafe impl Zeroable for x86_64::__m256d {} unsafe impl Zeroable for x86_64::__m256d {}

View File

@ -1,165 +1,165 @@
use core::mem::size_of; use core::mem::size_of;
use bytemuck::*; use bytemuck::*;
#[test] #[test]
fn test_try_cast_slice() { fn test_try_cast_slice() {
// some align4 data // some align4 data
let u32_slice: &[u32] = &[4, 5, 6]; let u32_slice: &[u32] = &[4, 5, 6];
// the same data as align1 // the same data as align1
let the_bytes: &[u8] = try_cast_slice(u32_slice).unwrap(); let the_bytes: &[u8] = try_cast_slice(u32_slice).unwrap();
assert_eq!( assert_eq!(
u32_slice.as_ptr() as *const u32 as usize, u32_slice.as_ptr() as *const u32 as usize,
the_bytes.as_ptr() as *const u8 as usize the_bytes.as_ptr() as *const u8 as usize
); );
assert_eq!( assert_eq!(
u32_slice.len() * size_of::<u32>(), u32_slice.len() * size_of::<u32>(),
the_bytes.len() * size_of::<u8>() the_bytes.len() * size_of::<u8>()
); );
// by taking one byte off the front, we're definitely mis-aligned for u32. // by taking one byte off the front, we're definitely mis-aligned for u32.
let mis_aligned_bytes = &the_bytes[1..]; let mis_aligned_bytes = &the_bytes[1..];
assert_eq!( assert_eq!(
try_cast_slice::<u8, u32>(mis_aligned_bytes), try_cast_slice::<u8, u32>(mis_aligned_bytes),
Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned) Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned)
); );
// by taking one byte off the end, we're aligned but would have slop bytes for u32 // by taking one byte off the end, we're aligned but would have slop bytes for u32
let the_bytes_len_minus1 = the_bytes.len() - 1; let the_bytes_len_minus1 = the_bytes.len() - 1;
let slop_bytes = &the_bytes[..the_bytes_len_minus1]; let slop_bytes = &the_bytes[..the_bytes_len_minus1];
assert_eq!( assert_eq!(
try_cast_slice::<u8, u32>(slop_bytes), try_cast_slice::<u8, u32>(slop_bytes),
Err(PodCastError::OutputSliceWouldHaveSlop) Err(PodCastError::OutputSliceWouldHaveSlop)
); );
// if we don't mess with it we can up-alignment cast // if we don't mess with it we can up-alignment cast
try_cast_slice::<u8, u32>(the_bytes).unwrap(); try_cast_slice::<u8, u32>(the_bytes).unwrap();
} }
#[test] #[test]
fn test_try_cast_slice_mut() { fn test_try_cast_slice_mut() {
// some align4 data // some align4 data
let u32_slice: &mut [u32] = &mut [4, 5, 6]; let u32_slice: &mut [u32] = &mut [4, 5, 6];
let u32_len = u32_slice.len(); let u32_len = u32_slice.len();
let u32_ptr = u32_slice.as_ptr(); let u32_ptr = u32_slice.as_ptr();
// the same data as align1 // the same data as align1
let the_bytes: &mut [u8] = try_cast_slice_mut(u32_slice).unwrap(); let the_bytes: &mut [u8] = try_cast_slice_mut(u32_slice).unwrap();
let the_bytes_len = the_bytes.len(); let the_bytes_len = the_bytes.len();
let the_bytes_ptr = the_bytes.as_ptr(); let the_bytes_ptr = the_bytes.as_ptr();
assert_eq!( assert_eq!(
u32_ptr as *const u32 as usize, u32_ptr as *const u32 as usize,
the_bytes_ptr as *const u8 as usize the_bytes_ptr as *const u8 as usize
); );
assert_eq!(u32_len * size_of::<u32>(), the_bytes_len * size_of::<u8>()); assert_eq!(u32_len * size_of::<u32>(), the_bytes_len * size_of::<u8>());
// by taking one byte off the front, we're definitely mis-aligned for u32. // by taking one byte off the front, we're definitely mis-aligned for u32.
let mis_aligned_bytes = &mut the_bytes[1..]; let mis_aligned_bytes = &mut the_bytes[1..];
assert_eq!( assert_eq!(
try_cast_slice_mut::<u8, u32>(mis_aligned_bytes), try_cast_slice_mut::<u8, u32>(mis_aligned_bytes),
Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned) Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned)
); );
// by taking one byte off the end, we're aligned but would have slop bytes for u32 // by taking one byte off the end, we're aligned but would have slop bytes for u32
let the_bytes_len_minus1 = the_bytes.len() - 1; let the_bytes_len_minus1 = the_bytes.len() - 1;
let slop_bytes = &mut the_bytes[..the_bytes_len_minus1]; let slop_bytes = &mut the_bytes[..the_bytes_len_minus1];
assert_eq!( assert_eq!(
try_cast_slice_mut::<u8, u32>(slop_bytes), try_cast_slice_mut::<u8, u32>(slop_bytes),
Err(PodCastError::OutputSliceWouldHaveSlop) Err(PodCastError::OutputSliceWouldHaveSlop)
); );
// if we don't mess with it we can up-alignment cast // if we don't mess with it we can up-alignment cast
try_cast_slice_mut::<u8, u32>(the_bytes).unwrap(); try_cast_slice_mut::<u8, u32>(the_bytes).unwrap();
} }
#[test] #[test]
fn test_types() { fn test_types() {
let _: i32 = cast(1.0_f32); let _: i32 = cast(1.0_f32);
let _: &mut i32 = cast_mut(&mut 1.0_f32); let _: &mut i32 = cast_mut(&mut 1.0_f32);
let _: &i32 = cast_ref(&1.0_f32); let _: &i32 = cast_ref(&1.0_f32);
let _: &[i32] = cast_slice(&[1.0_f32]); let _: &[i32] = cast_slice(&[1.0_f32]);
let _: &mut [i32] = cast_slice_mut(&mut [1.0_f32]); let _: &mut [i32] = cast_slice_mut(&mut [1.0_f32]);
// //
let _: Result<i32, PodCastError> = try_cast(1.0_f32); let _: Result<i32, PodCastError> = try_cast(1.0_f32);
let _: Result<&mut i32, PodCastError> = try_cast_mut(&mut 1.0_f32); let _: Result<&mut i32, PodCastError> = try_cast_mut(&mut 1.0_f32);
let _: Result<&i32, PodCastError> = try_cast_ref(&1.0_f32); let _: Result<&i32, PodCastError> = try_cast_ref(&1.0_f32);
let _: Result<&[i32], PodCastError> = try_cast_slice(&[1.0_f32]); let _: Result<&[i32], PodCastError> = try_cast_slice(&[1.0_f32]);
let _: Result<&mut [i32], PodCastError> = try_cast_slice_mut(&mut [1.0_f32]); let _: Result<&mut [i32], PodCastError> = try_cast_slice_mut(&mut [1.0_f32]);
} }
#[test] #[test]
fn test_bytes_of() { fn test_bytes_of() {
assert_eq!(bytes_of(&0xaabbccdd_u32), &0xaabbccdd_u32.to_ne_bytes()); assert_eq!(bytes_of(&0xaabbccdd_u32), &0xaabbccdd_u32.to_ne_bytes());
assert_eq!(bytes_of_mut(&mut 0xaabbccdd_u32), &mut 0xaabbccdd_u32.to_ne_bytes()); assert_eq!(bytes_of_mut(&mut 0xaabbccdd_u32), &mut 0xaabbccdd_u32.to_ne_bytes());
let mut a = 0xaabbccdd_u32; let mut a = 0xaabbccdd_u32;
let a_addr = &a as *const _ as usize; let a_addr = &a as *const _ as usize;
// ensure addresses match. // ensure addresses match.
assert_eq!(bytes_of(&a).as_ptr() as usize, a_addr); assert_eq!(bytes_of(&a).as_ptr() as usize, a_addr);
assert_eq!(bytes_of_mut(&mut a).as_ptr() as usize, a_addr); assert_eq!(bytes_of_mut(&mut a).as_ptr() as usize, a_addr);
} }
#[test] #[test]
fn test_try_from_bytes() { fn test_try_from_bytes() {
let u32s = [0xaabbccdd, 0x11223344_u32]; let u32s = [0xaabbccdd, 0x11223344_u32];
let bytes = bytemuck::cast_slice::<u32, u8>(&u32s); let bytes = bytemuck::cast_slice::<u32, u8>(&u32s);
assert_eq!(try_from_bytes::<u32>(&bytes[..4]), Ok(&u32s[0])); assert_eq!(try_from_bytes::<u32>(&bytes[..4]), Ok(&u32s[0]));
assert_eq!(try_from_bytes::<u32>(&bytes[..5]), Err(PodCastError::SizeMismatch)); assert_eq!(try_from_bytes::<u32>(&bytes[..5]), Err(PodCastError::SizeMismatch));
assert_eq!(try_from_bytes::<u32>(&bytes[..3]), Err(PodCastError::SizeMismatch)); assert_eq!(try_from_bytes::<u32>(&bytes[..3]), Err(PodCastError::SizeMismatch));
assert_eq!(try_from_bytes::<u32>(&bytes[1..5]), Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned)); assert_eq!(try_from_bytes::<u32>(&bytes[1..5]), Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned));
} }
#[test] #[test]
fn test_try_from_bytes_mut() { fn test_try_from_bytes_mut() {
let mut abcd = 0xaabbccdd; let mut abcd = 0xaabbccdd;
let mut u32s = [abcd, 0x11223344_u32]; let mut u32s = [abcd, 0x11223344_u32];
let bytes = bytemuck::cast_slice_mut::<u32, u8>(&mut u32s); let bytes = bytemuck::cast_slice_mut::<u32, u8>(&mut u32s);
assert_eq!(try_from_bytes_mut::<u32>(&mut bytes[..4]), Ok(&mut abcd)); assert_eq!(try_from_bytes_mut::<u32>(&mut bytes[..4]), Ok(&mut abcd));
assert_eq!(try_from_bytes_mut::<u32>(&mut bytes[..4]), Ok(&mut abcd)); assert_eq!(try_from_bytes_mut::<u32>(&mut bytes[..4]), Ok(&mut abcd));
assert_eq!(try_from_bytes_mut::<u32>(&mut bytes[..5]), Err(PodCastError::SizeMismatch)); assert_eq!(try_from_bytes_mut::<u32>(&mut bytes[..5]), Err(PodCastError::SizeMismatch));
assert_eq!(try_from_bytes_mut::<u32>(&mut bytes[..3]), Err(PodCastError::SizeMismatch)); assert_eq!(try_from_bytes_mut::<u32>(&mut bytes[..3]), Err(PodCastError::SizeMismatch));
assert_eq!(try_from_bytes::<u32>(&mut bytes[1..5]), Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned)); assert_eq!(try_from_bytes::<u32>(&mut bytes[1..5]), Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned));
} }
#[test] #[test]
fn test_from_bytes() { fn test_from_bytes() {
let abcd = 0xaabbccdd_u32; let abcd = 0xaabbccdd_u32;
let aligned_bytes = bytemuck::bytes_of(&abcd); let aligned_bytes = bytemuck::bytes_of(&abcd);
assert_eq!(from_bytes::<u32>(aligned_bytes), &abcd); assert_eq!(from_bytes::<u32>(aligned_bytes), &abcd);
assert!(core::ptr::eq(from_bytes(aligned_bytes), &abcd)); assert!(core::ptr::eq(from_bytes(aligned_bytes), &abcd));
} }
#[test] #[test]
fn test_from_bytes_mut() { fn test_from_bytes_mut() {
let mut a = 0xaabbccdd_u32; let mut a = 0xaabbccdd_u32;
let a_addr = &a as *const _ as usize; let a_addr = &a as *const _ as usize;
let aligned_bytes = bytemuck::bytes_of_mut(&mut a); let aligned_bytes = bytemuck::bytes_of_mut(&mut a);
assert_eq!(*from_bytes_mut::<u32>(aligned_bytes), 0xaabbccdd_u32); assert_eq!(*from_bytes_mut::<u32>(aligned_bytes), 0xaabbccdd_u32);
assert_eq!(from_bytes_mut::<u32>(aligned_bytes) as *const u32 as usize, a_addr); assert_eq!(from_bytes_mut::<u32>(aligned_bytes) as *const u32 as usize, a_addr);
} }
// like #[should_panic], but can be a part of another test, instead of requiring // like #[should_panic], but can be a part of another test, instead of requiring
// it to be it's own test. // it to be it's own test.
macro_rules! should_panic { macro_rules! should_panic {
($ex:expr) => { ($ex:expr) => {
assert!( assert!(
std::panic::catch_unwind(|| { let _ = $ex; }).is_err(), std::panic::catch_unwind(|| { let _ = $ex; }).is_err(),
concat!("should have panicked: `", stringify!($ex), "`") concat!("should have panicked: `", stringify!($ex), "`")
); );
}; };
} }
#[test] #[test]
fn test_panics() { fn test_panics() {
should_panic!(cast_slice::<u8, u32>(&[1u8, 2u8])); should_panic!(cast_slice::<u8, u32>(&[1u8, 2u8]));
should_panic!(cast_slice_mut::<u8, u32>(&mut [1u8, 2u8])); should_panic!(cast_slice_mut::<u8, u32>(&mut [1u8, 2u8]));
should_panic!(from_bytes::<u32>(&[1u8, 2])); should_panic!(from_bytes::<u32>(&[1u8, 2]));
should_panic!(from_bytes::<u32>(&[1u8, 2, 3, 4, 5])); should_panic!(from_bytes::<u32>(&[1u8, 2, 3, 4, 5]));
should_panic!(from_bytes_mut::<u32>(&mut [1u8, 2])); should_panic!(from_bytes_mut::<u32>(&mut [1u8, 2]));
should_panic!(from_bytes_mut::<u32>(&mut [1u8, 2, 3, 4, 5])); should_panic!(from_bytes_mut::<u32>(&mut [1u8, 2, 3, 4, 5]));
// use cast_slice on some u32s to get some align>=4 bytes, so we can know // use cast_slice on some u32s to get some align>=4 bytes, so we can know
// we'll give from_bytes unaligned ones. // we'll give from_bytes unaligned ones.
let aligned_bytes = bytemuck::cast_slice::<u32, u8>(&[0, 0]); let aligned_bytes = bytemuck::cast_slice::<u32, u8>(&[0, 0]);
should_panic!(from_bytes::<u32>(&aligned_bytes[1..5])); should_panic!(from_bytes::<u32>(&aligned_bytes[1..5]));
} }

View File

@ -1,25 +1,25 @@
#![cfg(feature = "derive")] #![cfg(feature = "derive")]
#![allow(dead_code)] #![allow(dead_code)]
use bytemuck::{Zeroable, Pod, TransparentWrapper}; use bytemuck::{Zeroable, Pod, TransparentWrapper};
#[derive(Copy, Clone, Pod, Zeroable)] #[derive(Copy, Clone, Pod, Zeroable)]
#[repr(C)] #[repr(C)]
struct Test { struct Test {
a: u16, a: u16,
b: u16, b: u16,
} }
#[derive(TransparentWrapper)] #[derive(TransparentWrapper)]
#[repr(transparent)] #[repr(transparent)]
struct TransparentSingle { struct TransparentSingle {
a: u16, a: u16,
} }
#[derive(TransparentWrapper)] #[derive(TransparentWrapper)]
#[repr(transparent)] #[repr(transparent)]
#[transparent(u16)] #[transparent(u16)]
struct TransparentWithZeroSized { struct TransparentWithZeroSized {
a: u16, a: u16,
b: () b: ()
} }

View File

@ -1,121 +1,121 @@
//! Cargo miri doesn't run doctests yet, so we duplicate these here. It's //! Cargo miri doesn't run doctests yet, so we duplicate these here. It's
//! probably not that important to sweat keeping these perfectly up to date, but //! probably not that important to sweat keeping these perfectly up to date, but
//! we should try to catch the cases where the primary tests are doctests. //! we should try to catch the cases where the primary tests are doctests.
use bytemuck::*; use bytemuck::*;
// Miri doesn't run on doctests, so... copypaste to the rescue. // Miri doesn't run on doctests, so... copypaste to the rescue.
#[test] #[test]
fn test_transparent_slice() { fn test_transparent_slice() {
#[repr(transparent)] #[repr(transparent)]
struct Slice<T>([T]); struct Slice<T>([T]);
unsafe impl<T> TransparentWrapper<[T]> for Slice<T> {} unsafe impl<T> TransparentWrapper<[T]> for Slice<T> {}
let s = Slice::wrap_ref(&[1u32, 2, 3]); let s = Slice::wrap_ref(&[1u32, 2, 3]);
assert_eq!(&s.0, &[1, 2, 3]); assert_eq!(&s.0, &[1, 2, 3]);
let mut buf = [1, 2, 3u8]; let mut buf = [1, 2, 3u8];
let _sm = Slice::wrap_mut(&mut buf); let _sm = Slice::wrap_mut(&mut buf);
} }
#[test] #[test]
fn test_transparent_basic() { fn test_transparent_basic() {
#[derive(Default)] #[derive(Default)]
struct SomeStruct(u32); struct SomeStruct(u32);
#[repr(transparent)] #[repr(transparent)]
struct MyWrapper(SomeStruct); struct MyWrapper(SomeStruct);
unsafe impl TransparentWrapper<SomeStruct> for MyWrapper {} unsafe impl TransparentWrapper<SomeStruct> for MyWrapper {}
// interpret a reference to &SomeStruct as a &MyWrapper // interpret a reference to &SomeStruct as a &MyWrapper
let thing = SomeStruct::default(); let thing = SomeStruct::default();
let wrapped_ref: &MyWrapper = MyWrapper::wrap_ref(&thing); let wrapped_ref: &MyWrapper = MyWrapper::wrap_ref(&thing);
// Works with &mut too. // Works with &mut too.
let mut mut_thing = SomeStruct::default(); let mut mut_thing = SomeStruct::default();
let wrapped_mut: &mut MyWrapper = MyWrapper::wrap_mut(&mut mut_thing); let wrapped_mut: &mut MyWrapper = MyWrapper::wrap_mut(&mut mut_thing);
let _ = (wrapped_ref, wrapped_mut); let _ = (wrapped_ref, wrapped_mut);
} }
// Work around miri not running doctests // Work around miri not running doctests
#[test] #[test]
fn test_contiguous_doc() { fn test_contiguous_doc() {
#[repr(u8)] #[repr(u8)]
#[derive(Debug, Copy, Clone, PartialEq)] #[derive(Debug, Copy, Clone, PartialEq)]
enum Foo { enum Foo {
A = 0, A = 0,
B = 1, B = 1,
C = 2, C = 2,
D = 3, D = 3,
E = 4, E = 4,
} }
unsafe impl Contiguous for Foo { unsafe impl Contiguous for Foo {
type Int = u8; type Int = u8;
const MIN_VALUE: u8 = Foo::A as u8; const MIN_VALUE: u8 = Foo::A as u8;
const MAX_VALUE: u8 = Foo::E as u8; const MAX_VALUE: u8 = Foo::E as u8;
} }
assert_eq!(Foo::from_integer(3).unwrap(), Foo::D); assert_eq!(Foo::from_integer(3).unwrap(), Foo::D);
assert_eq!(Foo::from_integer(8), None); assert_eq!(Foo::from_integer(8), None);
assert_eq!(Foo::C.into_integer(), 2); assert_eq!(Foo::C.into_integer(), 2);
assert_eq!(Foo::B.into_integer(), Foo::B as u8); assert_eq!(Foo::B.into_integer(), Foo::B as u8);
} }
#[test] #[test]
fn test_offsetof_vertex() { fn test_offsetof_vertex() {
#[repr(C)] #[repr(C)]
struct Vertex { struct Vertex {
pos: [f32; 2], pos: [f32; 2],
uv: [u16; 2], uv: [u16; 2],
color: [u8; 4], color: [u8; 4],
} }
unsafe impl Zeroable for Vertex {} unsafe impl Zeroable for Vertex {}
let pos = offset_of!(Zeroable::zeroed(), Vertex, pos); let pos = offset_of!(Zeroable::zeroed(), Vertex, pos);
let uv = offset_of!(Zeroable::zeroed(), Vertex, uv); let uv = offset_of!(Zeroable::zeroed(), Vertex, uv);
let color = offset_of!(Zeroable::zeroed(), Vertex, color); let color = offset_of!(Zeroable::zeroed(), Vertex, color);
assert_eq!(pos, 0); assert_eq!(pos, 0);
assert_eq!(uv, 8); assert_eq!(uv, 8);
assert_eq!(color, 12); assert_eq!(color, 12);
} }
#[test] #[test]
fn test_offsetof_nonpod() { fn test_offsetof_nonpod() {
#[derive(Default)] #[derive(Default)]
struct Foo { struct Foo {
a: u8, a: u8,
b: &'static str, b: &'static str,
c: i32, c: i32,
} }
let a_offset = offset_of!(Default::default(), Foo, a); let a_offset = offset_of!(Default::default(), Foo, a);
let b_offset = offset_of!(Default::default(), Foo, b); let b_offset = offset_of!(Default::default(), Foo, b);
let c_offset = offset_of!(Default::default(), Foo, c); let c_offset = offset_of!(Default::default(), Foo, c);
assert_ne!(a_offset, b_offset); assert_ne!(a_offset, b_offset);
assert_ne!(b_offset, c_offset); assert_ne!(b_offset, c_offset);
// We can't check against hardcoded values for a repr(Rust) type, // We can't check against hardcoded values for a repr(Rust) type,
// but prove to ourself this way. // but prove to ourself this way.
let foo = Foo::default(); let foo = Foo::default();
// Note: offsets are in bytes. // Note: offsets are in bytes.
let as_bytes = &foo as *const _ as *const u8; let as_bytes = &foo as *const _ as *const u8;
// we're using wrapping_offset here becasue it's not worth // we're using wrapping_offset here becasue it's not worth
// the unsafe block, but it would be valid to use `add` instead, // the unsafe block, but it would be valid to use `add` instead,
// as it cannot overflow. // as it cannot overflow.
assert_eq!( assert_eq!(
&foo.a as *const _ as usize, &foo.a as *const _ as usize,
as_bytes.wrapping_add(a_offset) as usize as_bytes.wrapping_add(a_offset) as usize
); );
assert_eq!( assert_eq!(
&foo.b as *const _ as usize, &foo.b as *const _ as usize,
as_bytes.wrapping_add(b_offset) as usize as_bytes.wrapping_add(b_offset) as usize
); );
assert_eq!( assert_eq!(
&foo.c as *const _ as usize, &foo.c as *const _ as usize,
as_bytes.wrapping_add(c_offset) as usize as_bytes.wrapping_add(c_offset) as usize
); );
} }

View File

@ -1,59 +1,59 @@
use bytemuck::{offset_of, Zeroable}; use bytemuck::{offset_of, Zeroable};
#[test] #[test]
fn test_offset_of_vertex() { fn test_offset_of_vertex() {
#[repr(C)] #[repr(C)]
struct Vertex { struct Vertex {
pos: [f32; 2], pos: [f32; 2],
uv: [u16; 2], uv: [u16; 2],
color: [u8; 4], color: [u8; 4],
} }
unsafe impl Zeroable for Vertex {} unsafe impl Zeroable for Vertex {}
let pos = offset_of!(Zeroable::zeroed(), Vertex, pos); let pos = offset_of!(Zeroable::zeroed(), Vertex, pos);
let uv = offset_of!(Zeroable::zeroed(), Vertex, uv); let uv = offset_of!(Zeroable::zeroed(), Vertex, uv);
let color = offset_of!(Zeroable::zeroed(), Vertex, color); let color = offset_of!(Zeroable::zeroed(), Vertex, color);
assert_eq!(pos, 0); assert_eq!(pos, 0);
assert_eq!(uv, 8); assert_eq!(uv, 8);
assert_eq!(color, 12); assert_eq!(color, 12);
} }
#[test] #[test]
fn test_offset_of_foo() { fn test_offset_of_foo() {
#[derive(Default)] #[derive(Default)]
struct Foo { struct Foo {
a: u8, a: u8,
b: &'static str, b: &'static str,
c: i32, c: i32,
} }
let a_offset = offset_of!(Default::default(), Foo, a); let a_offset = offset_of!(Default::default(), Foo, a);
let b_offset = offset_of!(Default::default(), Foo, b); let b_offset = offset_of!(Default::default(), Foo, b);
let c_offset = offset_of!(Default::default(), Foo, c); let c_offset = offset_of!(Default::default(), Foo, c);
assert_ne!(a_offset, b_offset); assert_ne!(a_offset, b_offset);
assert_ne!(b_offset, c_offset); assert_ne!(b_offset, c_offset);
// We can't check against hardcoded values for a repr(Rust) type, // We can't check against hardcoded values for a repr(Rust) type,
// but prove to ourself this way. // but prove to ourself this way.
let foo = Foo::default(); let foo = Foo::default();
// Note: offsets are in bytes. // Note: offsets are in bytes.
let as_bytes = &foo as *const _ as *const u8; let as_bytes = &foo as *const _ as *const u8;
// we're using wrapping_offset here because it's not worth // we're using wrapping_offset here because it's not worth
// the unsafe block, but it would be valid to use `add` instead, // the unsafe block, but it would be valid to use `add` instead,
// as it cannot overflow. // as it cannot overflow.
assert_eq!( assert_eq!(
&foo.a as *const _ as usize, &foo.a as *const _ as usize,
as_bytes.wrapping_add(a_offset) as usize as_bytes.wrapping_add(a_offset) as usize
); );
assert_eq!( assert_eq!(
&foo.b as *const _ as usize, &foo.b as *const _ as usize,
as_bytes.wrapping_add(b_offset) as usize as_bytes.wrapping_add(b_offset) as usize
); );
assert_eq!( assert_eq!(
&foo.c as *const _ as usize, &foo.c as *const _ as usize,
as_bytes.wrapping_add(c_offset) as usize as_bytes.wrapping_add(c_offset) as usize
); );
} }

View File

@ -1,29 +1,45 @@
//! The integration tests seem to always have `std` linked, so things that would //! The integration tests seem to always have `std` linked, so things that would
//! depend on that can go here. //! depend on that can go here.
use bytemuck::*; use bytemuck::*;
#[test] #[test]
fn test_transparent_vtabled() { fn test_transparent_vtabled() {
use core::fmt::Display; use core::fmt::Display;
#[repr(transparent)] #[repr(transparent)]
struct DisplayTraitObj(dyn Display); struct DisplayTraitObj(dyn Display);
unsafe impl TransparentWrapper<dyn Display> for DisplayTraitObj {} unsafe impl TransparentWrapper<dyn Display> for DisplayTraitObj {}
impl Display for DisplayTraitObj { impl Display for DisplayTraitObj {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.0.fmt(f) self.0.fmt(f)
} }
} }
let v = DisplayTraitObj::wrap_ref(&5i32); let v = DisplayTraitObj::wrap_ref(&5i32);
let s = format!("{}", v); let s = format!("{}", v);
assert_eq!(s, "5"); assert_eq!(s, "5");
let mut x = 100i32; let mut x = 100i32;
let v_mut = DisplayTraitObj::wrap_mut(&mut x); let v_mut = DisplayTraitObj::wrap_mut(&mut x);
let s = format!("{}", v_mut); let s = format!("{}", v_mut);
assert_eq!(s, "100"); assert_eq!(s, "100");
} }
#[test]
#[cfg(feature = "extern_crate_alloc")]
fn test_large_box_alloc() {
type SuperPage = [[u8; 4096]; 4096];
let _: Box<SuperPage> = try_zeroed_box().unwrap();
}
#[test]
#[cfg(feature = "extern_crate_alloc")]
fn test_zero_sized_box_alloc() {
#[repr(align(4096))]
struct Empty;
unsafe impl Zeroable for Empty {}
let _: Box<Empty> = try_zeroed_box().unwrap();
}

View File

@ -1 +0,0 @@
{"files":{"CHANGELOG.md":"51f0eb3b6139fc1a908d41a7b3cba7d58d684700986b3518f82e5af254c39e8e","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"fb8b84be3b93b1aa065558cf9f8a867e1fc0f9bda8323d686ece79bbcfe50868","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"b2dd89866b56f619661b90e8b3b7d3f741b0a8d5710e229df86843ae0881284f","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","benches/bench.rs":"80e43e07f34bc6d3ebe4f37cea79ba02cafce6cf30b737a1db65de55f2c38ca5","build.rs":"9671089eb30f52975911effd1fa0b30a0ab14473f44a315af0bafd6701dda6da","src/io.rs":"8f22d1b0e01fa4ce9c7c5cd727dbc40ca35c22d9c82fe8d324d9d83d37cdcc4a","src/lib.rs":"c43331d25d0d12e150b64137d6f180ae46a8c41124a374e4f62d2867482bd3d8"},"package":"08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"}

View File

@ -1,90 +0,0 @@
// For the 'try!' macro, until we bump MSRV past 1.12.
#![allow(deprecated)]
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

@ -0,0 +1 @@
{"files":{"CHANGELOG.md":"3a745d94ee9dce0d9dc638c02078cd5001d3d9d12d58b4f220c0101e32cfc16a","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"8585455e5a0e638cf5d489a21e286e93680f835cb8a13595918b5eb7c8c7f212","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"9d57556868344534de2489317e3c6bb611348ecd44438dcb982bd8d2a55a5a1b","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","benches/bench.rs":"a80bf3cd446c9b6c0cca3865c4de047bdf4644b74cdf696822f8ff87adfa1fca","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","src/io.rs":"9612530634d0e7ce9887a23836b58c0d972c1f45b05d9ada8355961567075627","src/lib.rs":"813ce6a8beafee3fd4e63325d783108aa02e8c57e412bc97580191d84082fbc9"},"package":"14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"}

View File

@ -32,8 +32,6 @@ licenses([
# Unsupported target "bench" with type "bench" omitted # Unsupported target "bench" with type "bench" omitted
# Unsupported target "build-script-build" with type "custom-build" omitted
rust_library( rust_library(
name = "byteorder", name = "byteorder",
srcs = glob(["**/*.rs"]), srcs = glob(["**/*.rs"]),
@ -44,7 +42,7 @@ rust_library(
crate_root = "src/lib.rs", crate_root = "src/lib.rs",
crate_type = "lib", crate_type = "lib",
data = [], data = [],
edition = "2015", edition = "2018",
rustc_flags = [ rustc_flags = [
"--cap-lints=allow", "--cap-lints=allow",
], ],
@ -52,7 +50,7 @@ rust_library(
"cargo-raze", "cargo-raze",
"manual", "manual",
], ],
version = "1.3.4", version = "1.4.3",
# buildifier: leave-alone # buildifier: leave-alone
deps = [ deps = [
], ],

View File

@ -1,3 +1,28 @@
1.3.4
=====
This patch release squashes deprecation warnings for the `try!` macro, in
accordance with byteorder's minimum supported Rust version (currently at Rust
1.12.0).
1.3.3
=====
This patch release adds `ByteOrder::write_i8_into()` as a simple, safe interface
for ordinarily unsafe or tedious code.
1.3.2
=====
This patch release adds `ReadBytesExt::read_i8_into()` as a simple, safe interface
for ordinarily unsafe or tedious code.
1.3.1
=====
This minor release performs mostly small internal changes. Going forward, these
are not going to be incorporated into the changelog.
1.3.0 1.3.0
===== =====
This new minor release now enables `i128` support automatically on Rust This new minor release now enables `i128` support automatically on Rust

View File

@ -11,17 +11,17 @@
# will likely look very different (and much more reasonable) # will likely look very different (and much more reasonable)
[package] [package]
edition = "2018"
name = "byteorder" name = "byteorder"
version = "1.3.4" version = "1.4.3"
authors = ["Andrew Gallant <jamslam@gmail.com>"] authors = ["Andrew Gallant <jamslam@gmail.com>"]
build = "build.rs"
exclude = ["/ci/*"] exclude = ["/ci/*"]
description = "Library for reading/writing numbers in big-endian and little-endian." description = "Library for reading/writing numbers in big-endian and little-endian."
homepage = "https://github.com/BurntSushi/byteorder" homepage = "https://github.com/BurntSushi/byteorder"
documentation = "https://docs.rs/byteorder" documentation = "https://docs.rs/byteorder"
readme = "README.md" readme = "README.md"
keywords = ["byte", "endian", "big-endian", "little-endian", "binary"] keywords = ["byte", "endian", "big-endian", "little-endian", "binary"]
categories = ["encoding", "parsing"] categories = ["encoding", "parsing", "no-std"]
license = "Unlicense OR MIT" license = "Unlicense OR MIT"
repository = "https://github.com/BurntSushi/byteorder" repository = "https://github.com/BurntSushi/byteorder"
[profile.bench] [profile.bench]
@ -30,19 +30,14 @@ opt-level = 3
[lib] [lib]
name = "byteorder" name = "byteorder"
bench = false bench = false
[dev-dependencies.doc-comment]
version = "0.3"
[dev-dependencies.quickcheck] [dev-dependencies.quickcheck]
version = "0.8" version = "0.9.2"
default-features = false default-features = false
[dev-dependencies.rand] [dev-dependencies.rand]
version = "0.6" version = "0.7"
[features] [features]
default = ["std"] default = ["std"]
i128 = [] i128 = []
std = [] std = []
[badges.travis-ci]
repository = "BurntSushi/byteorder"

View File

@ -1,10 +1,12 @@
byteorder
=========
This crate provides convenience methods for encoding and decoding This crate provides convenience methods for encoding and decoding
numbers in either big-endian or little-endian order. numbers in either big-endian or little-endian order.
[![Build status](https://api.travis-ci.org/BurntSushi/byteorder.svg)](https://travis-ci.org/BurntSushi/byteorder) [![Build status](https://github.com/BurntSushi/byteorder/workflows/ci/badge.svg)](https://github.com/BurntSushi/byteorder/actions)
[![](http://meritbadge.herokuapp.com/byteorder)](https://crates.io/crates/byteorder) [![](https://meritbadge.herokuapp.com/byteorder)](https://crates.io/crates/byteorder)
Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org). Dual-licensed under MIT or the [UNLICENSE](https://unlicense.org/).
### Documentation ### Documentation
@ -27,8 +29,6 @@ If you want to augment existing `Read` and `Write` traits, then import the
extension methods like so: extension methods like so:
```rust ```rust
extern crate byteorder;
use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian, LittleEndian}; use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian, LittleEndian};
``` ```

View File

@ -1,15 +1,15 @@
#![feature(test)] #![feature(test)]
extern crate byteorder;
extern crate rand;
extern crate test; extern crate test;
macro_rules! bench_num { macro_rules! bench_num {
($name:ident, $read:ident, $bytes:expr, $data:expr) => ( ($name:ident, $read:ident, $bytes:expr, $data:expr) => {
mod $name { mod $name {
use byteorder::{ByteOrder, BigEndian, NativeEndian, LittleEndian}; use byteorder::{
use super::test::Bencher; BigEndian, ByteOrder, LittleEndian, NativeEndian,
use super::test::black_box as bb; };
use test::black_box as bb;
use test::Bencher;
const NITER: usize = 100_000; const NITER: usize = 100_000;
@ -43,14 +43,16 @@ macro_rules! bench_num {
}); });
} }
} }
); };
($ty:ident, $max:ident, ($ty:ident, $max:ident,
$read:ident, $write:ident, $size:expr, $data:expr) => ( $read:ident, $write:ident, $size:expr, $data:expr) => {
mod $ty { mod $ty {
use byteorder::{
BigEndian, ByteOrder, LittleEndian, NativeEndian,
};
use std::$ty; use std::$ty;
use byteorder::{ByteOrder, BigEndian, NativeEndian, LittleEndian}; use test::black_box as bb;
use super::test::Bencher; use test::Bencher;
use super::test::black_box as bb;
const NITER: usize = 100_000; const NITER: usize = 100_000;
@ -117,7 +119,7 @@ macro_rules! bench_num {
}); });
} }
} }
); };
} }
bench_num!(u16, MAX, read_u16, write_u16, 2, [1, 2]); bench_num!(u16, MAX, read_u16, write_u16, 2, [1, 2]);
@ -127,8 +129,7 @@ bench_num!(i32, MAX, read_i32, write_i32, 4, [1, 2, 3, 4]);
bench_num!(u64, MAX, read_u64, write_u64, 8, [1, 2, 3, 4, 5, 6, 7, 8]); bench_num!(u64, MAX, read_u64, write_u64, 8, [1, 2, 3, 4, 5, 6, 7, 8]);
bench_num!(i64, MAX, read_i64, write_i64, 8, [1, 2, 3, 4, 5, 6, 7, 8]); bench_num!(i64, MAX, read_i64, write_i64, 8, [1, 2, 3, 4, 5, 6, 7, 8]);
bench_num!(f32, MAX, read_f32, write_f32, 4, [1, 2, 3, 4]); bench_num!(f32, MAX, read_f32, write_f32, 4, [1, 2, 3, 4]);
bench_num!(f64, MAX, read_f64, write_f64, 8, bench_num!(f64, MAX, read_f64, write_f64, 8, [1, 2, 3, 4, 5, 6, 7, 8]);
[1, 2, 3, 4, 5, 6, 7, 8]);
bench_num!(uint_1, read_uint, 1, [1]); bench_num!(uint_1, read_uint, 1, [1]);
bench_num!(uint_2, read_uint, 2, [1, 2]); bench_num!(uint_2, read_uint, 2, [1, 2]);
@ -148,120 +149,115 @@ 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_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]); bench_num!(int_8, read_int, 8, [1, 2, 3, 4, 5, 6, 7, 8]);
#[cfg(byteorder_i128)] bench_num!(
bench_num!(u128, MAX, read_u128, write_u128, u128,
16, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]); MAX,
#[cfg(byteorder_i128)] read_u128,
bench_num!(i128, MAX, read_i128, write_i128, write_u128,
16, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]); 16,
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
);
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)] bench_num!(uint128_1, read_uint128, 1, [1]);
bench_num!(uint128_1, read_uint128, bench_num!(uint128_2, read_uint128, 2, [1, 2]);
1, [1]); bench_num!(uint128_3, read_uint128, 3, [1, 2, 3]);
#[cfg(byteorder_i128)] bench_num!(uint128_4, read_uint128, 4, [1, 2, 3, 4]);
bench_num!(uint128_2, read_uint128, bench_num!(uint128_5, read_uint128, 5, [1, 2, 3, 4, 5]);
2, [1, 2]); bench_num!(uint128_6, read_uint128, 6, [1, 2, 3, 4, 5, 6]);
#[cfg(byteorder_i128)] bench_num!(uint128_7, read_uint128, 7, [1, 2, 3, 4, 5, 6, 7]);
bench_num!(uint128_3, read_uint128, bench_num!(uint128_8, read_uint128, 8, [1, 2, 3, 4, 5, 6, 7, 8]);
3, [1, 2, 3]); bench_num!(uint128_9, read_uint128, 9, [1, 2, 3, 4, 5, 6, 7, 8, 9]);
#[cfg(byteorder_i128)] bench_num!(uint128_10, read_uint128, 10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
bench_num!(uint128_4, read_uint128, bench_num!(uint128_11, read_uint128, 11, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
4, [1, 2, 3, 4]); bench_num!(
#[cfg(byteorder_i128)] uint128_12,
bench_num!(uint128_5, read_uint128, read_uint128,
5, [1, 2, 3, 4, 5]); 12,
#[cfg(byteorder_i128)] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
bench_num!(uint128_6, read_uint128, );
6, [1, 2, 3, 4, 5, 6]); bench_num!(
#[cfg(byteorder_i128)] uint128_13,
bench_num!(uint128_7, read_uint128, read_uint128,
7, [1, 2, 3, 4, 5, 6, 7]); 13,
#[cfg(byteorder_i128)] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
bench_num!(uint128_8, read_uint128, );
8, [1, 2, 3, 4, 5, 6, 7, 8]); bench_num!(
#[cfg(byteorder_i128)] uint128_14,
bench_num!(uint128_9, read_uint128, read_uint128,
9, [1, 2, 3, 4, 5, 6, 7, 8, 9]); 14,
#[cfg(byteorder_i128)] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
bench_num!(uint128_10, read_uint128, );
10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); bench_num!(
#[cfg(byteorder_i128)] uint128_15,
bench_num!(uint128_11, read_uint128, read_uint128,
11, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]); 15,
#[cfg(byteorder_i128)] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
bench_num!(uint128_12, read_uint128, );
12, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]); bench_num!(
#[cfg(byteorder_i128)] uint128_16,
bench_num!(uint128_13, read_uint128, read_uint128,
13, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]); 16,
#[cfg(byteorder_i128)] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
bench_num!(uint128_14, read_uint128, );
14, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]);
#[cfg(byteorder_i128)]
bench_num!(uint128_15, read_uint128,
15, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
#[cfg(byteorder_i128)]
bench_num!(uint128_16, read_uint128,
16, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
#[cfg(byteorder_i128)]
bench_num!(int128_1, read_int128,
1, [1]);
#[cfg(byteorder_i128)]
bench_num!(int128_2, read_int128,
2, [1, 2]);
#[cfg(byteorder_i128)]
bench_num!(int128_3, read_int128,
3, [1, 2, 3]);
#[cfg(byteorder_i128)]
bench_num!(int128_4, read_int128,
4, [1, 2, 3, 4]);
#[cfg(byteorder_i128)]
bench_num!(int128_5, read_int128,
5, [1, 2, 3, 4, 5]);
#[cfg(byteorder_i128)]
bench_num!(int128_6, read_int128,
6, [1, 2, 3, 4, 5, 6]);
#[cfg(byteorder_i128)]
bench_num!(int128_7, read_int128,
7, [1, 2, 3, 4, 5, 6, 7]);
#[cfg(byteorder_i128)]
bench_num!(int128_8, read_int128,
8, [1, 2, 3, 4, 5, 6, 7, 8]);
#[cfg(byteorder_i128)]
bench_num!(int128_9, read_int128,
9, [1, 2, 3, 4, 5, 6, 7, 8, 9]);
#[cfg(byteorder_i128)]
bench_num!(int128_10, read_int128,
10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
#[cfg(byteorder_i128)]
bench_num!(int128_11, read_int128,
11, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
#[cfg(byteorder_i128)]
bench_num!(int128_12, read_int128,
12, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
#[cfg(byteorder_i128)]
bench_num!(int128_13, read_int128,
13, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);
#[cfg(byteorder_i128)]
bench_num!(int128_14, read_int128,
14, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]);
#[cfg(byteorder_i128)]
bench_num!(int128_15, read_int128,
15, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
#[cfg(byteorder_i128)]
bench_num!(int128_16, read_int128,
16, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
bench_num!(int128_1, read_int128, 1, [1]);
bench_num!(int128_2, read_int128, 2, [1, 2]);
bench_num!(int128_3, read_int128, 3, [1, 2, 3]);
bench_num!(int128_4, read_int128, 4, [1, 2, 3, 4]);
bench_num!(int128_5, read_int128, 5, [1, 2, 3, 4, 5]);
bench_num!(int128_6, read_int128, 6, [1, 2, 3, 4, 5, 6]);
bench_num!(int128_7, read_int128, 7, [1, 2, 3, 4, 5, 6, 7]);
bench_num!(int128_8, read_int128, 8, [1, 2, 3, 4, 5, 6, 7, 8]);
bench_num!(int128_9, read_int128, 9, [1, 2, 3, 4, 5, 6, 7, 8, 9]);
bench_num!(int128_10, read_int128, 10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
bench_num!(int128_11, read_int128, 11, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
bench_num!(
int128_12,
read_int128,
12,
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
);
bench_num!(
int128_13,
read_int128,
13,
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
);
bench_num!(
int128_14,
read_int128,
14,
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
);
bench_num!(
int128_15,
read_int128,
15,
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
);
bench_num!(
int128_16,
read_int128,
16,
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
);
macro_rules! bench_slice { macro_rules! bench_slice {
($name:ident, $numty:ty, $read:ident, $write:ident) => { ($name:ident, $numty:ty, $read:ident, $write:ident) => {
mod $name { mod $name {
use std::mem::size_of; use std::mem::size_of;
use byteorder::{ByteOrder, BigEndian, LittleEndian}; use byteorder::{BigEndian, ByteOrder, LittleEndian};
use rand::{self, Rng};
use rand::distributions; use rand::distributions;
use rand::{self, Rng};
use test::Bencher; use test::Bencher;
#[bench] #[bench]
@ -322,7 +318,7 @@ macro_rules! bench_slice {
}); });
} }
} }
} };
} }
bench_slice!(slice_u64, u64, read_u64_into, write_u64_into); bench_slice!(slice_u64, u64, read_u64_into, write_u64_into);

View File

@ -1,7 +1,9 @@
use std::io::{self, Result}; use std::{
use std::slice; io::{self, Result},
slice,
};
use ByteOrder; use crate::ByteOrder;
/// Extends [`Read`] with methods for reading numbers. (For `std::io`.) /// Extends [`Read`] with methods for reading numbers. (For `std::io`.)
/// ///
@ -52,7 +54,7 @@ pub trait ReadBytesExt: io::Read {
#[inline] #[inline]
fn read_u8(&mut self) -> Result<u8> { fn read_u8(&mut self) -> Result<u8> {
let mut buf = [0; 1]; let mut buf = [0; 1];
try!(self.read_exact(&mut buf)); self.read_exact(&mut buf)?;
Ok(buf[0]) Ok(buf[0])
} }
@ -82,7 +84,7 @@ pub trait ReadBytesExt: io::Read {
#[inline] #[inline]
fn read_i8(&mut self) -> Result<i8> { fn read_i8(&mut self) -> Result<i8> {
let mut buf = [0; 1]; let mut buf = [0; 1];
try!(self.read_exact(&mut buf)); self.read_exact(&mut buf)?;
Ok(buf[0] as i8) Ok(buf[0] as i8)
} }
@ -109,7 +111,7 @@ pub trait ReadBytesExt: io::Read {
#[inline] #[inline]
fn read_u16<T: ByteOrder>(&mut self) -> Result<u16> { fn read_u16<T: ByteOrder>(&mut self) -> Result<u16> {
let mut buf = [0; 2]; let mut buf = [0; 2];
try!(self.read_exact(&mut buf)); self.read_exact(&mut buf)?;
Ok(T::read_u16(&buf)) Ok(T::read_u16(&buf))
} }
@ -136,7 +138,7 @@ pub trait ReadBytesExt: io::Read {
#[inline] #[inline]
fn read_i16<T: ByteOrder>(&mut self) -> Result<i16> { fn read_i16<T: ByteOrder>(&mut self) -> Result<i16> {
let mut buf = [0; 2]; let mut buf = [0; 2];
try!(self.read_exact(&mut buf)); self.read_exact(&mut buf)?;
Ok(T::read_i16(&buf)) Ok(T::read_i16(&buf))
} }
@ -162,7 +164,7 @@ pub trait ReadBytesExt: io::Read {
#[inline] #[inline]
fn read_u24<T: ByteOrder>(&mut self) -> Result<u32> { fn read_u24<T: ByteOrder>(&mut self) -> Result<u32> {
let mut buf = [0; 3]; let mut buf = [0; 3];
try!(self.read_exact(&mut buf)); self.read_exact(&mut buf)?;
Ok(T::read_u24(&buf)) Ok(T::read_u24(&buf))
} }
@ -188,7 +190,7 @@ pub trait ReadBytesExt: io::Read {
#[inline] #[inline]
fn read_i24<T: ByteOrder>(&mut self) -> Result<i32> { fn read_i24<T: ByteOrder>(&mut self) -> Result<i32> {
let mut buf = [0; 3]; let mut buf = [0; 3];
try!(self.read_exact(&mut buf)); self.read_exact(&mut buf)?;
Ok(T::read_i24(&buf)) Ok(T::read_i24(&buf))
} }
@ -214,7 +216,7 @@ pub trait ReadBytesExt: io::Read {
#[inline] #[inline]
fn read_u32<T: ByteOrder>(&mut self) -> Result<u32> { fn read_u32<T: ByteOrder>(&mut self) -> Result<u32> {
let mut buf = [0; 4]; let mut buf = [0; 4];
try!(self.read_exact(&mut buf)); self.read_exact(&mut buf)?;
Ok(T::read_u32(&buf)) Ok(T::read_u32(&buf))
} }
@ -240,7 +242,7 @@ pub trait ReadBytesExt: io::Read {
#[inline] #[inline]
fn read_i32<T: ByteOrder>(&mut self) -> Result<i32> { fn read_i32<T: ByteOrder>(&mut self) -> Result<i32> {
let mut buf = [0; 4]; let mut buf = [0; 4];
try!(self.read_exact(&mut buf)); self.read_exact(&mut buf)?;
Ok(T::read_i32(&buf)) Ok(T::read_i32(&buf))
} }
@ -266,7 +268,7 @@ pub trait ReadBytesExt: io::Read {
#[inline] #[inline]
fn read_u48<T: ByteOrder>(&mut self) -> Result<u64> { fn read_u48<T: ByteOrder>(&mut self) -> Result<u64> {
let mut buf = [0; 6]; let mut buf = [0; 6];
try!(self.read_exact(&mut buf)); self.read_exact(&mut buf)?;
Ok(T::read_u48(&buf)) Ok(T::read_u48(&buf))
} }
@ -292,7 +294,7 @@ pub trait ReadBytesExt: io::Read {
#[inline] #[inline]
fn read_i48<T: ByteOrder>(&mut self) -> Result<i64> { fn read_i48<T: ByteOrder>(&mut self) -> Result<i64> {
let mut buf = [0; 6]; let mut buf = [0; 6];
try!(self.read_exact(&mut buf)); self.read_exact(&mut buf)?;
Ok(T::read_i48(&buf)) Ok(T::read_i48(&buf))
} }
@ -318,7 +320,7 @@ pub trait ReadBytesExt: io::Read {
#[inline] #[inline]
fn read_u64<T: ByteOrder>(&mut self) -> Result<u64> { fn read_u64<T: ByteOrder>(&mut self) -> Result<u64> {
let mut buf = [0; 8]; let mut buf = [0; 8];
try!(self.read_exact(&mut buf)); self.read_exact(&mut buf)?;
Ok(T::read_u64(&buf)) Ok(T::read_u64(&buf))
} }
@ -344,7 +346,7 @@ pub trait ReadBytesExt: io::Read {
#[inline] #[inline]
fn read_i64<T: ByteOrder>(&mut self) -> Result<i64> { fn read_i64<T: ByteOrder>(&mut self) -> Result<i64> {
let mut buf = [0; 8]; let mut buf = [0; 8];
try!(self.read_exact(&mut buf)); self.read_exact(&mut buf)?;
Ok(T::read_i64(&buf)) Ok(T::read_i64(&buf))
} }
@ -370,11 +372,10 @@ pub trait ReadBytesExt: io::Read {
/// ]); /// ]);
/// assert_eq!(16947640962301618749969007319746179, rdr.read_u128::<BigEndian>().unwrap()); /// assert_eq!(16947640962301618749969007319746179, rdr.read_u128::<BigEndian>().unwrap());
/// ``` /// ```
#[cfg(byteorder_i128)]
#[inline] #[inline]
fn read_u128<T: ByteOrder>(&mut self) -> Result<u128> { fn read_u128<T: ByteOrder>(&mut self) -> Result<u128> {
let mut buf = [0; 16]; let mut buf = [0; 16];
try!(self.read_exact(&mut buf)); self.read_exact(&mut buf)?;
Ok(T::read_u128(&buf)) Ok(T::read_u128(&buf))
} }
@ -397,11 +398,10 @@ pub trait ReadBytesExt: io::Read {
/// let mut rdr = Cursor::new(vec![0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); /// 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()); /// assert_eq!(i128::min_value(), rdr.read_i128::<BigEndian>().unwrap());
/// ``` /// ```
#[cfg(byteorder_i128)]
#[inline] #[inline]
fn read_i128<T: ByteOrder>(&mut self) -> Result<i128> { fn read_i128<T: ByteOrder>(&mut self) -> Result<i128> {
let mut buf = [0; 16]; let mut buf = [0; 16];
try!(self.read_exact(&mut buf)); self.read_exact(&mut buf)?;
Ok(T::read_i128(&buf)) Ok(T::read_i128(&buf))
} }
@ -426,7 +426,7 @@ pub trait ReadBytesExt: io::Read {
#[inline] #[inline]
fn read_uint<T: ByteOrder>(&mut self, nbytes: usize) -> Result<u64> { fn read_uint<T: ByteOrder>(&mut self, nbytes: usize) -> Result<u64> {
let mut buf = [0; 8]; let mut buf = [0; 8];
try!(self.read_exact(&mut buf[..nbytes])); self.read_exact(&mut buf[..nbytes])?;
Ok(T::read_uint(&buf[..nbytes], nbytes)) Ok(T::read_uint(&buf[..nbytes], nbytes))
} }
@ -451,25 +451,23 @@ pub trait ReadBytesExt: io::Read {
#[inline] #[inline]
fn read_int<T: ByteOrder>(&mut self, nbytes: usize) -> Result<i64> { fn read_int<T: ByteOrder>(&mut self, nbytes: usize) -> Result<i64> {
let mut buf = [0; 8]; let mut buf = [0; 8];
try!(self.read_exact(&mut buf[..nbytes])); self.read_exact(&mut buf[..nbytes])?;
Ok(T::read_int(&buf[..nbytes], nbytes)) Ok(T::read_int(&buf[..nbytes], nbytes))
} }
/// Reads an unsigned n-bytes integer from the underlying reader. /// Reads an unsigned n-bytes integer from the underlying reader.
#[cfg(byteorder_i128)]
#[inline] #[inline]
fn read_uint128<T: ByteOrder>(&mut self, nbytes: usize) -> Result<u128> { fn read_uint128<T: ByteOrder>(&mut self, nbytes: usize) -> Result<u128> {
let mut buf = [0; 16]; let mut buf = [0; 16];
try!(self.read_exact(&mut buf[..nbytes])); self.read_exact(&mut buf[..nbytes])?;
Ok(T::read_uint128(&buf[..nbytes], nbytes)) Ok(T::read_uint128(&buf[..nbytes], nbytes))
} }
/// Reads a signed n-bytes integer from the underlying reader. /// Reads a signed n-bytes integer from the underlying reader.
#[cfg(byteorder_i128)]
#[inline] #[inline]
fn read_int128<T: ByteOrder>(&mut self, nbytes: usize) -> Result<i128> { fn read_int128<T: ByteOrder>(&mut self, nbytes: usize) -> Result<i128> {
let mut buf = [0; 16]; let mut buf = [0; 16];
try!(self.read_exact(&mut buf[..nbytes])); self.read_exact(&mut buf[..nbytes])?;
Ok(T::read_int128(&buf[..nbytes], nbytes)) Ok(T::read_int128(&buf[..nbytes], nbytes))
} }
@ -500,7 +498,7 @@ pub trait ReadBytesExt: io::Read {
#[inline] #[inline]
fn read_f32<T: ByteOrder>(&mut self) -> Result<f32> { fn read_f32<T: ByteOrder>(&mut self) -> Result<f32> {
let mut buf = [0; 4]; let mut buf = [0; 4];
try!(self.read_exact(&mut buf)); self.read_exact(&mut buf)?;
Ok(T::read_f32(&buf)) Ok(T::read_f32(&buf))
} }
@ -531,7 +529,7 @@ pub trait ReadBytesExt: io::Read {
#[inline] #[inline]
fn read_f64<T: ByteOrder>(&mut self) -> Result<f64> { fn read_f64<T: ByteOrder>(&mut self) -> Result<f64> {
let mut buf = [0; 8]; let mut buf = [0; 8];
try!(self.read_exact(&mut buf)); self.read_exact(&mut buf)?;
Ok(T::read_f64(&buf)) Ok(T::read_f64(&buf))
} }
@ -564,7 +562,7 @@ pub trait ReadBytesExt: io::Read {
fn read_u16_into<T: ByteOrder>(&mut self, dst: &mut [u16]) -> Result<()> { fn read_u16_into<T: ByteOrder>(&mut self, dst: &mut [u16]) -> Result<()> {
{ {
let buf = unsafe { slice_to_u8_mut(dst) }; let buf = unsafe { slice_to_u8_mut(dst) };
try!(self.read_exact(buf)); self.read_exact(buf)?;
} }
T::from_slice_u16(dst); T::from_slice_u16(dst);
Ok(()) Ok(())
@ -599,7 +597,7 @@ pub trait ReadBytesExt: io::Read {
fn read_u32_into<T: ByteOrder>(&mut self, dst: &mut [u32]) -> Result<()> { fn read_u32_into<T: ByteOrder>(&mut self, dst: &mut [u32]) -> Result<()> {
{ {
let buf = unsafe { slice_to_u8_mut(dst) }; let buf = unsafe { slice_to_u8_mut(dst) };
try!(self.read_exact(buf)); self.read_exact(buf)?;
} }
T::from_slice_u32(dst); T::from_slice_u32(dst);
Ok(()) Ok(())
@ -637,7 +635,7 @@ pub trait ReadBytesExt: io::Read {
fn read_u64_into<T: ByteOrder>(&mut self, dst: &mut [u64]) -> Result<()> { fn read_u64_into<T: ByteOrder>(&mut self, dst: &mut [u64]) -> Result<()> {
{ {
let buf = unsafe { slice_to_u8_mut(dst) }; let buf = unsafe { slice_to_u8_mut(dst) };
try!(self.read_exact(buf)); self.read_exact(buf)?;
} }
T::from_slice_u64(dst); T::from_slice_u64(dst);
Ok(()) Ok(())
@ -671,7 +669,6 @@ pub trait ReadBytesExt: io::Read {
/// rdr.read_u128_into::<BigEndian>(&mut dst).unwrap(); /// rdr.read_u128_into::<BigEndian>(&mut dst).unwrap();
/// assert_eq!([517, 768], dst); /// assert_eq!([517, 768], dst);
/// ``` /// ```
#[cfg(byteorder_i128)]
#[inline] #[inline]
fn read_u128_into<T: ByteOrder>( fn read_u128_into<T: ByteOrder>(
&mut self, &mut self,
@ -679,7 +676,7 @@ pub trait ReadBytesExt: io::Read {
) -> Result<()> { ) -> Result<()> {
{ {
let buf = unsafe { slice_to_u8_mut(dst) }; let buf = unsafe { slice_to_u8_mut(dst) };
try!(self.read_exact(buf)); self.read_exact(buf)?;
} }
T::from_slice_u128(dst); T::from_slice_u128(dst);
Ok(()) Ok(())
@ -750,7 +747,7 @@ pub trait ReadBytesExt: io::Read {
fn read_i16_into<T: ByteOrder>(&mut self, dst: &mut [i16]) -> Result<()> { fn read_i16_into<T: ByteOrder>(&mut self, dst: &mut [i16]) -> Result<()> {
{ {
let buf = unsafe { slice_to_u8_mut(dst) }; let buf = unsafe { slice_to_u8_mut(dst) };
try!(self.read_exact(buf)); self.read_exact(buf)?;
} }
T::from_slice_i16(dst); T::from_slice_i16(dst);
Ok(()) Ok(())
@ -785,7 +782,7 @@ pub trait ReadBytesExt: io::Read {
fn read_i32_into<T: ByteOrder>(&mut self, dst: &mut [i32]) -> Result<()> { fn read_i32_into<T: ByteOrder>(&mut self, dst: &mut [i32]) -> Result<()> {
{ {
let buf = unsafe { slice_to_u8_mut(dst) }; let buf = unsafe { slice_to_u8_mut(dst) };
try!(self.read_exact(buf)); self.read_exact(buf)?;
} }
T::from_slice_i32(dst); T::from_slice_i32(dst);
Ok(()) Ok(())
@ -823,7 +820,7 @@ pub trait ReadBytesExt: io::Read {
fn read_i64_into<T: ByteOrder>(&mut self, dst: &mut [i64]) -> Result<()> { fn read_i64_into<T: ByteOrder>(&mut self, dst: &mut [i64]) -> Result<()> {
{ {
let buf = unsafe { slice_to_u8_mut(dst) }; let buf = unsafe { slice_to_u8_mut(dst) };
try!(self.read_exact(buf)); self.read_exact(buf)?;
} }
T::from_slice_i64(dst); T::from_slice_i64(dst);
Ok(()) Ok(())
@ -857,7 +854,6 @@ pub trait ReadBytesExt: io::Read {
/// rdr.read_i128_into::<BigEndian>(&mut dst).unwrap(); /// rdr.read_i128_into::<BigEndian>(&mut dst).unwrap();
/// assert_eq!([517, 768], dst); /// assert_eq!([517, 768], dst);
/// ``` /// ```
#[cfg(byteorder_i128)]
#[inline] #[inline]
fn read_i128_into<T: ByteOrder>( fn read_i128_into<T: ByteOrder>(
&mut self, &mut self,
@ -865,7 +861,7 @@ pub trait ReadBytesExt: io::Read {
) -> Result<()> { ) -> Result<()> {
{ {
let buf = unsafe { slice_to_u8_mut(dst) }; let buf = unsafe { slice_to_u8_mut(dst) };
try!(self.read_exact(buf)); self.read_exact(buf)?;
} }
T::from_slice_i128(dst); T::from_slice_i128(dst);
Ok(()) Ok(())
@ -903,13 +899,10 @@ pub trait ReadBytesExt: io::Read {
/// assert_eq!([f32::consts::PI, 1.0], dst); /// assert_eq!([f32::consts::PI, 1.0], dst);
/// ``` /// ```
#[inline] #[inline]
fn read_f32_into<T: ByteOrder>( fn read_f32_into<T: ByteOrder>(&mut self, dst: &mut [f32]) -> Result<()> {
&mut self,
dst: &mut [f32],
) -> Result<()> {
{ {
let buf = unsafe { slice_to_u8_mut(dst) }; let buf = unsafe { slice_to_u8_mut(dst) };
try!(self.read_exact(buf)); self.read_exact(buf)?;
} }
T::from_slice_f32(dst); T::from_slice_f32(dst);
Ok(()) Ok(())
@ -951,7 +944,7 @@ pub trait ReadBytesExt: io::Read {
/// assert_eq!([f32::consts::PI, 1.0], dst); /// assert_eq!([f32::consts::PI, 1.0], dst);
/// ``` /// ```
#[inline] #[inline]
#[deprecated(since="1.2.0", note="please use `read_f32_into` instead")] #[deprecated(since = "1.2.0", note = "please use `read_f32_into` instead")]
fn read_f32_into_unchecked<T: ByteOrder>( fn read_f32_into_unchecked<T: ByteOrder>(
&mut self, &mut self,
dst: &mut [f32], dst: &mut [f32],
@ -991,13 +984,10 @@ pub trait ReadBytesExt: io::Read {
/// assert_eq!([f64::consts::PI, 1.0], dst); /// assert_eq!([f64::consts::PI, 1.0], dst);
/// ``` /// ```
#[inline] #[inline]
fn read_f64_into<T: ByteOrder>( fn read_f64_into<T: ByteOrder>(&mut self, dst: &mut [f64]) -> Result<()> {
&mut self,
dst: &mut [f64],
) -> Result<()> {
{ {
let buf = unsafe { slice_to_u8_mut(dst) }; let buf = unsafe { slice_to_u8_mut(dst) };
try!(self.read_exact(buf)); self.read_exact(buf)?;
} }
T::from_slice_f64(dst); T::from_slice_f64(dst);
Ok(()) Ok(())
@ -1045,7 +1035,7 @@ pub trait ReadBytesExt: io::Read {
/// assert_eq!([f64::consts::PI, 1.0], dst); /// assert_eq!([f64::consts::PI, 1.0], dst);
/// ``` /// ```
#[inline] #[inline]
#[deprecated(since="1.2.0", note="please use `read_f64_into` instead")] #[deprecated(since = "1.2.0", note = "please use `read_f64_into` instead")]
fn read_f64_into_unchecked<T: ByteOrder>( fn read_f64_into_unchecked<T: ByteOrder>(
&mut self, &mut self,
dst: &mut [f64], dst: &mut [f64],
@ -1408,7 +1398,6 @@ pub trait WriteBytesExt: io::Write {
} }
/// Writes an unsigned 128 bit integer to the underlying writer. /// Writes an unsigned 128 bit integer to the underlying writer.
#[cfg(byteorder_i128)]
#[inline] #[inline]
fn write_u128<T: ByteOrder>(&mut self, n: u128) -> Result<()> { fn write_u128<T: ByteOrder>(&mut self, n: u128) -> Result<()> {
let mut buf = [0; 16]; let mut buf = [0; 16];
@ -1417,7 +1406,6 @@ pub trait WriteBytesExt: io::Write {
} }
/// Writes a signed 128 bit integer to the underlying writer. /// Writes a signed 128 bit integer to the underlying writer.
#[cfg(byteorder_i128)]
#[inline] #[inline]
fn write_i128<T: ByteOrder>(&mut self, n: i128) -> Result<()> { fn write_i128<T: ByteOrder>(&mut self, n: i128) -> Result<()> {
let mut buf = [0; 16]; let mut buf = [0; 16];
@ -1501,7 +1489,6 @@ pub trait WriteBytesExt: io::Write {
/// ///
/// If the given integer is not representable in the given number of bytes, /// If the given integer is not representable in the given number of bytes,
/// this method panics. If `nbytes > 16`, this method panics. /// this method panics. If `nbytes > 16`, this method panics.
#[cfg(byteorder_i128)]
#[inline] #[inline]
fn write_uint128<T: ByteOrder>( fn write_uint128<T: ByteOrder>(
&mut self, &mut self,
@ -1517,7 +1504,6 @@ pub trait WriteBytesExt: io::Write {
/// ///
/// If the given integer is not representable in the given number of bytes, /// If the given integer is not representable in the given number of bytes,
/// this method panics. If `nbytes > 16`, this method panics. /// this method panics. If `nbytes > 16`, this method panics.
#[cfg(byteorder_i128)]
#[inline] #[inline]
fn write_int128<T: ByteOrder>( fn write_int128<T: ByteOrder>(
&mut self, &mut self,
@ -1596,7 +1582,8 @@ impl<W: io::Write + ?Sized> WriteBytesExt for W {}
/// representation. /// representation.
/// ///
/// This function is wildly unsafe because it permits arbitrary modification of /// This function is wildly unsafe because it permits arbitrary modification of
/// the binary representation of any `Copy` type. Use with care. /// the binary representation of any `Copy` type. Use with care. It's intended
/// to be called only where `T` is a numeric type.
unsafe fn slice_to_u8_mut<T: Copy>(slice: &mut [T]) -> &mut [u8] { unsafe fn slice_to_u8_mut<T: Copy>(slice: &mut [T]) -> &mut [u8] {
use std::mem::size_of; use std::mem::size_of;

View File

@ -49,7 +49,7 @@ rust_library(
version = "0.6.5", version = "0.6.5",
# buildifier: leave-alone # buildifier: leave-alone
deps = [ deps = [
"//third_party/cargo/vendor/log-0.4.11:log", "//third_party/cargo/vendor/log-0.4.14:log",
"//third_party/cargo/vendor/nix-0.18.0:nix", "//third_party/cargo/vendor/nix-0.18.0:nix",
], ],
) )

View File

@ -1 +1 @@
{"files":{"Cargo.lock":"e7f53256b803536940678cee654d7e2318882aa7cd163acbe8be0caa72087b65","Cargo.toml":"ecb8c7e0fccad7f2d42412b5a227bf51f8e53b9fd526e036fc1b8f41c5024a68","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"3055cc70608f92dab0dcd10338264357ef891f01d02219fa64457b4aa016936b","src/bin/gcc-shim.rs":"b77907875029494b6288841c3aed2e4939ed40708c7f597fca5c9e2570490ca6","src/com.rs":"bcdaf1c28b71e6ef889c6b08d1ce9d7c0761344a677f523bc4c3cd297957f804","src/lib.rs":"e1a05e4a092b903dbbc45612ee924c038585d5f680233792afc551000eb6aac5","src/registry.rs":"3cc1b5a50879fa751572878ae1d0afbfc960c11665258492754b2c8bccb0ff5d","src/setup_config.rs":"7014103587d3382eac599cb76f016e2609b8140970861b2237982d1db24af265","src/winapi.rs":"ea8b7edbb9ff87957254f465c2334e714c5d6b3b19a8d757c48ea7ca0881c50c","src/windows_registry.rs":"52afe8554f577c87841c48ddee3ba7ffe70a00129e1d6eeb2ec0efb3d2b9aa11","tests/cc_env.rs":"e02b3b0824ad039b47e4462c5ef6dbe6c824c28e7953af94a0f28f7b5158042e","tests/cflags.rs":"57f06eb5ce1557e5b4a032d0c4673e18fbe6f8d26c1deb153126e368b96b41b3","tests/cxxflags.rs":"c2c6c6d8a0d7146616fa1caed26876ee7bc9fcfffd525eb4743593cade5f3371","tests/support/mod.rs":"16274867f23871e9b07614eda4c7344da13d1751fed63d4f633857e40be86394","tests/test.rs":"65c073e0e2cf4aa0433066102788e9f57442719e6f32f5ad5248aa7132bb4597"},"package":"4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"} {"files":{"Cargo.lock":"45b8780aa6c52bb154732a5b8a11c5723dd8328e7f0d01493a2bcd07fdba96c9","Cargo.toml":"3b622b3ea56086289d3b4ddc13a7d11c94c3ff0c729b37aa18a2ddca70201929","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"9916275542d23bfa0815b1f48d4546e514739fadc79775500de6a81cf17aac09","src/bin/gcc-shim.rs":"b77907875029494b6288841c3aed2e4939ed40708c7f597fca5c9e2570490ca6","src/com.rs":"bcdaf1c28b71e6ef889c6b08d1ce9d7c0761344a677f523bc4c3cd297957f804","src/lib.rs":"43bfa26d2bc699d56e063f5608aadb0cc20c297612e1f02cc408e0221923ac88","src/registry.rs":"3cc1b5a50879fa751572878ae1d0afbfc960c11665258492754b2c8bccb0ff5d","src/setup_config.rs":"7014103587d3382eac599cb76f016e2609b8140970861b2237982d1db24af265","src/winapi.rs":"ea8b7edbb9ff87957254f465c2334e714c5d6b3b19a8d757c48ea7ca0881c50c","src/windows_registry.rs":"52afe8554f577c87841c48ddee3ba7ffe70a00129e1d6eeb2ec0efb3d2b9aa11","tests/cc_env.rs":"e02b3b0824ad039b47e4462c5ef6dbe6c824c28e7953af94a0f28f7b5158042e","tests/cflags.rs":"57f06eb5ce1557e5b4a032d0c4673e18fbe6f8d26c1deb153126e368b96b41b3","tests/cxxflags.rs":"c2c6c6d8a0d7146616fa1caed26876ee7bc9fcfffd525eb4743593cade5f3371","tests/support/mod.rs":"16274867f23871e9b07614eda4c7344da13d1751fed63d4f633857e40be86394","tests/test.rs":"65c073e0e2cf4aa0433066102788e9f57442719e6f32f5ad5248aa7132bb4597"},"package":"e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"}

View File

@ -47,7 +47,7 @@ rust_binary(
"cargo-raze", "cargo-raze",
"manual", "manual",
], ],
version = "1.0.66", version = "1.0.67",
# buildifier: leave-alone # buildifier: leave-alone
deps = [ deps = [
# Binaries get an implicit dependency on their crate's lib # Binaries get an implicit dependency on their crate's lib
@ -71,7 +71,7 @@ rust_library(
"cargo-raze", "cargo-raze",
"manual", "manual",
], ],
version = "1.0.66", version = "1.0.67",
# buildifier: leave-alone # buildifier: leave-alone
deps = [ deps = [
], ],

View File

@ -2,7 +2,7 @@
# It is not intended for manual editing. # It is not intended for manual editing.
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.66" version = "1.0.67"
dependencies = [ dependencies = [
"jobserver", "jobserver",
"tempfile", "tempfile",

View File

@ -13,7 +13,7 @@
[package] [package]
edition = "2018" edition = "2018"
name = "cc" name = "cc"
version = "1.0.66" version = "1.0.67"
authors = ["Alex Crichton <alex@alexcrichton.com>"] authors = ["Alex Crichton <alex@alexcrichton.com>"]
exclude = ["/.github", "/.travis.yml", "/appveyor.yml"] exclude = ["/.github", "/.travis.yml", "/appveyor.yml"]
description = "A build-time dependency for Cargo build scripts to assist in invoking the native\nC compiler to compile native C code into a static archive to be linked into Rust\ncode.\n" description = "A build-time dependency for Cargo build scripts to assist in invoking the native\nC compiler to compile native C code into a static archive to be linked into Rust\ncode.\n"

View File

@ -101,7 +101,7 @@ functions with hard requirements on some variables supplied by [cargo's
build-script driver][cargo] that it has the `TARGET`, `OUT_DIR`, `OPT_LEVEL`, build-script driver][cargo] that it has the `TARGET`, `OUT_DIR`, `OPT_LEVEL`,
and `HOST` variables. and `HOST` variables.
[cargo]: http://doc.crates.io/build-script.html#inputs-to-the-build-script [cargo]: https://doc.rust-lang.org/cargo/reference/build-scripts.html#inputs-to-the-build-script
## Optional features ## Optional features
@ -128,7 +128,7 @@ is being run. This crate does not ship a C compiler with it. The compiler
required varies per platform, but there are three broad categories: required varies per platform, but there are three broad categories:
* Unix platforms require `cc` to be the C compiler. This can be found by * Unix platforms require `cc` to be the C compiler. This can be found by
installing cc/clang on Linux distributions and Xcode on OSX, for example. installing cc/clang on Linux distributions and Xcode on macOS, for example.
* Windows platforms targeting MSVC (e.g. your target triple ends in `-msvc`) * Windows platforms targeting MSVC (e.g. your target triple ends in `-msvc`)
require `cl.exe` to be available and in `PATH`. This is typically found in require `cl.exe` to be available and in `PATH`. This is typically found in
standard Visual Studio installations and the `PATH` can be set up by running standard Visual Studio installations and the `PATH` can be set up by running
@ -138,12 +138,12 @@ required varies per platform, but there are three broad categories:
[MinGW-w64](http://mingw-w64.org) distribution, which is using the [MinGW-w64](http://mingw-w64.org) distribution, which is using the
[Win-builds](http://win-builds.org) installation system. [Win-builds](http://win-builds.org) installation system.
You may also acquire it via You may also acquire it via
[MSYS2](http://msys2.github.io), as explained [here][msys2-help]. Make sure [MSYS2](https://www.msys2.org/), as explained [here][msys2-help]. Make sure
to install the appropriate architecture corresponding to your installation of to install the appropriate architecture corresponding to your installation of
rustc. GCC from older [MinGW](http://www.mingw.org) project is compatible rustc. GCC from older [MinGW](http://www.mingw.org) project is compatible
only with 32-bit rust compiler. only with 32-bit rust compiler.
[msys2-help]: http://github.com/rust-lang/rust#building-on-windows [msys2-help]: https://github.com/rust-lang/rust#building-on-windows
## C++ support ## C++ support
@ -161,7 +161,7 @@ fn main() {
For C++ libraries, the `CXX` and `CXXFLAGS` environment variables are used instead of `CC` and `CFLAGS`. For C++ libraries, the `CXX` and `CXXFLAGS` environment variables are used instead of `CC` and `CFLAGS`.
The C++ standard library may be linked to the crate target. By default it's `libc++` for OS X, FreeBSD, and OpenBSD, `libc++_shared` for Android, nothing for MSVC, and `libstdc++` for anything else. It can be changed in one of two ways: The C++ standard library may be linked to the crate target. By default it's `libc++` for macOS, FreeBSD, and OpenBSD, `libc++_shared` for Android, nothing for MSVC, and `libstdc++` for anything else. It can be changed in one of two ways:
1. by using the `cpp_link_stdlib` method on `Build`: 1. by using the `cpp_link_stdlib` method on `Build`:
```rust,no-run ```rust,no-run
@ -209,9 +209,9 @@ fn main() {
This project is licensed under either of This project is licensed under either of
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
http://www.apache.org/licenses/LICENSE-2.0) https://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or * MIT license ([LICENSE-MIT](LICENSE-MIT) or
http://opensource.org/licenses/MIT) https://opensource.org/licenses/MIT)
at your option. at your option.

View File

@ -1414,7 +1414,7 @@ impl Build {
cmd.push_opt_unless_duplicate("-DANDROID".into()); cmd.push_opt_unless_duplicate("-DANDROID".into());
} }
if !target.contains("-ios") { if !target.contains("apple-ios") {
cmd.push_cc_arg("-ffunction-sections".into()); cmd.push_cc_arg("-ffunction-sections".into());
cmd.push_cc_arg("-fdata-sections".into()); cmd.push_cc_arg("-fdata-sections".into());
} }
@ -1468,6 +1468,20 @@ impl Build {
cmd.args cmd.args
.push(format!("--target={}-apple-{}-macabi", arch, ios).into()); .push(format!("--target={}-apple-{}-macabi", arch, ios).into());
} }
} else if target.contains("ios-sim") {
if let Some(arch) =
map_darwin_target_from_rust_to_compiler_architecture(target)
{
let deployment_target = env::var("IPHONEOS_DEPLOYMENT_TARGET")
.unwrap_or_else(|_| "7.0".into());
cmd.args.push(
format!(
"--target={}-apple-ios{}-simulator",
arch, deployment_target
)
.into(),
);
}
} else { } else {
cmd.args.push(format!("--target={}", target).into()); cmd.args.push(format!("--target={}", target).into());
} }
@ -1600,7 +1614,7 @@ impl Build {
cmd.args.push("-march=i686".into()); cmd.args.push("-march=i686".into());
} }
// Looks like `musl-gcc` makes is hard for `-m32` to make its way // Looks like `musl-gcc` makes it hard for `-m32` to make its way
// all the way to the linker, so we need to actually instruct the // all the way to the linker, so we need to actually instruct the
// linker that we're generating 32-bit executables as well. This'll // linker that we're generating 32-bit executables as well. This'll
// typically only be used for build scripts which transitively use // typically only be used for build scripts which transitively use
@ -1677,14 +1691,17 @@ impl Build {
let mut parts = target.split('-'); let mut parts = target.split('-');
if let Some(arch) = parts.next() { if let Some(arch) = parts.next() {
let arch = &arch[5..]; let arch = &arch[5..];
cmd.args.push(("-march=rv".to_owned() + arch).into());
if target.contains("linux") && arch.starts_with("64") { if target.contains("linux") && arch.starts_with("64") {
cmd.args.push(("-march=rv64gc").into());
cmd.args.push("-mabi=lp64d".into()); cmd.args.push("-mabi=lp64d".into());
} else if target.contains("linux") && arch.starts_with("32") { } else if target.contains("linux") && arch.starts_with("32") {
cmd.args.push(("-march=rv32gc").into());
cmd.args.push("-mabi=ilp32d".into()); cmd.args.push("-mabi=ilp32d".into());
} else if arch.starts_with("64") { } else if arch.starts_with("64") {
cmd.args.push(("-march=rv".to_owned() + arch).into());
cmd.args.push("-mabi=lp64".into()); cmd.args.push("-mabi=lp64".into());
} else { } else {
cmd.args.push(("-march=rv".to_owned() + arch).into());
cmd.args.push("-mabi=ilp32".into()); cmd.args.push("-mabi=ilp32".into());
} }
cmd.args.push("-mcmodel=medany".into()); cmd.args.push("-mcmodel=medany".into());
@ -1693,9 +1710,7 @@ impl Build {
} }
} }
if target.contains("-ios") { if target.contains("apple-ios") {
// FIXME: potential bug. iOS is always compiled with Clang, but Gcc compiler may be
// detected instead.
self.ios_flags(cmd)?; self.ios_flags(cmd)?;
} }
@ -2044,6 +2059,8 @@ impl Build {
} else { } else {
format!("{}.exe", gnu) format!("{}.exe", gnu)
} }
} else if target.contains("apple-ios") {
clang.to_string()
} else if target.contains("android") { } else if target.contains("android") {
autodetect_android_compiler(&target, &host, gnu, clang) autodetect_android_compiler(&target, &host, gnu, clang)
} else if target.contains("cloudabi") { } else if target.contains("cloudabi") {
@ -2420,6 +2437,9 @@ impl Build {
"riscv-none-embed", "riscv-none-embed",
]), ]),
"riscv64gc-unknown-linux-gnu" => Some("riscv64-linux-gnu"), "riscv64gc-unknown-linux-gnu" => Some("riscv64-linux-gnu"),
"riscv32gc-unknown-linux-gnu" => Some("riscv32-linux-gnu"),
"riscv64gc-unknown-linux-musl" => Some("riscv64-linux-musl"),
"riscv32gc-unknown-linux-musl" => Some("riscv32-linux-musl"),
"s390x-unknown-linux-gnu" => Some("s390x-linux-gnu"), "s390x-unknown-linux-gnu" => Some("s390x-linux-gnu"),
"sparc-unknown-linux-gnu" => Some("sparc-linux-gnu"), "sparc-unknown-linux-gnu" => Some("sparc-linux-gnu"),
"sparc64-unknown-linux-gnu" => Some("sparc64-linux-gnu"), "sparc64-unknown-linux-gnu" => Some("sparc64-linux-gnu"),
@ -2643,11 +2663,7 @@ impl Tool {
let family = if let Some(fname) = path.file_name().and_then(|p| p.to_str()) { let family = if let Some(fname) = path.file_name().and_then(|p| p.to_str()) {
if fname.contains("clang-cl") { if fname.contains("clang-cl") {
ToolFamily::Msvc { clang_cl: true } ToolFamily::Msvc { clang_cl: true }
} else if fname.contains("cl") } else if fname.ends_with("cl") || fname == "cl.exe" {
&& !fname.contains("cloudabi")
&& !fname.contains("uclibc")
&& !fname.contains("clang")
{
ToolFamily::Msvc { clang_cl: false } ToolFamily::Msvc { clang_cl: false }
} else if fname.contains("clang") { } else if fname.contains("clang") {
match clang_driver { match clang_driver {

View File

@ -62,7 +62,7 @@ rust_library(
"//third_party/cargo/vendor/core-foundation-0.7.0:core_foundation", "//third_party/cargo/vendor/core-foundation-0.7.0:core_foundation",
"//third_party/cargo/vendor/core-graphics-0.19.2:core_graphics", "//third_party/cargo/vendor/core-graphics-0.19.2:core_graphics",
"//third_party/cargo/vendor/foreign-types-0.3.2:foreign_types", "//third_party/cargo/vendor/foreign-types-0.3.2:foreign_types",
"//third_party/cargo/vendor/libc-0.2.82:libc", "//third_party/cargo/vendor/libc-0.2.92:libc",
"//third_party/cargo/vendor/objc-0.2.7:objc", "//third_party/cargo/vendor/objc-0.2.7:objc",
], ],
) )

View File

@ -63,7 +63,7 @@ rust_library(
"//third_party/cargo/vendor/core-foundation-0.9.1:core_foundation", "//third_party/cargo/vendor/core-foundation-0.9.1:core_foundation",
"//third_party/cargo/vendor/core-graphics-0.22.2:core_graphics", "//third_party/cargo/vendor/core-graphics-0.22.2:core_graphics",
"//third_party/cargo/vendor/foreign-types-0.3.2:foreign_types", "//third_party/cargo/vendor/foreign-types-0.3.2:foreign_types",
"//third_party/cargo/vendor/libc-0.2.82:libc", "//third_party/cargo/vendor/libc-0.2.92:libc",
"//third_party/cargo/vendor/objc-0.2.7:objc", "//third_party/cargo/vendor/objc-0.2.7:objc",
], ],
) )

View File

@ -54,7 +54,7 @@ rust_library(
"//third_party/cargo/vendor/core-foundation-0.9.1:core_foundation", "//third_party/cargo/vendor/core-foundation-0.9.1:core_foundation",
"//third_party/cargo/vendor/core-graphics-types-0.1.1:core_graphics_types", "//third_party/cargo/vendor/core-graphics-types-0.1.1:core_graphics_types",
"//third_party/cargo/vendor/foreign-types-0.3.2:foreign_types", "//third_party/cargo/vendor/foreign-types-0.3.2:foreign_types",
"//third_party/cargo/vendor/libc-0.2.82:libc", "//third_party/cargo/vendor/libc-0.2.92:libc",
"//third_party/cargo/vendor/objc-0.2.7:objc", "//third_party/cargo/vendor/objc-0.2.7:objc",
], ],
) )

View File

@ -1 +0,0 @@
{"files":{"CHANGELOG.md":"3d4c8910c720a6467a5576a3ed910d852e3595b0a55a5e412514eefc481ec8d9","Cargo.toml":"9163a47eff7b4bd7d6ed96159d3b8b8452eb39aeb0b8e694309a99e47ddc99a7","LICENSE-APACHE":"0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"e2c098d1b809f792484ca7e4ff21a1992ae83693683ba39d4a0e34ba1be2760f","build.rs":"0095fffab24644ea5b04a6132b0ccb53762435cc637092e6d4c471c4cc66f60b","src/ast.rs":"4d4a1ddb8deefa31c3e798ffe9cb32752f9b5418c61a8e45be32ca0d5f9b63f3","src/error.rs":"9bc6f12801616dc1750346bf4228d1b172bee88777e9c8cb841dd9348fecbcf3","src/iter.rs":"4eccd018075a4f4839adef2e2cf05198780b9b60d6fbfa8188522c2ad8e82cb5","src/lib.rs":"3ad19d38445a06934b60abe94611c77145c0dbcdc28630abb9a5c27c6b6f998f","src/to_tokens.rs":"5e831889f220c5abaf0403e56b485fbbbb1c4516023e82934f69a230d76694bf","src/utils.rs":"b73f44e9260d32d71aa2712b242f8c451317f62ee1523595fca19878ac07dcd4"},"package":"28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6"}

View File

@ -1,55 +0,0 @@
"""
@generated
cargo-raze crate build file.
DO NOT EDIT! Replaced on runs of cargo-raze
"""
# buildifier: disable=load
load(
"@rules_rust//rust:rust.bzl",
"rust_binary",
"rust_library",
"rust_test",
)
# buildifier: disable=load
load("@bazel_skylib//lib:selects.bzl", "selects")
package(default_visibility = [
# Public for visibility by "@raze__crate__version//" targets.
#
# Prefer access through "//third_party/cargo", which limits external
# visibility to explicit Cargo.toml dependencies.
"//visibility:public",
])
licenses([
"notice", # Apache-2.0 from expression "Apache-2.0 OR MIT"
])
# Generated Targets
# Unsupported target "build-script-build" with type "custom-build" omitted
rust_library(
name = "const_fn",
srcs = glob(["**/*.rs"]),
crate_features = [
],
crate_root = "src/lib.rs",
crate_type = "proc-macro",
data = [],
edition = "2018",
rustc_flags = [
"--cap-lints=allow",
],
tags = [
"cargo-raze",
"manual",
],
version = "0.4.5",
# buildifier: leave-alone
deps = [
],
)

View File

@ -1,149 +0,0 @@
# Changelog
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org).
<!--
Note: In this file, do not use the hard wrap in the middle of a sentence for compatibility with GitHub comment style markdown rendering.
-->
## [Unreleased]
## [0.4.5] - 2021-01-05
- Exclude unneeded files from crates.io.
## [0.4.4] - 2020-11-02
- [Accept `const_fn` attribute with no arguments and functions without `const` keyword.](https://github.com/taiki-e/const_fn/pull/34)
This allows `const_fn` to be used as an optional dependency.
```rust
#[cfg_attr(feature = "...", const_fn::const_fn)]
pub fn func() {
/* ... */
}
```
## [0.4.3] - 2020-11-02
- [`const_fn` no longer fails to compile if unable to determine rustc version. Instead, it now displays a warning.](https://github.com/taiki-e/const_fn/pull/31)
- [`const_fn` no longer relies on debug print format.](https://github.com/taiki-e/const_fn/pull/30)
## [0.4.2] - 2020-08-31
- [Improve error messages when failed to parse version information.](https://github.com/taiki-e/const_fn/pull/26)
- [Fix compile failure with cargo installed by yum.](https://github.com/taiki-e/const_fn/pull/26)
## [0.4.1] - 2020-08-25
- [Fix compile failure with non-cargo build systems.](https://github.com/taiki-e/const_fn/pull/23)
## [0.4.0] - 2020-08-25
- [Add support for version-based code generation.](https://github.com/taiki-e/const_fn/pull/17) The following conditions are available:
```rust
use const_fn::const_fn;
// function is `const` on specified version and later compiler (including beta and nightly)
#[const_fn("1.36")]
pub const fn version() {
/* ... */
}
// function is `const` on nightly compiler (including dev build)
#[const_fn(nightly)]
pub const fn nightly() {
/* ... */
}
// function is `const` if `cfg(...)` is true
#[const_fn(cfg(...))]
pub const fn cfg() {
/* ... */
}
// function is `const` if `cfg(feature = "...")` is true
#[const_fn(feature = "...")]
pub const fn feature() {
/* ... */
}
```
- Improve compile time by removing proc-macro related dependencies ([#18](https://github.com/taiki-e/const_fn/pull/18), [#20](https://github.com/taiki-e/const_fn/pull/20)).
## [0.3.1] - 2019-12-09
- Updated `syn-mid` to 0.5.
## [0.3.0] - 2019-10-20
- `#[const_fn]` attribute may only be used on const functions.
## [0.2.1] - 2019-08-15
- Updated `proc-macro2`, `syn`, and `quote` to 1.0.
- Updated `syn-mid` to 0.4.
## [0.2.0] - 2019-06-16
- Transition to Rust 2018. With this change, the minimum required version will go up to Rust 1.31.
## [0.1.7] - 2019-02-18
- Update syn-mid version to 0.3
## [0.1.6] - 2019-02-15
- Reduce compilation time
## [0.1.5] - 2019-02-15
- Revert 0.1.4
## [0.1.4] - 2019-02-15
**Note: This release has been yanked.**
- Reduce compilation time
## [0.1.3] - 2019-01-06
- Fix dependencies
## [0.1.2] - 2018-12-27
- Improve error messages
## [0.1.1] - 2018-12-27
- Improve an error message
## [0.1.0] - 2018-12-25
Initial release
[Unreleased]: https://github.com/taiki-e/const_fn/compare/v0.4.5...HEAD
[0.4.5]: https://github.com/taiki-e/const_fn/compare/v0.4.4...v0.4.5
[0.4.4]: https://github.com/taiki-e/const_fn/compare/v0.4.3...v0.4.4
[0.4.3]: https://github.com/taiki-e/const_fn/compare/v0.4.2...v0.4.3
[0.4.2]: https://github.com/taiki-e/const_fn/compare/v0.4.1...v0.4.2
[0.4.1]: https://github.com/taiki-e/const_fn/compare/v0.4.0...v0.4.1
[0.4.0]: https://github.com/taiki-e/const_fn/compare/v0.3.1...v0.4.0
[0.3.1]: https://github.com/taiki-e/const_fn/compare/v0.3.0...v0.3.1
[0.3.0]: https://github.com/taiki-e/const_fn/compare/v0.2.1...v0.3.0
[0.2.1]: https://github.com/taiki-e/const_fn/compare/v0.2.0...v0.2.1
[0.2.0]: https://github.com/taiki-e/const_fn/compare/v0.1.7...v0.2.0
[0.1.7]: https://github.com/taiki-e/const_fn/compare/v0.1.6...v0.1.7
[0.1.6]: https://github.com/taiki-e/const_fn/compare/v0.1.5...v0.1.6
[0.1.5]: https://github.com/taiki-e/const_fn/compare/v0.1.4...v0.1.5
[0.1.4]: https://github.com/taiki-e/const_fn/compare/v0.1.3...v0.1.4
[0.1.3]: https://github.com/taiki-e/const_fn/compare/v0.1.2...v0.1.3
[0.1.2]: https://github.com/taiki-e/const_fn/compare/v0.1.1...v0.1.2
[0.1.1]: https://github.com/taiki-e/const_fn/compare/v0.1.0...v0.1.1
[0.1.0]: https://github.com/taiki-e/const_fn/releases/tag/v0.1.0

View File

@ -1,30 +0,0 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies
#
# If you believe there's an error in this file please file an
# issue against the rust-lang/cargo repository. If you're
# editing this file be aware that the upstream Cargo.toml
# will likely look very different (and much more reasonable)
[package]
edition = "2018"
name = "const_fn"
version = "0.4.5"
authors = ["Taiki Endo <te316e89@gmail.com>"]
exclude = ["/.github", "/scripts"]
description = "An attribute for easy generation of const functions with conditional compilations.\n"
documentation = "https://docs.rs/const_fn"
readme = "README.md"
keywords = ["macros", "attribute", "const", "static"]
categories = ["rust-patterns", "no-std"]
license = "Apache-2.0 OR MIT"
repository = "https://github.com/taiki-e/const_fn"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
[lib]
proc-macro = true

View File

@ -1,177 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

View File

@ -1,71 +0,0 @@
# \#\[const_fn\]
[![crates.io](https://img.shields.io/crates/v/const_fn.svg?style=flat-square&logo=rust)](https://crates.io/crates/const_fn)
[![docs.rs](https://img.shields.io/badge/docs.rs-const__fn-blue?style=flat-square)](https://docs.rs/const_fn)
[![license](https://img.shields.io/badge/license-Apache--2.0_OR_MIT-blue.svg?style=flat-square)](#license)
[![rustc](https://img.shields.io/badge/rustc-1.31+-blue.svg?style=flat-square)](https://www.rust-lang.org)
[![build status](https://img.shields.io/github/workflow/status/taiki-e/const_fn/CI/master?style=flat-square)](https://github.com/taiki-e/const_fn/actions?query=workflow%3ACI+branch%3Amaster)
An attribute for easy generation of const functions with conditional
compilations.
## Usage
Add this to your `Cargo.toml`:
```toml
[dependencies]
const_fn = "0.4"
```
*Compiler support: requires rustc 1.31+*
## Examples
```rust
use const_fn::const_fn;
// function is `const` on specified version and later compiler (including beta and nightly)
#[const_fn("1.36")]
pub const fn version() {
/* ... */
}
// function is `const` on nightly compiler (including dev build)
#[const_fn(nightly)]
pub const fn nightly() {
/* ... */
}
// function is `const` if `cfg(...)` is true
#[const_fn(cfg(...))]
pub const fn cfg() {
/* ... */
}
// function is `const` if `cfg(feature = "...")` is true
#[const_fn(feature = "...")]
pub const fn feature() {
/* ... */
}
```
## Alternatives
This crate is proc-macro, but is very lightweight, and has no dependencies.
You can manually define declarative macros with similar functionality (see
[`if_rust_version`](https://github.com/ogoffart/if_rust_version#examples)),
or [you can define the same function twice with different cfg](https://github.com/crossbeam-rs/crossbeam/blob/0b6ea5f69fde8768c1cfac0d3601e0b4325d7997/crossbeam-epoch/src/atomic.rs#L340-L372).
(Note: the former approach requires more macros to be defined depending on the
number of version requirements, the latter approach requires more functions to
be maintained manually)
## License
Licensed under either of [Apache License, Version 2.0](LICENSE-APACHE) or
[MIT license](LICENSE-MIT) at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall
be dual licensed as above, without any additional terms or conditions.

View File

@ -1,102 +0,0 @@
#![forbid(unsafe_code)]
#![warn(rust_2018_idioms, single_use_lifetimes)]
use std::{
env, fs,
path::{Path, PathBuf},
process::Command,
str,
};
// The rustc-cfg strings below are *not* public API. Please let us know by
// opening a GitHub issue if your build environment requires some way to enable
// these cfgs other than by executing our build script.
fn main() {
let rustc: PathBuf = env::var_os("RUSTC").unwrap_or_else(|| "rustc".into()).into();
let version = match Version::from_rustc(&rustc) {
Ok(version) => version.print(),
Err(e) => {
println!(
"cargo:warning={}: unable to determine rustc version: {}",
env!("CARGO_PKG_NAME"),
e
);
return;
}
};
let out_dir: PathBuf = env::var_os("OUT_DIR").expect("OUT_DIR not set").into();
let out_file = &out_dir.join("version");
fs::write(out_file, version)
.unwrap_or_else(|e| panic!("failed to write {}: {}", out_file.display(), e));
// Mark as build script has been run successfully.
println!("cargo:rustc-cfg=const_fn_has_build_script");
}
struct Version {
minor: u32,
nightly: bool,
}
impl Version {
// Based on https://github.com/cuviper/autocfg/blob/1.0.1/src/version.rs#L25-L59
//
// TODO: use autocfg if https://github.com/cuviper/autocfg/issues/28 merged
// or https://github.com/taiki-e/const_fn/issues/27 rejected.
fn from_rustc(rustc: &Path) -> Result<Self, String> {
let output =
Command::new(rustc).args(&["--version", "--verbose"]).output().map_err(|e| {
format!("could not execute `{} --version --verbose`: {}", rustc.display(), e)
})?;
if !output.status.success() {
return Err(format!(
"process didn't exit successfully: `{} --version --verbose`",
rustc.display()
));
}
let output = str::from_utf8(&output.stdout).map_err(|e| {
format!("failed to parse output of `{} --version --verbose`: {}", rustc.display(), e)
})?;
// Find the release line in the verbose version output.
let release = output
.lines()
.find(|line| line.starts_with("release: "))
.map(|line| &line["release: ".len()..])
.ok_or_else(|| {
format!(
"could not find rustc release from output of `{} --version --verbose`: {}",
rustc.display(),
output
)
})?;
// Split the version and channel info.
let mut version_channel = release.split('-');
let version = version_channel.next().unwrap();
let channel = version_channel.next();
let minor = (|| {
// Split the version into semver components.
let mut digits = version.splitn(3, '.');
let major = digits.next()?;
if major != "1" {
return None;
}
let minor = digits.next()?.parse().ok()?;
let _patch = digits.next()?;
Some(minor)
})()
.ok_or_else(|| {
format!("unexpected output from `{} --version --verbose`: {}", rustc.display(), output)
})?;
let nightly = channel.map_or(false, |c| c == "dev" || c == "nightly");
Ok(Self { minor, nightly })
}
fn print(&self) -> String {
format!("Version {{ minor: {}, nightly: {} }}\n", self.minor, self.nightly)
}
}

View File

@ -1,141 +0,0 @@
use proc_macro::{Delimiter, Ident, Literal, Span, TokenStream, TokenTree};
use crate::{
iter::TokenIter,
to_tokens::ToTokens,
utils::{parse_as_empty, tt_span},
Result,
};
pub(crate) struct Func {
pub(crate) attrs: Vec<Attribute>,
pub(crate) sig: Vec<TokenTree>,
pub(crate) body: TokenTree,
pub(crate) print_const: bool,
}
pub(crate) fn parse_input(input: TokenStream) -> Result<Func> {
let mut input = TokenIter::new(input);
let attrs = parse_attrs(&mut input)?;
let sig = parse_signature(&mut input);
let body = input.next();
parse_as_empty(input)?;
if body.is_none()
|| !sig
.iter()
.any(|tt| if let TokenTree::Ident(i) = tt { i.to_string() == "fn" } else { false })
{
return Err(error!(
Span::call_site(),
"#[const_fn] attribute may only be used on functions"
));
}
Ok(Func { attrs, sig, body: body.unwrap(), print_const: true })
}
impl ToTokens for Func {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.attrs.iter().for_each(|attr| attr.to_tokens(tokens));
if self.print_const {
self.sig.iter().for_each(|attr| attr.to_tokens(tokens));
} else {
self.sig
.iter()
.filter(
|tt| if let TokenTree::Ident(i) = tt { i.to_string() != "const" } else { true },
)
.for_each(|tt| tt.to_tokens(tokens));
}
self.body.to_tokens(tokens);
}
}
fn parse_signature(input: &mut TokenIter) -> Vec<TokenTree> {
let mut sig = Vec::new();
let mut has_const = false;
loop {
match input.peek() {
Some(TokenTree::Group(group)) if group.delimiter() == Delimiter::Brace => break,
None => break,
Some(TokenTree::Ident(i)) if !has_const => {
match &*i.to_string() {
"const" => has_const = true,
"async" | "unsafe" | "extern" | "fn" => {
sig.push(TokenTree::Ident(Ident::new("const", i.span())));
has_const = true;
}
_ => {}
}
sig.push(input.next().unwrap());
}
Some(_) => sig.push(input.next().unwrap()),
}
}
sig
}
fn parse_attrs(input: &mut TokenIter) -> Result<Vec<Attribute>> {
let mut attrs = Vec::new();
loop {
let pound_token = match input.peek() {
Some(TokenTree::Punct(p)) if p.as_char() == '#' => input.next().unwrap(),
_ => break,
};
let group = match input.peek() {
Some(TokenTree::Group(g)) if g.delimiter() == Delimiter::Bracket => {
input.next().unwrap()
}
tt => return Err(error!(tt_span(tt), "expected `[`")),
};
attrs.push(Attribute { pound_token, group });
}
Ok(attrs)
}
pub(crate) struct Attribute {
// `#`
pub(crate) pound_token: TokenTree,
// `[...]`
pub(crate) group: TokenTree,
}
impl ToTokens for Attribute {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.pound_token.to_tokens(tokens);
self.group.to_tokens(tokens);
}
}
pub(crate) struct LitStr {
pub(crate) token: Literal,
value: String,
}
impl LitStr {
pub(crate) fn new(token: Literal) -> Result<Self> {
let value = token.to_string();
// unlike `syn::LitStr`, only accepts `"..."`
if value.starts_with('"') && value.ends_with('"') {
Ok(Self { token, value })
} else {
Err(error!(token.span(), "expected string literal"))
}
}
pub(crate) fn value(&self) -> &str {
&self.value[1..self.value.len() - 1]
}
pub(crate) fn span(&self) -> Span {
self.token.span()
}
}
impl ToTokens for LitStr {
fn to_tokens(&self, tokens: &mut TokenStream) {
self.token.to_tokens(tokens);
}
}

View File

@ -1,37 +0,0 @@
use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
use std::iter::FromIterator;
pub(crate) struct Error {
span: Span,
msg: String,
}
impl Error {
pub(crate) fn new(span: Span, msg: impl Into<String>) -> Self {
Self { span, msg: msg.into() }
}
// https://github.com/dtolnay/syn/blob/1.0.39/src/error.rs#L218-L237
pub(crate) fn to_compile_error(&self) -> TokenStream {
// compile_error!($msg)
TokenStream::from_iter(vec![
TokenTree::Ident(Ident::new("compile_error", self.span)),
TokenTree::Punct({
let mut punct = Punct::new('!', Spacing::Alone);
punct.set_span(self.span);
punct
}),
TokenTree::Group({
let mut group = Group::new(Delimiter::Brace, {
TokenStream::from_iter(vec![TokenTree::Literal({
let mut string = Literal::string(&self.msg);
string.set_span(self.span);
string
})])
});
group.set_span(self.span);
group
}),
])
}
}

View File

@ -1,39 +0,0 @@
// Based on https://github.com/dtolnay/proc-macro-hack/blob/0.5.18/src/iter.rs
use proc_macro::{token_stream, Delimiter, TokenStream, TokenTree};
pub(crate) struct TokenIter {
stack: Vec<token_stream::IntoIter>,
peeked: Option<TokenTree>,
}
impl TokenIter {
pub(crate) fn new(tokens: TokenStream) -> Self {
Self { stack: vec![tokens.into_iter()], peeked: None }
}
pub(crate) fn peek(&mut self) -> Option<&TokenTree> {
self.peeked = self.next();
self.peeked.as_ref()
}
}
impl Iterator for TokenIter {
type Item = TokenTree;
fn next(&mut self) -> Option<Self::Item> {
if let Some(tt) = self.peeked.take() {
return Some(tt);
}
loop {
let top = self.stack.last_mut()?;
match top.next() {
None => drop(self.stack.pop()),
Some(TokenTree::Group(ref group)) if group.delimiter() == Delimiter::None => {
self.stack.push(group.stream().into_iter());
}
Some(tt) => return Some(tt),
}
}
}
}

View File

@ -1,233 +0,0 @@
//! An attribute for easy generation of const functions with conditional
//! compilations.
//!
//! # Examples
//!
//! ```rust
//! use const_fn::const_fn;
//!
//! // function is `const` on specified version and later compiler (including beta and nightly)
//! #[const_fn("1.36")]
//! pub const fn version() {
//! /* ... */
//! }
//!
//! // function is `const` on nightly compiler (including dev build)
//! #[const_fn(nightly)]
//! pub const fn nightly() {
//! /* ... */
//! }
//!
//! // function is `const` if `cfg(...)` is true
//! # #[cfg(any())]
//! #[const_fn(cfg(...))]
//! # pub fn _cfg() { unimplemented!() }
//! pub const fn cfg() {
//! /* ... */
//! }
//!
//! // function is `const` if `cfg(feature = "...")` is true
//! #[const_fn(feature = "...")]
//! pub const fn feature() {
//! /* ... */
//! }
//! ```
//!
//! # Alternatives
//!
//! This crate is proc-macro, but is very lightweight, and has no dependencies.
//!
//! You can manually define declarative macros with similar functionality (see [`if_rust_version`](https://github.com/ogoffart/if_rust_version#examples)), or [you can define the same function twice with different cfg](https://github.com/crossbeam-rs/crossbeam/blob/0b6ea5f69fde8768c1cfac0d3601e0b4325d7997/crossbeam-epoch/src/atomic.rs#L340-L372).
//! (Note: the former approach requires more macros to be defined depending on the number of version requirements, the latter approach requires more functions to be maintained manually)
#![doc(test(
no_crate_inject,
attr(
deny(warnings, rust_2018_idioms, single_use_lifetimes),
allow(dead_code, unused_variables)
)
))]
#![forbid(unsafe_code)]
#![warn(future_incompatible, rust_2018_idioms, single_use_lifetimes, unreachable_pub)]
#![warn(clippy::all, clippy::default_trait_access)]
// older compilers require explicit `extern crate`.
#[allow(unused_extern_crates)]
extern crate proc_macro;
#[macro_use]
mod utils;
mod ast;
mod error;
mod iter;
mod to_tokens;
use proc_macro::{Delimiter, TokenStream, TokenTree};
use std::str::FromStr;
use crate::{
ast::{Func, LitStr},
error::Error,
to_tokens::ToTokens,
utils::{cfg_attrs, parse_as_empty, tt_span},
};
type Result<T, E = Error> = std::result::Result<T, E>;
/// An attribute for easy generation of const functions with conditional compilations.
///
/// See crate level documentation for details.
#[proc_macro_attribute]
pub fn const_fn(args: TokenStream, input: TokenStream) -> TokenStream {
let arg = match parse_arg(args) {
Ok(arg) => arg,
Err(e) => return e.to_compile_error(),
};
let func = match ast::parse_input(input) {
Ok(func) => func,
Err(e) => return e.to_compile_error(),
};
expand(arg, func)
}
fn expand(arg: Arg, mut func: Func) -> TokenStream {
match arg {
Arg::Cfg(cfg) => {
let (mut tokens, cfg_not) = cfg_attrs(cfg);
tokens.extend(func.to_token_stream());
tokens.extend(cfg_not);
func.print_const = false;
tokens.extend(func.to_token_stream());
tokens
}
Arg::Feature(feat) => {
let (mut tokens, cfg_not) = cfg_attrs(feat);
tokens.extend(func.to_token_stream());
tokens.extend(cfg_not);
func.print_const = false;
tokens.extend(func.to_token_stream());
tokens
}
Arg::Version(req) => {
if req.major > 1 || req.minor > VERSION.minor {
func.print_const = false;
}
func.to_token_stream()
}
Arg::Nightly => {
func.print_const = VERSION.nightly;
func.to_token_stream()
}
Arg::Always => func.to_token_stream(),
}
}
enum Arg {
// `const_fn("...")`
Version(VersionReq),
// `const_fn(nightly)`
Nightly,
// `const_fn(cfg(...))`
Cfg(TokenStream),
// `const_fn(feature = "...")`
Feature(TokenStream),
// `const_fn`
Always,
}
fn parse_arg(tokens: TokenStream) -> Result<Arg> {
let mut iter = tokens.into_iter();
let next = iter.next();
let next_span = tt_span(next.as_ref());
match next {
None => return Ok(Arg::Always),
Some(TokenTree::Ident(i)) => match &*i.to_string() {
"nightly" => {
parse_as_empty(iter)?;
return Ok(Arg::Nightly);
}
"cfg" => {
return match iter.next().as_ref() {
Some(TokenTree::Group(g)) if g.delimiter() == Delimiter::Parenthesis => {
parse_as_empty(iter)?;
Ok(Arg::Cfg(g.stream()))
}
tt => Err(error!(tt_span(tt), "expected `(`")),
};
}
"feature" => {
let next = iter.next();
return match next.as_ref() {
Some(TokenTree::Punct(p)) if p.as_char() == '=' => match iter.next() {
Some(TokenTree::Literal(l)) => {
let l = LitStr::new(l)?;
parse_as_empty(iter)?;
Ok(Arg::Feature(
vec![TokenTree::Ident(i), next.unwrap(), l.token.into()]
.into_iter()
.collect(),
))
}
tt => Err(error!(tt_span(tt.as_ref()), "expected string literal")),
},
tt => Err(error!(tt_span(tt), "expected `=`")),
};
}
_ => {}
},
Some(TokenTree::Literal(l)) => {
if let Ok(l) = LitStr::new(l) {
parse_as_empty(iter)?;
return match l.value().parse::<VersionReq>() {
Ok(req) => Ok(Arg::Version(req)),
Err(e) => Err(error!(l.span(), "{}", e)),
};
}
}
Some(_) => {}
}
Err(error!(next_span, "expected one of: `nightly`, `cfg`, `feature`, string literal"))
}
struct VersionReq {
major: u32,
minor: u32,
}
impl FromStr for VersionReq {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut pieces = s.split('.');
let major = pieces
.next()
.ok_or("need to specify the major version")?
.parse::<u32>()
.map_err(|e| e.to_string())?;
let minor = pieces
.next()
.ok_or("need to specify the minor version")?
.parse::<u32>()
.map_err(|e| e.to_string())?;
if let Some(s) = pieces.next() {
Err(format!("unexpected input: .{}", s))
} else {
Ok(Self { major, minor })
}
}
}
struct Version {
minor: u32,
nightly: bool,
}
#[cfg(const_fn_has_build_script)]
const VERSION: Version = include!(concat!(env!("OUT_DIR"), "/version"));
// If build script has not run or unable to determine version, it is considered as Rust 1.0.
#[cfg(not(const_fn_has_build_script))]
const VERSION: Version = Version { minor: 0, nightly: false };

View File

@ -1,36 +0,0 @@
use proc_macro::{Ident, Literal, TokenStream, TokenTree};
use std::iter;
pub(crate) trait ToTokens {
fn to_tokens(&self, tokens: &mut TokenStream);
fn to_token_stream(&self) -> TokenStream {
let mut tokens = TokenStream::new();
self.to_tokens(&mut tokens);
tokens
}
}
impl ToTokens for Ident {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.extend(iter::once(TokenTree::Ident(self.clone())));
}
}
impl ToTokens for Literal {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.extend(iter::once(TokenTree::Literal(self.clone())));
}
}
impl ToTokens for TokenTree {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.extend(iter::once(self.clone()));
}
}
impl ToTokens for TokenStream {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.extend(self.clone());
}
}

View File

@ -1,46 +0,0 @@
use proc_macro::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree};
use std::iter::FromIterator;
use crate::Result;
macro_rules! error {
($span:expr, $msg:expr) => {{
crate::error::Error::new($span, $msg)
}};
($span:expr, $($tt:tt)*) => {
error!($span, format!($($tt)*))
};
}
pub(crate) fn tt_span(tt: Option<&TokenTree>) -> Span {
tt.map_or_else(Span::call_site, TokenTree::span)
}
pub(crate) fn parse_as_empty(mut tokens: impl Iterator<Item = TokenTree>) -> Result<()> {
match tokens.next() {
Some(tt) => Err(error!(tt.span(), "unexpected token: {}", tt)),
None => Ok(()),
}
}
// (`#[cfg(<tokens>)]`, `#[cfg(not(<tokens>))]`)
pub(crate) fn cfg_attrs(tokens: TokenStream) -> (TokenStream, TokenStream) {
let f = |tokens| {
let tokens = TokenStream::from_iter(vec![
TokenTree::Ident(Ident::new("cfg", Span::call_site())),
TokenTree::Group(Group::new(Delimiter::Parenthesis, tokens)),
]);
TokenStream::from_iter(vec![
TokenTree::Punct(Punct::new('#', Spacing::Alone)),
TokenTree::Group(Group::new(Delimiter::Bracket, tokens)),
])
};
let cfg_not = TokenTree::Group(Group::new(Delimiter::Parenthesis, tokens.clone()));
let cfg_not = TokenStream::from_iter(vec![
TokenTree::Ident(Ident::new("not", Span::call_site())),
cfg_not,
]);
(f(tokens), f(cfg_not))
}

View File

@ -50,7 +50,7 @@ rust_library(
# buildifier: leave-alone # buildifier: leave-alone
deps = [ deps = [
"//third_party/cargo/vendor/core-foundation-sys-0.7.0:core_foundation_sys", "//third_party/cargo/vendor/core-foundation-sys-0.7.0:core_foundation_sys",
"//third_party/cargo/vendor/libc-0.2.82:libc", "//third_party/cargo/vendor/libc-0.2.92:libc",
], ],
) )

View File

@ -50,7 +50,7 @@ rust_library(
# buildifier: leave-alone # buildifier: leave-alone
deps = [ deps = [
"//third_party/cargo/vendor/core-foundation-sys-0.8.2:core_foundation_sys", "//third_party/cargo/vendor/core-foundation-sys-0.8.2:core_foundation_sys",
"//third_party/cargo/vendor/libc-0.2.82:libc", "//third_party/cargo/vendor/libc-0.2.92:libc",
], ],
) )

View File

@ -53,6 +53,6 @@ rust_library(
"//third_party/cargo/vendor/bitflags-1.2.1:bitflags", "//third_party/cargo/vendor/bitflags-1.2.1:bitflags",
"//third_party/cargo/vendor/core-foundation-0.7.0:core_foundation", "//third_party/cargo/vendor/core-foundation-0.7.0:core_foundation",
"//third_party/cargo/vendor/foreign-types-0.3.2:foreign_types", "//third_party/cargo/vendor/foreign-types-0.3.2:foreign_types",
"//third_party/cargo/vendor/libc-0.2.82:libc", "//third_party/cargo/vendor/libc-0.2.92:libc",
], ],
) )

View File

@ -54,6 +54,6 @@ rust_library(
"//third_party/cargo/vendor/core-foundation-0.9.1:core_foundation", "//third_party/cargo/vendor/core-foundation-0.9.1:core_foundation",
"//third_party/cargo/vendor/core-graphics-types-0.1.1:core_graphics_types", "//third_party/cargo/vendor/core-graphics-types-0.1.1:core_graphics_types",
"//third_party/cargo/vendor/foreign-types-0.3.2:foreign_types", "//third_party/cargo/vendor/foreign-types-0.3.2:foreign_types",
"//third_party/cargo/vendor/libc-0.2.82:libc", "//third_party/cargo/vendor/libc-0.2.92:libc",
], ],
) )

View File

@ -52,6 +52,6 @@ rust_library(
"//third_party/cargo/vendor/bitflags-1.2.1:bitflags", "//third_party/cargo/vendor/bitflags-1.2.1:bitflags",
"//third_party/cargo/vendor/core-foundation-0.9.1:core_foundation", "//third_party/cargo/vendor/core-foundation-0.9.1:core_foundation",
"//third_party/cargo/vendor/foreign-types-0.3.2:foreign_types", "//third_party/cargo/vendor/foreign-types-0.3.2:foreign_types",
"//third_party/cargo/vendor/libc-0.2.82:libc", "//third_party/cargo/vendor/libc-0.2.92:libc",
], ],
) )

View File

@ -55,7 +55,7 @@ rust_library(
"//third_party/cargo/vendor/cfg-if-0.1.10:cfg_if", "//third_party/cargo/vendor/cfg-if-0.1.10:cfg_if",
"//third_party/cargo/vendor/core-foundation-sys-0.7.0:core_foundation_sys", "//third_party/cargo/vendor/core-foundation-sys-0.7.0:core_foundation_sys",
"//third_party/cargo/vendor/core-graphics-0.19.2:core_graphics", "//third_party/cargo/vendor/core-graphics-0.19.2:core_graphics",
"//third_party/cargo/vendor/libc-0.2.82:libc", "//third_party/cargo/vendor/libc-0.2.92:libc",
"//third_party/cargo/vendor/objc-0.2.7:objc", "//third_party/cargo/vendor/objc-0.2.7:objc",
], ],
) )

View File

@ -61,7 +61,7 @@ rust_library(
# buildifier: leave-alone # buildifier: leave-alone
deps = [ deps = [
"//third_party/cargo/vendor/cfg-if-1.0.0:cfg_if", "//third_party/cargo/vendor/cfg-if-1.0.0:cfg_if",
"//third_party/cargo/vendor/crossbeam-utils-0.8.1:crossbeam_utils", "//third_party/cargo/vendor/crossbeam-utils-0.8.3:crossbeam_utils",
], ],
) )

View File

@ -54,8 +54,8 @@ rust_library(
# buildifier: leave-alone # buildifier: leave-alone
deps = [ deps = [
"//third_party/cargo/vendor/cfg-if-1.0.0:cfg_if", "//third_party/cargo/vendor/cfg-if-1.0.0:cfg_if",
"//third_party/cargo/vendor/crossbeam-epoch-0.9.1:crossbeam_epoch", "//third_party/cargo/vendor/crossbeam-epoch-0.9.3:crossbeam_epoch",
"//third_party/cargo/vendor/crossbeam-utils-0.8.1:crossbeam_utils", "//third_party/cargo/vendor/crossbeam-utils-0.8.3:crossbeam_utils",
], ],
) )

View File

@ -1 +0,0 @@
{"files":{"CHANGELOG.md":"be05797b229bfb486c7b0432093aedc6be1129543979aad352f3e2c8b6ecb0e1","Cargo.lock":"701958899c3aeb45c5a8e46c7478f8899b85649c7f66ce63d0e6a5c3209f1ec1","Cargo.toml":"91e77f6969e25d10b83e69dc1274321329045712c7e7d389be20bc250b4409c1","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","README.md":"dbab340cd33d900cf38d5bdee509e09ef7ec3c490c7b47931e840cefec1f1d53","benches/defer.rs":"c330b704d96b2ad1aed29f72c37a99da534adef8cb06a3976d5f93bf567abb20","benches/flush.rs":"0389ac6c473632f0e93c962f223404cc360257f6699b4ec90b9b3be16bb6d74f","benches/pin.rs":"80f9e65ba04a2ddec7a330172d0b0fbc698e20c221b3d8cdc70cc42e3b9099d1","examples/sanitize.rs":"30001550746a54d6a377f8913fa41c72bf85140d7e8777e07c38491a4e31664b","examples/treiber_stack.rs":"ce4a5f8da67f8497ab0321aaa1aed032ae343c0d36500f2e55a24e76230dedcb","src/atomic.rs":"b92192024336203b865496c8c398ce53ec15bd401eb98c85fa3634bcbd126f86","src/collector.rs":"c310be652b837f73048663c08e872bc14f64b4ae9030c34fe737e6fe0e2d768b","src/default.rs":"b2c9a86b392dc3d687b01abee61b479a6043c5c654a22b79e880f4226dcf65ae","src/deferred.rs":"1df28c99dad1e22ecad7515e829b78ba54bdbbce07ad0b7b122db22b7b215a1e","src/epoch.rs":"76dd63356d5bc52e741883d39abb636e4ccb04d20499fb2a0ce797bb81aa4e91","src/guard.rs":"55c56ca1b2fbc067ae21108f0f7de4be91e5b41df2492055b635ed436782dd52","src/internal.rs":"c6f0a79fb8bccbcc58c5db1135a9bc8a6fc69affaf346c5afb69aa725b46e2b7","src/lib.rs":"a4655d14fce9c4c028d9dd0c5d8ea56064eec1dbc0aef400a236d4ace3f49c7c","src/sync/list.rs":"b16e6dc7c2f94c8682926ea8627352f49ab2b464245b241cfc77b72fa1878dd3","src/sync/mod.rs":"2da979ca3a2293f7626a2e6a9ab2fad758d92e3d2bed6cc712ef59eeeea87eab","src/sync/queue.rs":"225d4878142c245226262346c18434436ffc35f14f15a600a3006758449cccb0"},"package":"a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d"}

Some files were not shown because too many files have changed in this diff Show More