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(
name = "image",
actual = "//third_party/cargo/vendor/image-0.23.12:image",
actual = "//third_party/cargo/vendor/image-0.23.14:image",
tags = [
"cargo-raze",
"manual",
@ -50,7 +50,7 @@ alias(
alias(
name = "log",
actual = "//third_party/cargo/vendor/log-0.4.11:log",
actual = "//third_party/cargo/vendor/log-0.4.14:log",
tags = [
"cargo-raze",
"manual",
@ -59,7 +59,7 @@ alias(
alias(
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 = [
"cargo-raze",
"manual",
@ -68,7 +68,7 @@ alias(
alias(
name = "quote",
actual = "//third_party/cargo/vendor/quote-1.0.8:quote",
actual = "//third_party/cargo/vendor/quote-1.0.9:quote",
tags = [
"cargo-raze",
"manual",
@ -77,7 +77,7 @@ alias(
alias(
name = "syn",
actual = "//third_party/cargo/vendor/syn-1.0.58:syn",
actual = "//third_party/cargo/vendor/syn-1.0.68:syn",
tags = [
"cargo-raze",
"manual",

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

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

View File

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

View File

@ -2,5 +2,5 @@ cc_library(
name = "libloading_global_static",
srcs = ["libloading/global_static.c"],
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",
"manual",
],
version = "0.2.3",
version = "1.0.2",
# buildifier: leave-alone
deps = [
],

View File

@ -4,6 +4,35 @@
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)
- 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
[#5]: https://github.com/jonas-schievink/adler/pull/5

View File

@ -12,17 +12,17 @@
[package]
name = "adler"
version = "0.2.3"
version = "1.0.2"
authors = ["Jonas Schievink <jonasschievink@gmail.com>"]
description = "A simple clean-room implementation of the Adler-32 checksum"
documentation = "https://docs.rs/adler/"
readme = "README.md"
keywords = ["checksum", "integrity", "hash", "adler32"]
keywords = ["checksum", "integrity", "hash", "adler32", "zlib"]
categories = ["algorithms"]
license = "0BSD OR MIT OR Apache-2.0"
repository = "https://github.com/jonas-schievink/adler.git"
[package.metadata.docs.rs]
rustdoc-args = ["--cfg docsrs"]
rustdoc-args = ["--cfg=docsrs"]
[package.metadata.release]
no-dev-version = true
@ -62,8 +62,3 @@ version = "0.3.2"
default = ["std"]
rustc-dep-of-std = ["core", "compiler_builtins"]
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)
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
releases.
@ -14,6 +14,7 @@ releases.
- Permissively licensed (0BSD) clean-room implementation.
- Zero dependencies.
- Zero `unsafe`.
- Decent performance (3-4 GB/s).
- Supports `#![no_std]` (with `default-features = false`).
@ -23,7 +24,7 @@ Add an entry to your `Cargo.toml`:
```toml
[dependencies]
adler = "0.2.3"
adler = "1.0.2"
```
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.
//! - Zero dependencies.
//! - Zero `unsafe`.
//! - Decent performance (3-4 GB/s).
//! - `#![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
#![doc(test(attr(deny(unused_imports, unused_must_use))))]
#![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
/// 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
/// one).
/// that is not recommended (while every checksum is a hash function, they are not necessarily a
/// 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
/// [`from_checksum`]: #method.from_checksum
@ -119,6 +163,10 @@ impl Hasher for Adler32 {
}
/// 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 {
let mut h = Adler32::new();
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.
///
/// 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_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();
loop {
let len = {
@ -151,7 +222,6 @@ pub fn adler32_reader<R: BufRead>(reader: &mut R) -> io::Result<u32> {
#[cfg(test)]
mod tests {
use super::*;
use std::io::BufReader;
#[test]
fn zeroes() {
@ -198,12 +268,14 @@ mod tests {
assert_eq!(adler.checksum(), 0x8e88ef11); // from above
}
#[cfg(feature = "std")]
#[test]
fn bufread() {
use std::io::BufReader;
fn test(data: &[u8], checksum: u32) {
// `BufReader` uses an 8 KB buffer, so this will test buffer refilling.
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);
}

View File

@ -52,9 +52,9 @@ rust_library(
# buildifier: leave-alone
deps = [
"//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.1:walkdir",
"//third_party/cargo/vendor/walkdir-2.3.2:walkdir",
"//third_party/cargo/vendor/xdg-2.2.0:xdg",
"//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",
): [
"//third_party/cargo/vendor/libc-0.2.82:libc",
"//third_party/cargo/vendor/libc-0.2.92:libc",
],
"//conditions:default": [],
}) + 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",
"manual",
],
version = "1.4.1",
version = "1.5.1",
# buildifier: leave-alone
deps = [
],

View File

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

View File

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

View File

@ -1,9 +1,9 @@
MIT License
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:
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.
MIT License
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:
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.

View File

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

View File

@ -1,27 +1,27 @@
[![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)
[![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/)
# bytemuck
A crate for mucking around with piles of bytes.
## Extensions
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
in the other repo.
* https://github.com/rodrimati1992/zeroable_crates
## Stability
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,
so `rustc-1.34` will continue to be supported for at least the rest of the
`bytemuck-1.y.z` series of the crate.
(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.)
[![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)
[![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/)
# bytemuck
A crate for mucking around with piles of bytes.
## Extensions
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
in the other repo.
* https://github.com/rodrimati1992/zeroable_crates
## Stability
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,
so `rustc-1.34` will continue to be supported for at least the rest of the
`bytemuck-1.y.z` series of the crate.
(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.)

View File

@ -1,62 +1,84 @@
# `bytemuck` changelog
## 1.4
* [icewind1991](https://github.com/icewind1991) has contributed the proc-macros
for deriving impls of `Pod`, `TransparentWrapper`, `Zeroable`!! Everyone has
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
generates all the appropriate tests for you.
* The `zeroable_maybe_uninit` feature now adds a `Zeroable` impl to the
`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`).
## 1.3.1
* The entire crate is now available under the `Apache-2.0 OR MIT` license as
well as the previous `Zlib` license
[#24](https://github.com/Lokathor/bytemuck/pull/24).
* [HeroicKatora](https://github.com/HeroicKatora) added the
`try_zeroed_slice_box` function
[#10](https://github.com/Lokathor/bytemuck/pull/17). `zeroed_slice_box` is
also available.
* The `offset_of!` macro now supports a 2-arg version. For types that impl
Default, it'll just make an instance using `default` and then call over to the
3-arg version.
* The `PodCastError` type now supports `Hash` and `Display`. Also if you enable
the `extern_crate_std` feature then it will support `std::error::Error`.
* 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
isn't aligned has been corrected from being `AlignmentMismatch` (intended for
allocation casting only) to `TargetAlignmentGreaterAndInputNotAligned`.
## 1.3.0
* 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`
feature was used. Still, this is yanked, sorry.
## 1.2.0
* [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
# `bytemuck` changelog
## 1.5.1
* Fix `bytes_of` failing on zero sized types.
[PR 53](https://github.com/Lokathor/bytemuck/pull/53)
## 1.5
* Added `pod_collect_to_vec`, which will gather a slice into a vec,
allowing you to change the pod type while also safely ignoring alignment.
[PR 50](https://github.com/Lokathor/bytemuck/pull/50)
## 1.4.2
* [Kimundi](https://github.com/Kimundi) fixed an issue that could make `try_zeroed_box`
stack overflow for large values at low optimization levels.
[PR 43](https://github.com/Lokathor/bytemuck/pull/43)
## 1.4.1
* [thomcc](https://github.com/thomcc) fixed up the CI and patched over a soundness hole in `offset_of!`.
[PR 38](https://github.com/Lokathor/bytemuck/pull/38)
## 1.4
* [icewind1991](https://github.com/icewind1991) has contributed the proc-macros
for deriving impls of `Pod`, `TransparentWrapper`, `Zeroable`!! Everyone has
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
generates all the appropriate tests for you.
* The `zeroable_maybe_uninit` feature now adds a `Zeroable` impl to the
`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`).
## 1.3.1
* The entire crate is now available under the `Apache-2.0 OR MIT` license as
well as the previous `Zlib` license
[#24](https://github.com/Lokathor/bytemuck/pull/24).
* [HeroicKatora](https://github.com/HeroicKatora) added the
`try_zeroed_slice_box` function
[#10](https://github.com/Lokathor/bytemuck/pull/17). `zeroed_slice_box` is
also available.
* The `offset_of!` macro now supports a 2-arg version. For types that impl
Default, it'll just make an instance using `default` and then call over to the
3-arg version.
* The `PodCastError` type now supports `Hash` and `Display`. Also if you enable
the `extern_crate_std` feature then it will support `std::error::Error`.
* 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
isn't aligned has been corrected from being `AlignmentMismatch` (intended for
allocation casting only) to `TargetAlignmentGreaterAndInputNotAligned`.
## 1.3.0
* 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`
feature was used. Still, this is yanked, sorry.
## 1.2.0
* [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
# https://github.com/rust-lang/rustfmt/blob/rustfmt-1.4.19/Configurations.md
# Stable
edition = "2018"
fn_args_layout = "Compressed"
max_width = 80
tab_spaces = 2
use_field_init_shorthand = true
use_try_shorthand = true
use_small_heuristics = "Max"
# Unstable
format_code_in_doc_comments = true
merge_imports = true
wrap_comments = true
# Based on
# https://github.com/rust-lang/rustfmt/blob/rustfmt-1.4.19/Configurations.md
# Stable
edition = "2018"
fn_args_layout = "Compressed"
max_width = 80
tab_spaces = 2
use_field_init_shorthand = true
use_try_shorthand = true
use_small_heuristics = "Max"
# Unstable
format_code_in_doc_comments = true
merge_imports = true
wrap_comments = true

View File

@ -1,166 +1,212 @@
#![cfg(feature = "extern_crate_alloc")]
//! Stuff to boost things in the `alloc` crate.
//!
//! * You must enable the `extern_crate_alloc` feature of `bytemuck` or you will
//! not be able to use this module!
use super::*;
use alloc::{
alloc::{alloc_zeroed, Layout},
boxed::Box,
vec::Vec,
};
/// As [`try_cast_box`](try_cast_box), but unwraps for you.
#[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`.
///
/// ## Failure
///
/// * The start and end content type of the `Box` must have the exact same
/// alignment.
/// * The start and end size of the `Box` must have the exact same size.
#[inline]
pub fn try_cast_box<A: Pod, B: Pod>(
input: Box<A>,
) -> Result<Box<B>, (PodCastError, Box<A>)> {
if align_of::<A>() != align_of::<B>() {
Err((PodCastError::AlignmentMismatch, input))
} else if size_of::<A>() != size_of::<B>() {
Err((PodCastError::SizeMismatch, input))
} else {
// 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_
/// 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
/// without fear of a stack overflow.
///
/// ## Failure
///
/// This fails if the allocation fails.
#[inline]
pub fn try_zeroed_box<T: Zeroable>() -> Result<Box<T>, ()> {
if size_of::<T>() == 0 {
return Ok(Box::new(T::zeroed()));
}
let layout =
Layout::from_size_align(size_of::<T>(), align_of::<T>()).unwrap();
let ptr = unsafe { alloc_zeroed(layout) };
if ptr.is_null() {
// we don't know what the error is because `alloc_zeroed` is a dumb API
Err(())
} else {
Ok(unsafe { Box::<T>::from_raw(ptr as *mut T) })
}
}
/// As [`try_zeroed_box`], but unwraps for you.
#[inline]
pub fn zeroed_box<T: Zeroable>() -> Box<T> {
try_zeroed_box().unwrap()
}
/// Allocates a `Box<[T]>` with all contents being zeroed out.
///
/// This uses the global allocator to create a zeroed allocation and _then_
/// 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
/// without fear of a stack overflow.
///
/// ## Failure
///
/// This fails if the allocation fails.
#[inline]
pub fn try_zeroed_slice_box<T: Zeroable>(
length: usize,
) -> Result<Box<[T]>, ()> {
if size_of::<T>() == 0 {
// This will not allocate but simple create a dangling slice pointer.
let mut vec = Vec::with_capacity(length);
vec.resize_with(length, || T::zeroed());
return Ok(vec.into_boxed_slice());
}
if length == 0 {
// 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 type.
let layout_length = size_of::<T>().checked_mul(length).ok_or(())?;
assert!(layout_length != 0);
let layout =
Layout::from_size_align(layout_length, align_of::<T>()).map_err(|_| ())?;
let ptr = unsafe { alloc_zeroed(layout) };
if ptr.is_null() {
// we don't know what the error is because `alloc_zeroed` is a dumb API
Err(())
} else {
let slice =
unsafe { core::slice::from_raw_parts_mut(ptr as *mut T, length) };
Ok(unsafe { Box::<[T]>::from_raw(slice) })
}
}
/// As [`try_zeroed_slice_box`](try_zeroed_slice_box), but unwraps for you.
pub fn zeroed_slice_box<T: Zeroable>(length: usize) -> Box<[T]> {
try_zeroed_slice_box(length).unwrap()
}
/// As [`try_cast_vec`](try_cast_vec), but unwraps for you.
#[inline]
pub fn cast_vec<A: Pod, B: Pod>(input: Vec<A>) -> Vec<B> {
try_cast_vec(input).map_err(|(e, _v)| e).unwrap()
}
/// Attempts to cast the content type of a [`Vec`](alloc::vec::Vec).
///
/// On failure you get back an error along with the starting `Vec`.
///
/// ## Failure
///
/// * The start and end content type of the `Vec` must have the exact same
/// alignment.
/// * 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
/// absolute.
#[inline]
pub fn try_cast_vec<A: Pod, B: Pod>(
input: Vec<A>,
) -> Result<Vec<B>, (PodCastError, Vec<A>)> {
if align_of::<A>() != align_of::<B>() {
Err((PodCastError::AlignmentMismatch, input))
} else if size_of::<A>() != size_of::<B>() {
// Note(Lokathor): Under some conditions it would be possible to cast
// 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) })
}
}
#![cfg(feature = "extern_crate_alloc")]
//! Stuff to boost things in the `alloc` crate.
//!
//! * You must enable the `extern_crate_alloc` feature of `bytemuck` or you will
//! not be able to use this module!
use super::*;
use alloc::{
alloc::{alloc_zeroed, Layout},
boxed::Box,
vec,
vec::Vec,
};
use core::convert::TryInto;
/// As [`try_cast_box`](try_cast_box), but unwraps for you.
#[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`.
///
/// ## Failure
///
/// * The start and end content type of the `Box` must have the exact same
/// alignment.
/// * The start and end size of the `Box` must have the exact same size.
#[inline]
pub fn try_cast_box<A: Pod, B: Pod>(
input: Box<A>,
) -> Result<Box<B>, (PodCastError, Box<A>)> {
if align_of::<A>() != align_of::<B>() {
Err((PodCastError::AlignmentMismatch, input))
} else if size_of::<A>() != size_of::<B>() {
Err((PodCastError::SizeMismatch, input))
} else {
// 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_
/// 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
/// without fear of a stack overflow.
///
/// ## Failure
///
/// This fails if the allocation fails.
#[inline]
pub fn try_zeroed_box<T: Zeroable>() -> Result<Box<T>, ()> {
if size_of::<T>() == 0 {
// This will not allocate but simple create a dangling slice pointer.
// NB: We go the way via a push to `Vec<T>` to ensure the compiler
// does not allocate space for T on the stack even if the branch
// would not be taken.
let mut vec = Vec::with_capacity(1);
vec.resize_with(1, || T::zeroed());
let ptr: Box<[T; 1]> = vec.into_boxed_slice().try_into().ok().unwrap();
debug_assert!(
align_of::<[T; 1]>() == align_of::<T>()
&& size_of::<[T; 1]>() == size_of::<T>()
);
// NB: We basically do the same as in try_cast_box here:
let ptr: Box<T> = unsafe { Box::from_raw(Box::into_raw(ptr) as *mut _) };
return Ok(ptr);
}
let layout =
Layout::from_size_align(size_of::<T>(), align_of::<T>()).unwrap();
let ptr = unsafe { alloc_zeroed(layout) };
if ptr.is_null() {
// we don't know what the error is because `alloc_zeroed` is a dumb API
Err(())
} else {
Ok(unsafe { Box::<T>::from_raw(ptr as *mut T) })
}
}
/// As [`try_zeroed_box`], but unwraps for you.
#[inline]
pub fn zeroed_box<T: Zeroable>() -> Box<T> {
try_zeroed_box().unwrap()
}
/// Allocates a `Box<[T]>` with all contents being zeroed out.
///
/// This uses the global allocator to create a zeroed allocation and _then_
/// 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
/// without fear of a stack overflow.
///
/// ## Failure
///
/// This fails if the allocation fails.
#[inline]
pub fn try_zeroed_slice_box<T: Zeroable>(
length: usize,
) -> Result<Box<[T]>, ()> {
if size_of::<T>() == 0 {
// This will not allocate but simple create a dangling slice pointer.
let mut vec = Vec::with_capacity(length);
vec.resize_with(length, || T::zeroed());
return Ok(vec.into_boxed_slice());
}
if length == 0 {
// 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
// type.
let layout_length = size_of::<T>().checked_mul(length).ok_or(())?;
assert!(layout_length != 0);
let layout =
Layout::from_size_align(layout_length, align_of::<T>()).map_err(|_| ())?;
let ptr = unsafe { alloc_zeroed(layout) };
if ptr.is_null() {
// we don't know what the error is because `alloc_zeroed` is a dumb API
Err(())
} else {
let slice =
unsafe { core::slice::from_raw_parts_mut(ptr as *mut T, length) };
Ok(unsafe { Box::<[T]>::from_raw(slice) })
}
}
/// As [`try_zeroed_slice_box`](try_zeroed_slice_box), but unwraps for you.
pub fn zeroed_slice_box<T: Zeroable>(length: usize) -> Box<[T]> {
try_zeroed_slice_box(length).unwrap()
}
/// As [`try_cast_vec`](try_cast_vec), but unwraps for you.
#[inline]
pub fn cast_vec<A: Pod, B: Pod>(input: Vec<A>) -> Vec<B> {
try_cast_vec(input).map_err(|(e, _v)| e).unwrap()
}
/// Attempts to cast the content type of a [`Vec`](alloc::vec::Vec).
///
/// On failure you get back an error along with the starting `Vec`.
///
/// ## Failure
///
/// * The start and end content type of the `Vec` must have the exact same
/// alignment.
/// * 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
/// absolute.
#[inline]
pub fn try_cast_vec<A: Pod, B: Pod>(
input: Vec<A>,
) -> Result<Vec<B>, (PodCastError, Vec<A>)> {
if align_of::<A>() != align_of::<B>() {
Err((PodCastError::AlignmentMismatch, input))
} else if size_of::<A>() != size_of::<B>() {
// Note(Lokathor): Under some conditions it would be possible to cast
// 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 core::mem::{size_of, transmute_copy};
/// A trait indicating that:
///
/// 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.
/// 3. Within that range, there are no gaps.
///
/// 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
/// `#[repr(Rust)]` fieldess enums have an unspecified layout.
///
/// Additionally, you shouldn't assume that all implementations are enums. Any
/// type which meets the requirements above while following the rules under
/// "Safety" below is valid.
///
/// # Example
///
/// ```
/// # use bytemuck::Contiguous;
/// #[repr(u8)]
/// #[derive(Debug, Copy, Clone, PartialEq)]
/// enum Foo {
/// A = 0,
/// B = 1,
/// C = 2,
/// D = 3,
/// E = 4,
/// }
/// unsafe impl Contiguous for Foo {
/// type Int = u8;
/// const MIN_VALUE: u8 = Foo::A as u8;
/// const MAX_VALUE: u8 = Foo::E as u8;
/// }
/// assert_eq!(Foo::from_integer(3).unwrap(), Foo::D);
/// assert_eq!(Foo::from_integer(8), None);
/// assert_eq!(Foo::C.into_integer(), 2);
/// ```
/// # Safety
///
/// This is an unsafe trait, and incorrectly implementing it is undefined
/// behavior.
///
/// 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`
/// and `C::MAX_VALUE` exactly once, without any gaps.
///
/// Precisely, the guarantees you must uphold when implementing `Contiguous` for
/// some type `C` are:
///
/// 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)
///
/// 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
/// identical for a relevant set of traits (Ord, arithmetic, ...).
///
/// 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
/// `C`.
///
/// 4. There exist no instances of `C` such that their bitpatterns, when
/// 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
/// gets a `C` that implements `Contiguous`, it is in the appropriate range.
///
/// 5. Finally, you promise not to provide overridden implementations of
/// `Contiguous::from_integer` and `Contiguous::into_integer`.
///
/// For clarity, the following rules could be derived from the above, but are
/// listed explicitly:
///
/// - `C::MAX_VALUE` must be greater or equal to `C::MIN_VALUE` (therefore, `C`
/// must be an inhabited type).
///
/// - 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).
pub unsafe trait Contiguous: Copy + 'static {
/// The primitive integer type with an identical representation to this
/// type.
///
/// Contiguous is broadly intended for use with fieldless enums, and for
/// these the correct integer type is easy: The enum should have a
/// `#[repr(Int)]` or `#[repr(C)]` attribute, (if it does not, it is
/// *unsound* to implement `Contiguous`!).
///
/// - For `#[repr(Int)]`, use the listed `Int`. e.g. `#[repr(u8)]` should
/// use `type Int = u8`.
///
/// - 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`
/// or `libc`), but it's up to you to make the determination as the
/// implementer of the unsafe trait.
///
/// For precise rules, see the list under "Safety" above.
type Int: Copy + Ord;
/// The upper *inclusive* bound for valid instances of this type.
const MAX_VALUE: Self::Int;
/// The lower *inclusive* bound for valid instances of this type.
const MIN_VALUE: Self::Int;
/// If `value` is within the range for valid instances of this type,
/// returns `Some(converted_value)`, otherwise, returns `None`.
///
/// 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
/// `Contiguous` on your type you **must not** override this method.
///
/// # Panics
///
/// We will not panic for any correct implementation of `Contiguous`, but
/// *may* panic if we detect an incorrect one.
///
/// This is undefined behavior regardless, so it could have been the nasal
/// demons at that point anyway ;).
#[inline]
fn from_integer(value: Self::Int) -> Option<Self> {
// Guard against an illegal implementation of Contiguous. Annoyingly we
// can't rely on `transmute` to do this for us (see below), but
// whatever, this gets compiled into nothing in release.
assert!(size_of::<Self>() == size_of::<Self::Int>());
if Self::MIN_VALUE <= value && value <= Self::MAX_VALUE {
// SAFETY: We've checked their bounds (and their size, even though
// they've sworn under the Oath Of Unsafe Rust that that already
// matched) so this is allowed by `Contiguous`'s unsafe contract.
//
// So, the `transmute_copy`. ideally we'd use transmute here, which
// is more obviously safe. Sadly, we can't, as these types still
// have unspecified sizes.
Some(unsafe { transmute_copy::<Self::Int, Self>(&value) })
} else {
None
}
}
/// Perform the conversion from `C` into the underlying integral type. This
/// mostly exists otherwise generic code would need unsafe for the `value as
/// integer`
///
/// 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
/// `Contiguous` on your type you **must not** override this method.
///
/// # Panics
///
/// We will not panic for any correct implementation of `Contiguous`, but
/// *may* panic if we detect an incorrect one.
///
/// This is undefined behavior regardless, so it could have been the nasal
/// demons at that point anyway ;).
#[inline]
fn into_integer(self) -> Self::Int {
// Guard against an illegal implementation of Contiguous. Annoyingly we
// can't rely on `transmute` to do the size check for us (see
// `from_integer's comment`), but whatever, this gets compiled into
// nothing in release. Note that we don't check the result of cast
assert!(size_of::<Self>() == size_of::<Self::Int>());
// SAFETY: The unsafe contract requires that these have identical
// representations, and that the range be entirely valid. Using
// transmute_copy instead of transmute here is annoying, but is required
// as `Self` and `Self::Int` have unspecified sizes still.
unsafe { transmute_copy::<Self, Self::Int>(&self) }
}
}
macro_rules! impl_contiguous {
($($src:ty as $repr:ident in [$min:expr, $max:expr];)*) => {$(
unsafe impl Contiguous for $src {
type Int = $repr;
const MAX_VALUE: $repr = $max;
const MIN_VALUE: $repr = $min;
}
)*};
}
impl_contiguous! {
bool as u8 in [0, 1];
u8 as u8 in [0, u8::max_value()];
u16 as u16 in [0, u16::max_value()];
u32 as u32 in [0, u32::max_value()];
u64 as u64 in [0, u64::max_value()];
u128 as u128 in [0, u128::max_value()];
usize as usize in [0, usize::max_value()];
i8 as i8 in [i8::min_value(), i8::max_value()];
i16 as i16 in [i16::min_value(), i16::max_value()];
i32 as i32 in [i32::min_value(), i32::max_value()];
i64 as i64 in [i64::min_value(), i64::max_value()];
i128 as i128 in [i128::min_value(), i128::max_value()];
isize as isize in [isize::min_value(), isize::max_value()];
NonZeroU8 as u8 in [1, u8::max_value()];
NonZeroU16 as u16 in [1, u16::max_value()];
NonZeroU32 as u32 in [1, u32::max_value()];
NonZeroU64 as u64 in [1, u64::max_value()];
NonZeroU128 as u128 in [1, u128::max_value()];
NonZeroUsize as usize in [1, usize::max_value()];
}
use super::*;
use core::mem::{size_of, transmute_copy};
/// A trait indicating that:
///
/// 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.
/// 3. Within that range, there are no gaps.
///
/// 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
/// `#[repr(Rust)]` fieldess enums have an unspecified layout.
///
/// Additionally, you shouldn't assume that all implementations are enums. Any
/// type which meets the requirements above while following the rules under
/// "Safety" below is valid.
///
/// # Example
///
/// ```
/// # use bytemuck::Contiguous;
/// #[repr(u8)]
/// #[derive(Debug, Copy, Clone, PartialEq)]
/// enum Foo {
/// A = 0,
/// B = 1,
/// C = 2,
/// D = 3,
/// E = 4,
/// }
/// unsafe impl Contiguous for Foo {
/// type Int = u8;
/// const MIN_VALUE: u8 = Foo::A as u8;
/// const MAX_VALUE: u8 = Foo::E as u8;
/// }
/// assert_eq!(Foo::from_integer(3).unwrap(), Foo::D);
/// assert_eq!(Foo::from_integer(8), None);
/// assert_eq!(Foo::C.into_integer(), 2);
/// ```
/// # Safety
///
/// This is an unsafe trait, and incorrectly implementing it is undefined
/// behavior.
///
/// 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`
/// and `C::MAX_VALUE` exactly once, without any gaps.
///
/// Precisely, the guarantees you must uphold when implementing `Contiguous` for
/// some type `C` are:
///
/// 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)
///
/// 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
/// identical for a relevant set of traits (Ord, arithmetic, ...).
///
/// 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
/// `C`.
///
/// 4. There exist no instances of `C` such that their bitpatterns, when
/// 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
/// gets a `C` that implements `Contiguous`, it is in the appropriate range.
///
/// 5. Finally, you promise not to provide overridden implementations of
/// `Contiguous::from_integer` and `Contiguous::into_integer`.
///
/// For clarity, the following rules could be derived from the above, but are
/// listed explicitly:
///
/// - `C::MAX_VALUE` must be greater or equal to `C::MIN_VALUE` (therefore, `C`
/// must be an inhabited type).
///
/// - 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).
pub unsafe trait Contiguous: Copy + 'static {
/// The primitive integer type with an identical representation to this
/// type.
///
/// Contiguous is broadly intended for use with fieldless enums, and for
/// these the correct integer type is easy: The enum should have a
/// `#[repr(Int)]` or `#[repr(C)]` attribute, (if it does not, it is
/// *unsound* to implement `Contiguous`!).
///
/// - For `#[repr(Int)]`, use the listed `Int`. e.g. `#[repr(u8)]` should
/// use `type Int = u8`.
///
/// - 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`
/// or `libc`), but it's up to you to make the determination as the
/// implementer of the unsafe trait.
///
/// For precise rules, see the list under "Safety" above.
type Int: Copy + Ord;
/// The upper *inclusive* bound for valid instances of this type.
const MAX_VALUE: Self::Int;
/// The lower *inclusive* bound for valid instances of this type.
const MIN_VALUE: Self::Int;
/// If `value` is within the range for valid instances of this type,
/// returns `Some(converted_value)`, otherwise, returns `None`.
///
/// 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
/// `Contiguous` on your type you **must not** override this method.
///
/// # Panics
///
/// We will not panic for any correct implementation of `Contiguous`, but
/// *may* panic if we detect an incorrect one.
///
/// This is undefined behavior regardless, so it could have been the nasal
/// demons at that point anyway ;).
#[inline]
fn from_integer(value: Self::Int) -> Option<Self> {
// Guard against an illegal implementation of Contiguous. Annoyingly we
// can't rely on `transmute` to do this for us (see below), but
// whatever, this gets compiled into nothing in release.
assert!(size_of::<Self>() == size_of::<Self::Int>());
if Self::MIN_VALUE <= value && value <= Self::MAX_VALUE {
// SAFETY: We've checked their bounds (and their size, even though
// they've sworn under the Oath Of Unsafe Rust that that already
// matched) so this is allowed by `Contiguous`'s unsafe contract.
//
// So, the `transmute_copy`. ideally we'd use transmute here, which
// is more obviously safe. Sadly, we can't, as these types still
// have unspecified sizes.
Some(unsafe { transmute_copy::<Self::Int, Self>(&value) })
} else {
None
}
}
/// Perform the conversion from `C` into the underlying integral type. This
/// mostly exists otherwise generic code would need unsafe for the `value as
/// integer`
///
/// 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
/// `Contiguous` on your type you **must not** override this method.
///
/// # Panics
///
/// We will not panic for any correct implementation of `Contiguous`, but
/// *may* panic if we detect an incorrect one.
///
/// This is undefined behavior regardless, so it could have been the nasal
/// demons at that point anyway ;).
#[inline]
fn into_integer(self) -> Self::Int {
// Guard against an illegal implementation of Contiguous. Annoyingly we
// can't rely on `transmute` to do the size check for us (see
// `from_integer's comment`), but whatever, this gets compiled into
// nothing in release. Note that we don't check the result of cast
assert!(size_of::<Self>() == size_of::<Self::Int>());
// SAFETY: The unsafe contract requires that these have identical
// representations, and that the range be entirely valid. Using
// transmute_copy instead of transmute here is annoying, but is required
// as `Self` and `Self::Int` have unspecified sizes still.
unsafe { transmute_copy::<Self, Self::Int>(&self) }
}
}
macro_rules! impl_contiguous {
($($src:ty as $repr:ident in [$min:expr, $max:expr];)*) => {$(
unsafe impl Contiguous for $src {
type Int = $repr;
const MAX_VALUE: $repr = $max;
const MIN_VALUE: $repr = $min;
}
)*};
}
impl_contiguous! {
bool as u8 in [0, 1];
u8 as u8 in [0, u8::max_value()];
u16 as u16 in [0, u16::max_value()];
u32 as u32 in [0, u32::max_value()];
u64 as u64 in [0, u64::max_value()];
u128 as u128 in [0, u128::max_value()];
usize as usize in [0, usize::max_value()];
i8 as i8 in [i8::min_value(), i8::max_value()];
i16 as i16 in [i16::min_value(), i16::max_value()];
i32 as i32 in [i32::min_value(), i32::max_value()];
i64 as i64 in [i64::min_value(), i64::max_value()];
i128 as i128 in [i128::min_value(), i128::max_value()];
isize as isize in [isize::min_value(), isize::max_value()];
NonZeroU8 as u8 in [1, u8::max_value()];
NonZeroU16 as u16 in [1, u16::max_value()];
NonZeroU32 as u32 in [1, u32::max_value()];
NonZeroU64 as u64 in [1, u64::max_value()];
NonZeroU128 as u128 in [1, u128::max_value()];
NonZeroUsize as usize in [1, usize::max_value()];
}

View File

@ -1,442 +1,450 @@
#![no_std]
#![warn(missing_docs)]
//! This crate gives small utilities for casting between plain data types.
//!
//! ## Basics
//!
//! Data comes in five basic forms in Rust, so we have five basic casting
//! functions:
//!
//! * `T` uses [`cast`]
//! * `&T` uses [`cast_ref`]
//! * `&mut T` uses [`cast_mut`]
//! * `&[T]` uses [`cast_slice`]
//! * `&mut [T]` uses [`cast_slice_mut`]
//!
//! 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
//! 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
//! invalid input.
//!
//! ## Using Your Own Types
//!
//! All the functions here are guarded by the [`Pod`] trait, which is a
//! sub-trait of the [`Zeroable`] trait.
//!
//! 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,
//! these traits are `unsafe`, and you should carefully read the requirements
//! before adding the them to your own types.
//!
//! ## Features
//!
//! * 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
//! methods related to `Box` and `Vec`. Note that the `docs.rs` documentation
//! is always built with `extern_crate_alloc` cargo feature enabled.
#[cfg(target_arch = "x86")]
use core::arch::x86;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64;
//
use core::{marker::*, mem::*, num::*, ptr::*};
// 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
// crates to use our macros, but I'm not sure how important that is.
#[doc(hidden)]
pub use ::core as __core;
macro_rules! impl_unsafe_marker_for_array {
( $marker:ident , $( $n:expr ),* ) => {
$(unsafe impl<T> $marker for [T; $n] where T: $marker {})*
}
}
#[cfg(feature = "extern_crate_std")]
extern crate std;
#[cfg(feature = "extern_crate_alloc")]
extern crate alloc;
#[cfg(feature = "extern_crate_alloc")]
pub mod allocation;
#[cfg(feature = "extern_crate_alloc")]
pub use allocation::*;
mod zeroable;
pub use zeroable::*;
mod pod;
pub use pod::*;
mod contiguous;
pub use contiguous::*;
mod offset_of;
pub use offset_of::*;
mod transparent;
pub use transparent::*;
#[cfg(feature = "derive")]
pub use bytemuck_derive::{Zeroable, Pod, TransparentWrapper, Contiguous};
/*
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
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
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
possibility code branch.
*/
/// Immediately panics.
#[cold]
#[inline(never)]
fn something_went_wrong(src: &str, err: PodCastError) -> ! {
// Note(Lokathor): Keeping the panic here makes the panic _formatting_ go
// here too, which helps assembly readability and also helps keep down
// the inline pressure.
panic!("{src}>{err:?}", src = src, err = err)
}
/// Re-interprets `&T` as `&[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]
pub fn bytes_of<T: Pod>(t: &T) -> &[u8] {
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]
pub fn bytes_of_mut<T: Pod>(t: &mut T) -> &mut [u8] {
match try_cast_slice_mut::<T, u8>(core::slice::from_mut(t)) {
Ok(s) => s,
Err(_) => unreachable!(),
}
}
/// Re-interprets `&[u8]` as `&T`.
///
/// ## Panics
///
/// 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,
Err(e) => something_went_wrong("from_bytes", e),
}
}
/// Re-interprets `&mut [u8]` as `&mut T`.
///
/// ## Panics
///
/// This is [`try_from_bytes_mut`] but will panic on error.
#[inline]
pub fn from_bytes_mut<T: Pod>(s: &mut [u8]) -> &mut T {
match try_from_bytes_mut(s) {
Ok(t) => t,
Err(e) => something_went_wrong("from_bytes_mut", e),
}
}
/// Re-interprets `&[u8]` as `&T`.
///
/// ## Failure
///
/// * If the slice isn't aligned for the new type
/// * 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>() {
Err(PodCastError::SizeMismatch)
} else if (s.as_ptr() as usize) % align_of::<T>() != 0 {
Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned)
} else {
Ok(unsafe { &*(s.as_ptr() as *const T) })
}
}
/// Re-interprets `&mut [u8]` as `&mut T`.
///
/// ## Failure
///
/// * If the slice isn't aligned for the new type
/// * 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],
) -> Result<&mut T, PodCastError> {
if s.len() != size_of::<T>() {
Err(PodCastError::SizeMismatch)
} else if (s.as_ptr() as usize) % align_of::<T>() != 0 {
Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned)
} else {
Ok(unsafe { &mut *(s.as_mut_ptr() as *mut T) })
}
}
/// The things that can go wrong when casting between [`Pod`] data forms.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum PodCastError {
/// You tried to cast a slice to an element type with a higher alignment
/// requirement but the slice wasn't aligned.
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.
OutputSliceWouldHaveSlop,
/// When casting a slice you can't convert between ZST elements and non-ZST
/// elements. When casting an individual `T`, `&T`, or `&mut T` value the
/// source size and destination size must be an exact match.
SizeMismatch,
/// For this type of cast the alignments must be exactly the same and they
/// were not so now you're sad.
///
/// This error is generated **only** by operations that cast allocated types
/// (such as `Box` and `Vec`), because in that case the alignment must stay
/// exact.
AlignmentMismatch,
}
impl core::fmt::Display for PodCastError {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "{:?}", self)
}
}
#[cfg(feature = "extern_crate_std")]
impl std::error::Error for PodCastError {}
/// Cast `T` into `U`
///
/// ## Panics
///
/// * This is like [`try_cast`](try_cast), but will panic on a size mismatch.
#[inline]
pub fn cast<A: Pod, B: Pod>(a: A) -> B {
if size_of::<A>() == size_of::<B>() {
unsafe { core::mem::transmute_copy(&a) }
} else {
something_went_wrong("cast", PodCastError::SizeMismatch)
}
}
/// Cast `&mut T` into `&mut U`.
///
/// ## Panics
///
/// This is [`try_cast_mut`] but will panic on error.
#[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.
match try_cast_mut(a) {
Ok(b) => b,
Err(_) => unreachable!(),
}
} else {
match try_cast_mut(a) {
Ok(b) => b,
Err(e) => something_went_wrong("cast_mut", e),
}
}
}
/// Cast `&T` into `&U`.
///
/// ## Panics
///
/// 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.
match try_cast_ref(a) {
Ok(b) => b,
Err(_) => unreachable!(),
}
} else {
match try_cast_ref(a) {
Ok(b) => b,
Err(e) => something_went_wrong("cast_ref", e),
}
}
}
/// Cast `&[A]` into `&[B]`.
///
/// ## Panics
///
/// 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,
Err(e) => something_went_wrong("cast_slice", e),
}
}
/// Cast `&mut [T]` into `&mut [U]`.
///
/// ## Panics
///
/// This is [`try_cast_slice_mut`] but will panic on error.
#[inline]
pub fn cast_slice_mut<A: Pod, B: Pod>(a: &mut [A]) -> &mut [B] {
match try_cast_slice_mut(a) {
Ok(b) => b,
Err(e) => something_went_wrong("cast_slice_mut", e),
}
}
/// As `align_to`, but safe because of the [`Pod`] bound.
#[inline]
pub fn pod_align_to<T: Pod, U: Pod>(vals: &[T]) -> (&[T], &[U], &[T]) {
unsafe { vals.align_to::<U>() }
}
/// As `align_to_mut`, but safe because of the [`Pod`] bound.
#[inline]
pub fn pod_align_to_mut<T: Pod, U: Pod>(
vals: &mut [T],
) -> (&mut [T], &mut [U], &mut [T]) {
unsafe { vals.align_to_mut::<U>() }
}
/// Try to cast `T` into `U`.
///
/// Note that for this particular type of cast, alignment isn't a factor. The
/// input value is semantically copied into the function and then returned to a
/// new memory location which will have whatever the required alignment of the
/// output type is.
///
/// ## Failure
///
/// * If the types don't have the same size this fails.
#[inline]
pub fn try_cast<A: Pod, B: Pod>(a: A) -> Result<B, PodCastError> {
if size_of::<A>() == size_of::<B>() {
Ok(unsafe { core::mem::transmute_copy(&a) })
} else {
Err(PodCastError::SizeMismatch)
}
}
/// Try to convert a `&T` into `&U`.
///
/// ## Failure
///
/// * If the reference isn't aligned in the new type
/// * 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
// after monomorphization.
if align_of::<B>() > align_of::<A>()
&& (a as *const A as usize) % align_of::<B>() != 0
{
Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned)
} else if size_of::<B>() == size_of::<A>() {
Ok(unsafe { &*(a as *const A as *const B) })
} else {
Err(PodCastError::SizeMismatch)
}
}
/// Try to convert a `&mut T` into `&mut U`.
///
/// As [`try_cast_ref`], but `mut`.
#[inline]
pub fn try_cast_mut<A: Pod, B: Pod>(a: &mut A) -> Result<&mut B, PodCastError> {
// 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
{
Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned)
} else if size_of::<B>() == size_of::<A>() {
Ok(unsafe { &mut *(a as *mut A as *mut B) })
} else {
Err(PodCastError::SizeMismatch)
}
}
/// Try to convert `&[A]` into `&[B]` (possibly with a change in length).
///
/// * `input.as_ptr() as usize == output.as_ptr() as usize`
/// * `input.len() * size_of::<A>() == output.len() * size_of::<B>()`
///
/// ## Failure
///
/// * If the target type has a greater alignment requirement and the input slice
/// isn't aligned.
/// * 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
/// accounting for the size change (eg: 3 `u16` values is 1.5 `u32` values, so
/// 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)
/// and a non-ZST.
#[inline]
pub fn try_cast_slice<A: Pod, B: Pod>(a: &[A]) -> Result<&[B], PodCastError> {
// Note(Lokathor): everything with `align_of` and `size_of` will optimize away
// after monomorphization.
if align_of::<B>() > align_of::<A>()
&& (a.as_ptr() as usize) % align_of::<B>() != 0
{
Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned)
} 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)
} 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(a.as_ptr() as *const B, new_len) })
} else {
Err(PodCastError::OutputSliceWouldHaveSlop)
}
}
/// Try to convert `&mut [A]` into `&mut [B]` (possibly with a change in
/// length).
///
/// As [`try_cast_slice`], but `&mut`.
#[inline]
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
// after monomorphization.
if align_of::<B>() > align_of::<A>()
&& (a.as_mut_ptr() as usize) % align_of::<B>() != 0
{
Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned)
} else if size_of::<B>() == size_of::<A>() {
Ok(unsafe {
core::slice::from_raw_parts_mut(a.as_mut_ptr() as *mut B, a.len())
})
} 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)
}
}
#![no_std]
#![warn(missing_docs)]
//! This crate gives small utilities for casting between plain data types.
//!
//! ## Basics
//!
//! Data comes in five basic forms in Rust, so we have five basic casting
//! functions:
//!
//! * `T` uses [`cast`]
//! * `&T` uses [`cast_ref`]
//! * `&mut T` uses [`cast_mut`]
//! * `&[T]` uses [`cast_slice`]
//! * `&mut [T]` uses [`cast_slice_mut`]
//!
//! 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
//! 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
//! invalid input.
//!
//! ## Using Your Own Types
//!
//! All the functions here are guarded by the [`Pod`] trait, which is a
//! sub-trait of the [`Zeroable`] trait.
//!
//! 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,
//! these traits are `unsafe`, and you should carefully read the requirements
//! before adding the them to your own types.
//!
//! ## Features
//!
//! * 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
//! methods related to `Box` and `Vec`. Note that the `docs.rs` documentation
//! is always built with `extern_crate_alloc` cargo feature enabled.
#[cfg(target_arch = "x86")]
use core::arch::x86;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64;
//
use core::{marker::*, mem::*, num::*, ptr::*};
// 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
// crates to use our macros, but I'm not sure how important that is.
#[doc(hidden)]
pub use ::core as __core;
macro_rules! impl_unsafe_marker_for_array {
( $marker:ident , $( $n:expr ),* ) => {
$(unsafe impl<T> $marker for [T; $n] where T: $marker {})*
}
}
#[cfg(feature = "extern_crate_std")]
extern crate std;
#[cfg(feature = "extern_crate_alloc")]
extern crate alloc;
#[cfg(feature = "extern_crate_alloc")]
pub mod allocation;
#[cfg(feature = "extern_crate_alloc")]
pub use allocation::*;
mod zeroable;
pub use zeroable::*;
mod pod;
pub use pod::*;
mod contiguous;
pub use contiguous::*;
mod offset_of;
pub use offset_of::*;
mod transparent;
pub use transparent::*;
#[cfg(feature = "derive")]
pub use bytemuck_derive::{Contiguous, Pod, TransparentWrapper, Zeroable};
/*
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
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
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
possibility code branch.
*/
/// Immediately panics.
#[cold]
#[inline(never)]
fn something_went_wrong(src: &str, err: PodCastError) -> ! {
// Note(Lokathor): Keeping the panic here makes the panic _formatting_ go
// here too, which helps assembly readability and also helps keep down
// the inline pressure.
panic!("{src}>{err:?}", src = src, err = err)
}
/// Re-interprets `&T` as `&[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]
pub fn bytes_of<T: Pod>(t: &T) -> &[u8] {
if size_of::<T>() == 0 {
&[]
} 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]
pub fn bytes_of_mut<T: Pod>(t: &mut T) -> &mut [u8] {
if size_of::<T>() == 0 {
&mut []
} else {
match try_cast_slice_mut::<T, u8>(core::slice::from_mut(t)) {
Ok(s) => s,
Err(_) => unreachable!(),
}
}
}
/// Re-interprets `&[u8]` as `&T`.
///
/// ## Panics
///
/// 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,
Err(e) => something_went_wrong("from_bytes", e),
}
}
/// Re-interprets `&mut [u8]` as `&mut T`.
///
/// ## Panics
///
/// This is [`try_from_bytes_mut`] but will panic on error.
#[inline]
pub fn from_bytes_mut<T: Pod>(s: &mut [u8]) -> &mut T {
match try_from_bytes_mut(s) {
Ok(t) => t,
Err(e) => something_went_wrong("from_bytes_mut", e),
}
}
/// Re-interprets `&[u8]` as `&T`.
///
/// ## Failure
///
/// * If the slice isn't aligned for the new type
/// * 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>() {
Err(PodCastError::SizeMismatch)
} else if (s.as_ptr() as usize) % align_of::<T>() != 0 {
Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned)
} else {
Ok(unsafe { &*(s.as_ptr() as *const T) })
}
}
/// Re-interprets `&mut [u8]` as `&mut T`.
///
/// ## Failure
///
/// * If the slice isn't aligned for the new type
/// * 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],
) -> Result<&mut T, PodCastError> {
if s.len() != size_of::<T>() {
Err(PodCastError::SizeMismatch)
} else if (s.as_ptr() as usize) % align_of::<T>() != 0 {
Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned)
} else {
Ok(unsafe { &mut *(s.as_mut_ptr() as *mut T) })
}
}
/// The things that can go wrong when casting between [`Pod`] data forms.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum PodCastError {
/// You tried to cast a slice to an element type with a higher alignment
/// requirement but the slice wasn't aligned.
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.
OutputSliceWouldHaveSlop,
/// When casting a slice you can't convert between ZST elements and non-ZST
/// elements. When casting an individual `T`, `&T`, or `&mut T` value the
/// source size and destination size must be an exact match.
SizeMismatch,
/// For this type of cast the alignments must be exactly the same and they
/// were not so now you're sad.
///
/// This error is generated **only** by operations that cast allocated types
/// (such as `Box` and `Vec`), because in that case the alignment must stay
/// exact.
AlignmentMismatch,
}
impl core::fmt::Display for PodCastError {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "{:?}", self)
}
}
#[cfg(feature = "extern_crate_std")]
impl std::error::Error for PodCastError {}
/// Cast `T` into `U`
///
/// ## Panics
///
/// * This is like [`try_cast`](try_cast), but will panic on a size mismatch.
#[inline]
pub fn cast<A: Pod, B: Pod>(a: A) -> B {
if size_of::<A>() == size_of::<B>() {
unsafe { core::mem::transmute_copy(&a) }
} else {
something_went_wrong("cast", PodCastError::SizeMismatch)
}
}
/// Cast `&mut T` into `&mut U`.
///
/// ## Panics
///
/// This is [`try_cast_mut`] but will panic on error.
#[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.
match try_cast_mut(a) {
Ok(b) => b,
Err(_) => unreachable!(),
}
} else {
match try_cast_mut(a) {
Ok(b) => b,
Err(e) => something_went_wrong("cast_mut", e),
}
}
}
/// Cast `&T` into `&U`.
///
/// ## Panics
///
/// 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.
match try_cast_ref(a) {
Ok(b) => b,
Err(_) => unreachable!(),
}
} else {
match try_cast_ref(a) {
Ok(b) => b,
Err(e) => something_went_wrong("cast_ref", e),
}
}
}
/// Cast `&[A]` into `&[B]`.
///
/// ## Panics
///
/// 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,
Err(e) => something_went_wrong("cast_slice", e),
}
}
/// Cast `&mut [T]` into `&mut [U]`.
///
/// ## Panics
///
/// This is [`try_cast_slice_mut`] but will panic on error.
#[inline]
pub fn cast_slice_mut<A: Pod, B: Pod>(a: &mut [A]) -> &mut [B] {
match try_cast_slice_mut(a) {
Ok(b) => b,
Err(e) => something_went_wrong("cast_slice_mut", e),
}
}
/// As `align_to`, but safe because of the [`Pod`] bound.
#[inline]
pub fn pod_align_to<T: Pod, U: Pod>(vals: &[T]) -> (&[T], &[U], &[T]) {
unsafe { vals.align_to::<U>() }
}
/// As `align_to_mut`, but safe because of the [`Pod`] bound.
#[inline]
pub fn pod_align_to_mut<T: Pod, U: Pod>(
vals: &mut [T],
) -> (&mut [T], &mut [U], &mut [T]) {
unsafe { vals.align_to_mut::<U>() }
}
/// Try to cast `T` into `U`.
///
/// Note that for this particular type of cast, alignment isn't a factor. The
/// input value is semantically copied into the function and then returned to a
/// new memory location which will have whatever the required alignment of the
/// output type is.
///
/// ## Failure
///
/// * If the types don't have the same size this fails.
#[inline]
pub fn try_cast<A: Pod, B: Pod>(a: A) -> Result<B, PodCastError> {
if size_of::<A>() == size_of::<B>() {
Ok(unsafe { core::mem::transmute_copy(&a) })
} else {
Err(PodCastError::SizeMismatch)
}
}
/// Try to convert a `&T` into `&U`.
///
/// ## Failure
///
/// * If the reference isn't aligned in the new type
/// * 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
// after monomorphization.
if align_of::<B>() > align_of::<A>()
&& (a as *const A as usize) % align_of::<B>() != 0
{
Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned)
} else if size_of::<B>() == size_of::<A>() {
Ok(unsafe { &*(a as *const A as *const B) })
} else {
Err(PodCastError::SizeMismatch)
}
}
/// Try to convert a `&mut T` into `&mut U`.
///
/// As [`try_cast_ref`], but `mut`.
#[inline]
pub fn try_cast_mut<A: Pod, B: Pod>(a: &mut A) -> Result<&mut B, PodCastError> {
// 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
{
Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned)
} else if size_of::<B>() == size_of::<A>() {
Ok(unsafe { &mut *(a as *mut A as *mut B) })
} else {
Err(PodCastError::SizeMismatch)
}
}
/// Try to convert `&[A]` into `&[B]` (possibly with a change in length).
///
/// * `input.as_ptr() as usize == output.as_ptr() as usize`
/// * `input.len() * size_of::<A>() == output.len() * size_of::<B>()`
///
/// ## Failure
///
/// * If the target type has a greater alignment requirement and the input slice
/// isn't aligned.
/// * 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
/// accounting for the size change (eg: 3 `u16` values is 1.5 `u32` values, so
/// 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)
/// and a non-ZST.
#[inline]
pub fn try_cast_slice<A: Pod, B: Pod>(a: &[A]) -> Result<&[B], PodCastError> {
// Note(Lokathor): everything with `align_of` and `size_of` will optimize away
// after monomorphization.
if align_of::<B>() > align_of::<A>()
&& (a.as_ptr() as usize) % align_of::<B>() != 0
{
Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned)
} 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)
} 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(a.as_ptr() as *const B, new_len) })
} else {
Err(PodCastError::OutputSliceWouldHaveSlop)
}
}
/// Try to convert `&mut [A]` into `&mut [B]` (possibly with a change in
/// length).
///
/// As [`try_cast_slice`], but `&mut`.
#[inline]
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
// after monomorphization.
if align_of::<B>() > align_of::<A>()
&& (a.as_mut_ptr() as usize) % align_of::<B>() != 0
{
Err(PodCastError::TargetAlignmentGreaterAndInputNotAligned)
} else if size_of::<B>() == size_of::<A>() {
Ok(unsafe {
core::slice::from_raw_parts_mut(a.as_mut_ptr() as *mut B, a.len())
})
} 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)]
/// Find the offset in bytes of the given `$field` of `$Type`. Requires an
/// already initialized `$instance` value to work with.
///
/// This is similar to the macro from [`memoffset`](https://docs.rs/memoffset),
/// however it uses no `unsafe` code.
///
/// 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,
/// and the field name.
/// * In the 2-arg version the macro will call the [`default`](Default::default)
/// 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
/// 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
/// compilers.
///
/// ## Examples
///
/// ### 3-arg Usage
///
/// ```rust
/// # use bytemuck::offset_of;
/// // enums can't derive default, and for this example we don't pick one
/// enum MyExampleEnum {
/// A, B, C,
/// }
///
/// // so now our struct here doesn't have Default
/// #[repr(C)]
/// struct MyNotDefaultType {
/// pub counter: i32,
/// pub some_field: MyExampleEnum,
/// }
///
/// // but we provide an instance of the type and it's all good.
/// let val = MyNotDefaultType { counter: 5, some_field: MyExampleEnum::A };
/// assert_eq!(offset_of!(val, MyNotDefaultType, some_field), 4);
/// ```
///
/// ### 2-arg Usage
///
/// ```rust
/// # use bytemuck::offset_of;
/// #[derive(Default)]
/// #[repr(C)]
/// struct Vertex {
/// pub loc: [f32; 3],
/// pub color: [f32; 3],
/// }
/// // 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, color), 12);
/// ```
///
/// # Usage with `#[repr(packed)]` structs
///
/// Attempting to compute the offset of a `#[repr(packed)]` struct with
/// `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
/// Rust (See [rust-lang/rust#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;">
/// <strong>Warning:</strong> This is only true for versions of bytemuck > 1.4.0.
/// Previous versions of
/// <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,
/// which can lead to unsoundness.
/// </p>
///
/// For example, the following will fail to compile:
///
/// ```compile_fail
/// #[repr(C, packed)]
/// #[derive(Default)]
/// struct Example {
/// field: u32,
/// }
/// // Doesn't compile:
/// let _offset = bytemuck::offset_of!(Example, field);
/// ```
///
/// While the error message this generates will mention the
/// `safe_packed_borrows` lint, the macro will still fail to compile even if
/// that lint is `#[allow]`ed:
///
/// ```compile_fail
/// # #[repr(C, packed)] #[derive(Default)] struct Example { field: u32 }
/// // Still doesn't compile:
/// #[allow(safe_packed_borrows)] {
/// let _offset = bytemuck::offset_of!(Example, field);
/// }
/// ```
///
/// 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.
///
/// 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`)
/// and can prove that the struct's alignment and the field's offset are enough
/// to prove the field's alignment.
///
/// 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
/// `1.x` version of this crate that will be behind an on-by-default cargo
/// feature (to maintain minimum rust version support).
#[macro_export]
macro_rules! offset_of {
($instance:expr, $Type:path, $field:tt) => {{
#[forbid(safe_packed_borrows)]
{
// This helps us guard against field access going through a Deref impl.
#[allow(clippy::unneeded_field_pattern)]
let $Type { $field: _, .. };
let reference: &$Type = &$instance;
let address = reference as *const _ as usize;
let field_pointer = &reference.$field as *const _ as usize;
// These asserts/unwraps are compiled away at release, and defend against
// the case where somehow a deref impl is still invoked.
let result = field_pointer.checked_sub(address).unwrap();
assert!(result <= $crate::__core::mem::size_of::<$Type>());
result
}
}};
($Type:path, $field:tt) => {{
$crate::offset_of!(<$Type as Default>::default(), $Type, $field)
}};
}
#![forbid(unsafe_code)]
/// Find the offset in bytes of the given `$field` of `$Type`. Requires an
/// already initialized `$instance` value to work with.
///
/// This is similar to the macro from [`memoffset`](https://docs.rs/memoffset),
/// however it uses no `unsafe` code.
///
/// 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,
/// and the field name.
/// * In the 2-arg version the macro will call the [`default`](Default::default)
/// 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
/// 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
/// compilers.
///
/// ## Examples
///
/// ### 3-arg Usage
///
/// ```rust
/// # use bytemuck::offset_of;
/// // enums can't derive default, and for this example we don't pick one
/// enum MyExampleEnum {
/// A, B, C,
/// }
///
/// // so now our struct here doesn't have Default
/// #[repr(C)]
/// struct MyNotDefaultType {
/// pub counter: i32,
/// pub some_field: MyExampleEnum,
/// }
///
/// // but we provide an instance of the type and it's all good.
/// let val = MyNotDefaultType { counter: 5, some_field: MyExampleEnum::A };
/// assert_eq!(offset_of!(val, MyNotDefaultType, some_field), 4);
/// ```
///
/// ### 2-arg Usage
///
/// ```rust
/// # use bytemuck::offset_of;
/// #[derive(Default)]
/// #[repr(C)]
/// struct Vertex {
/// pub loc: [f32; 3],
/// pub color: [f32; 3],
/// }
/// // 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, color), 12);
/// ```
///
/// # Usage with `#[repr(packed)]` structs
///
/// Attempting to compute the offset of a `#[repr(packed)]` struct with
/// `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
/// Rust (See [rust-lang/rust#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;">
/// <strong>Warning:</strong> This is only true for versions of bytemuck > 1.4.0.
/// Previous versions of
/// <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,
/// which can lead to unsoundness.
/// </p>
///
/// For example, the following will fail to compile:
///
/// ```compile_fail
/// #[repr(C, packed)]
/// #[derive(Default)]
/// struct Example {
/// field: u32,
/// }
/// // Doesn't compile:
/// let _offset = bytemuck::offset_of!(Example, field);
/// ```
///
/// While the error message this generates will mention the
/// `safe_packed_borrows` lint, the macro will still fail to compile even if
/// that lint is `#[allow]`ed:
///
/// ```compile_fail
/// # #[repr(C, packed)] #[derive(Default)] struct Example { field: u32 }
/// // Still doesn't compile:
/// #[allow(safe_packed_borrows)] {
/// let _offset = bytemuck::offset_of!(Example, field);
/// }
/// ```
///
/// 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.
///
/// 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`)
/// and can prove that the struct's alignment and the field's offset are enough
/// to prove the field's alignment.
///
/// 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
/// `1.x` version of this crate that will be behind an on-by-default cargo
/// feature (to maintain minimum rust version support).
#[macro_export]
macro_rules! offset_of {
($instance:expr, $Type:path, $field:tt) => {{
#[forbid(safe_packed_borrows)]
{
// This helps us guard against field access going through a Deref impl.
#[allow(clippy::unneeded_field_pattern)]
let $Type { $field: _, .. };
let reference: &$Type = &$instance;
let address = reference as *const _ as usize;
let field_pointer = &reference.$field as *const _ as usize;
// These asserts/unwraps are compiled away at release, and defend against
// the case where somehow a deref impl is still invoked.
let result = field_pointer.checked_sub(address).unwrap();
assert!(result <= $crate::__core::mem::size_of::<$Type>());
result
}
}};
($Type:path, $field:tt) => {{
$crate::offset_of!(<$Type as Default>::default(), $Type, $field)
}};
}

View File

@ -1,99 +1,99 @@
use super::*;
/// Marker trait for "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,
/// it's a relatively strong claim to make about a type. Do not add this to your
/// type casually.
///
/// **Reminder:** The results of casting around bytes between data types are
/// _endian dependant_. Little-endian machines are the most common, but
/// big-endian machines do exist (and big-endian is also used for "network
/// order" bytes).
///
/// ## Safety
///
/// * The type must be inhabited (eg: no
/// [Infallible](core::convert::Infallible)).
/// * The type must allow any bit pattern (eg: no `bool` or `char`, which have
/// illegal bit patterns).
/// * 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
/// middle, and also no `#[repr(C)] struct Foo(u16, u8)`, which has padding on
/// the end).
/// * The type needs to have all fields also be `Pod`.
/// * 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
/// all other rules end up being followed.
pub unsafe trait Pod: Zeroable + Copy + 'static {}
unsafe impl Pod for () {}
unsafe impl Pod for u8 {}
unsafe impl Pod for i8 {}
unsafe impl Pod for u16 {}
unsafe impl Pod for i16 {}
unsafe impl Pod for u32 {}
unsafe impl Pod for i32 {}
unsafe impl Pod for u64 {}
unsafe impl Pod for i64 {}
unsafe impl Pod for usize {}
unsafe impl Pod for isize {}
unsafe impl Pod for u128 {}
unsafe impl Pod for i128 {}
unsafe impl Pod for f32 {}
unsafe impl Pod for f64 {}
unsafe impl<T: Pod> Pod for Wrapping<T> {}
unsafe impl Pod for Option<NonZeroI8> {}
unsafe impl Pod for Option<NonZeroI16> {}
unsafe impl Pod for Option<NonZeroI32> {}
unsafe impl Pod for Option<NonZeroI64> {}
unsafe impl Pod for Option<NonZeroI128> {}
unsafe impl Pod for Option<NonZeroIsize> {}
unsafe impl Pod for Option<NonZeroU8> {}
unsafe impl Pod for Option<NonZeroU16> {}
unsafe impl Pod for Option<NonZeroU32> {}
unsafe impl Pod for Option<NonZeroU64> {}
unsafe impl Pod for Option<NonZeroU128> {}
unsafe impl Pod for Option<NonZeroUsize> {}
unsafe impl<T: 'static> Pod for *mut T {}
unsafe impl<T: 'static> Pod for *const T {}
unsafe impl<T: 'static> Pod for Option<NonNull<T>> {}
unsafe impl<T: Pod> Pod for PhantomData<T> {}
unsafe impl<T: Pod> Pod for ManuallyDrop<T> {}
// Note(Lokathor): MaybeUninit can NEVER be Pod.
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,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 48, 64, 96, 128, 256,
512, 1024, 2048, 4096
);
#[cfg(target_arch = "x86")]
unsafe impl Pod for x86::__m128i {}
#[cfg(target_arch = "x86")]
unsafe impl Pod for x86::__m128 {}
#[cfg(target_arch = "x86")]
unsafe impl Pod for x86::__m128d {}
#[cfg(target_arch = "x86")]
unsafe impl Pod for x86::__m256i {}
#[cfg(target_arch = "x86")]
unsafe impl Pod for x86::__m256 {}
#[cfg(target_arch = "x86")]
unsafe impl Pod for x86::__m256d {}
#[cfg(target_arch = "x86_64")]
unsafe impl Pod for x86_64::__m128i {}
#[cfg(target_arch = "x86_64")]
unsafe impl Pod for x86_64::__m128 {}
#[cfg(target_arch = "x86_64")]
unsafe impl Pod for x86_64::__m128d {}
#[cfg(target_arch = "x86_64")]
unsafe impl Pod for x86_64::__m256i {}
#[cfg(target_arch = "x86_64")]
unsafe impl Pod for x86_64::__m256 {}
#[cfg(target_arch = "x86_64")]
unsafe impl Pod for x86_64::__m256d {}
use super::*;
/// Marker trait for "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,
/// it's a relatively strong claim to make about a type. Do not add this to your
/// type casually.
///
/// **Reminder:** The results of casting around bytes between data types are
/// _endian dependant_. Little-endian machines are the most common, but
/// big-endian machines do exist (and big-endian is also used for "network
/// order" bytes).
///
/// ## Safety
///
/// * The type must be inhabited (eg: no
/// [Infallible](core::convert::Infallible)).
/// * The type must allow any bit pattern (eg: no `bool` or `char`, which have
/// illegal bit patterns).
/// * 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
/// middle, and also no `#[repr(C)] struct Foo(u16, u8)`, which has padding on
/// the end).
/// * The type needs to have all fields also be `Pod`.
/// * 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
/// all other rules end up being followed.
pub unsafe trait Pod: Zeroable + Copy + 'static {}
unsafe impl Pod for () {}
unsafe impl Pod for u8 {}
unsafe impl Pod for i8 {}
unsafe impl Pod for u16 {}
unsafe impl Pod for i16 {}
unsafe impl Pod for u32 {}
unsafe impl Pod for i32 {}
unsafe impl Pod for u64 {}
unsafe impl Pod for i64 {}
unsafe impl Pod for usize {}
unsafe impl Pod for isize {}
unsafe impl Pod for u128 {}
unsafe impl Pod for i128 {}
unsafe impl Pod for f32 {}
unsafe impl Pod for f64 {}
unsafe impl<T: Pod> Pod for Wrapping<T> {}
unsafe impl Pod for Option<NonZeroI8> {}
unsafe impl Pod for Option<NonZeroI16> {}
unsafe impl Pod for Option<NonZeroI32> {}
unsafe impl Pod for Option<NonZeroI64> {}
unsafe impl Pod for Option<NonZeroI128> {}
unsafe impl Pod for Option<NonZeroIsize> {}
unsafe impl Pod for Option<NonZeroU8> {}
unsafe impl Pod for Option<NonZeroU16> {}
unsafe impl Pod for Option<NonZeroU32> {}
unsafe impl Pod for Option<NonZeroU64> {}
unsafe impl Pod for Option<NonZeroU128> {}
unsafe impl Pod for Option<NonZeroUsize> {}
unsafe impl<T: 'static> Pod for *mut T {}
unsafe impl<T: 'static> Pod for *const T {}
unsafe impl<T: 'static> Pod for Option<NonNull<T>> {}
unsafe impl<T: Pod> Pod for PhantomData<T> {}
unsafe impl<T: Pod> Pod for ManuallyDrop<T> {}
// Note(Lokathor): MaybeUninit can NEVER be Pod.
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,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 48, 64, 96, 128, 256,
512, 1024, 2048, 4096
);
#[cfg(target_arch = "x86")]
unsafe impl Pod for x86::__m128i {}
#[cfg(target_arch = "x86")]
unsafe impl Pod for x86::__m128 {}
#[cfg(target_arch = "x86")]
unsafe impl Pod for x86::__m128d {}
#[cfg(target_arch = "x86")]
unsafe impl Pod for x86::__m256i {}
#[cfg(target_arch = "x86")]
unsafe impl Pod for x86::__m256 {}
#[cfg(target_arch = "x86")]
unsafe impl Pod for x86::__m256d {}
#[cfg(target_arch = "x86_64")]
unsafe impl Pod for x86_64::__m128i {}
#[cfg(target_arch = "x86_64")]
unsafe impl Pod for x86_64::__m128 {}
#[cfg(target_arch = "x86_64")]
unsafe impl Pod for x86_64::__m128d {}
#[cfg(target_arch = "x86_64")]
unsafe impl Pod for x86_64::__m256i {}
#[cfg(target_arch = "x86_64")]
unsafe impl Pod for x86_64::__m256 {}
#[cfg(target_arch = "x86_64")]
unsafe impl Pod for x86_64::__m256d {}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,59 +1,59 @@
use bytemuck::{offset_of, Zeroable};
#[test]
fn test_offset_of_vertex() {
#[repr(C)]
struct Vertex {
pos: [f32; 2],
uv: [u16; 2],
color: [u8; 4],
}
unsafe impl Zeroable for Vertex {}
let pos = offset_of!(Zeroable::zeroed(), Vertex, pos);
let uv = offset_of!(Zeroable::zeroed(), Vertex, uv);
let color = offset_of!(Zeroable::zeroed(), Vertex, color);
assert_eq!(pos, 0);
assert_eq!(uv, 8);
assert_eq!(color, 12);
}
#[test]
fn test_offset_of_foo() {
#[derive(Default)]
struct Foo {
a: u8,
b: &'static str,
c: i32,
}
let a_offset = offset_of!(Default::default(), Foo, a);
let b_offset = offset_of!(Default::default(), Foo, b);
let c_offset = offset_of!(Default::default(), Foo, c);
assert_ne!(a_offset, b_offset);
assert_ne!(b_offset, c_offset);
// We can't check against hardcoded values for a repr(Rust) type,
// but prove to ourself this way.
let foo = Foo::default();
// Note: offsets are in bytes.
let as_bytes = &foo as *const _ as *const u8;
// we're using wrapping_offset here because it's not worth
// the unsafe block, but it would be valid to use `add` instead,
// as it cannot overflow.
assert_eq!(
&foo.a as *const _ as usize,
as_bytes.wrapping_add(a_offset) as usize
);
assert_eq!(
&foo.b as *const _ as usize,
as_bytes.wrapping_add(b_offset) as usize
);
assert_eq!(
&foo.c as *const _ as usize,
as_bytes.wrapping_add(c_offset) as usize
);
}
use bytemuck::{offset_of, Zeroable};
#[test]
fn test_offset_of_vertex() {
#[repr(C)]
struct Vertex {
pos: [f32; 2],
uv: [u16; 2],
color: [u8; 4],
}
unsafe impl Zeroable for Vertex {}
let pos = offset_of!(Zeroable::zeroed(), Vertex, pos);
let uv = offset_of!(Zeroable::zeroed(), Vertex, uv);
let color = offset_of!(Zeroable::zeroed(), Vertex, color);
assert_eq!(pos, 0);
assert_eq!(uv, 8);
assert_eq!(color, 12);
}
#[test]
fn test_offset_of_foo() {
#[derive(Default)]
struct Foo {
a: u8,
b: &'static str,
c: i32,
}
let a_offset = offset_of!(Default::default(), Foo, a);
let b_offset = offset_of!(Default::default(), Foo, b);
let c_offset = offset_of!(Default::default(), Foo, c);
assert_ne!(a_offset, b_offset);
assert_ne!(b_offset, c_offset);
// We can't check against hardcoded values for a repr(Rust) type,
// but prove to ourself this way.
let foo = Foo::default();
// Note: offsets are in bytes.
let as_bytes = &foo as *const _ as *const u8;
// we're using wrapping_offset here because it's not worth
// the unsafe block, but it would be valid to use `add` instead,
// as it cannot overflow.
assert_eq!(
&foo.a as *const _ as usize,
as_bytes.wrapping_add(a_offset) as usize
);
assert_eq!(
&foo.b as *const _ as usize,
as_bytes.wrapping_add(b_offset) as usize
);
assert_eq!(
&foo.c as *const _ 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
//! depend on that can go here.
use bytemuck::*;
#[test]
fn test_transparent_vtabled() {
use core::fmt::Display;
#[repr(transparent)]
struct DisplayTraitObj(dyn Display);
unsafe impl TransparentWrapper<dyn Display> for DisplayTraitObj {}
impl Display for DisplayTraitObj {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.0.fmt(f)
}
}
let v = DisplayTraitObj::wrap_ref(&5i32);
let s = format!("{}", v);
assert_eq!(s, "5");
let mut x = 100i32;
let v_mut = DisplayTraitObj::wrap_mut(&mut x);
let s = format!("{}", v_mut);
assert_eq!(s, "100");
}
//! The integration tests seem to always have `std` linked, so things that would
//! depend on that can go here.
use bytemuck::*;
#[test]
fn test_transparent_vtabled() {
use core::fmt::Display;
#[repr(transparent)]
struct DisplayTraitObj(dyn Display);
unsafe impl TransparentWrapper<dyn Display> for DisplayTraitObj {}
impl Display for DisplayTraitObj {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.0.fmt(f)
}
}
let v = DisplayTraitObj::wrap_ref(&5i32);
let s = format!("{}", v);
assert_eq!(s, "5");
let mut x = 100i32;
let v_mut = DisplayTraitObj::wrap_mut(&mut x);
let s = format!("{}", v_mut);
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 "build-script-build" with type "custom-build" omitted
rust_library(
name = "byteorder",
srcs = glob(["**/*.rs"]),
@ -44,7 +42,7 @@ rust_library(
crate_root = "src/lib.rs",
crate_type = "lib",
data = [],
edition = "2015",
edition = "2018",
rustc_flags = [
"--cap-lints=allow",
],
@ -52,7 +50,7 @@ rust_library(
"cargo-raze",
"manual",
],
version = "1.3.4",
version = "1.4.3",
# buildifier: leave-alone
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
=====
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)
[package]
edition = "2018"
name = "byteorder"
version = "1.3.4"
version = "1.4.3"
authors = ["Andrew Gallant <jamslam@gmail.com>"]
build = "build.rs"
exclude = ["/ci/*"]
description = "Library for reading/writing numbers in big-endian and little-endian."
homepage = "https://github.com/BurntSushi/byteorder"
documentation = "https://docs.rs/byteorder"
readme = "README.md"
keywords = ["byte", "endian", "big-endian", "little-endian", "binary"]
categories = ["encoding", "parsing"]
categories = ["encoding", "parsing", "no-std"]
license = "Unlicense OR MIT"
repository = "https://github.com/BurntSushi/byteorder"
[profile.bench]
@ -30,19 +30,14 @@ opt-level = 3
[lib]
name = "byteorder"
bench = false
[dev-dependencies.doc-comment]
version = "0.3"
[dev-dependencies.quickcheck]
version = "0.8"
version = "0.9.2"
default-features = false
[dev-dependencies.rand]
version = "0.6"
version = "0.7"
[features]
default = ["std"]
i128 = []
std = []
[badges.travis-ci]
repository = "BurntSushi/byteorder"

View File

@ -1,10 +1,12 @@
byteorder
=========
This crate provides convenience methods for encoding and decoding
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)
[![](http://meritbadge.herokuapp.com/byteorder)](https://crates.io/crates/byteorder)
[![Build status](https://github.com/BurntSushi/byteorder/workflows/ci/badge.svg)](https://github.com/BurntSushi/byteorder/actions)
[![](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
@ -27,8 +29,6 @@ If you want to augment existing `Read` and `Write` traits, then import the
extension methods like so:
```rust
extern crate byteorder;
use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian, LittleEndian};
```

View File

@ -1,15 +1,15 @@
#![feature(test)]
extern crate byteorder;
extern crate rand;
extern crate test;
macro_rules! bench_num {
($name:ident, $read:ident, $bytes:expr, $data:expr) => (
($name:ident, $read:ident, $bytes:expr, $data:expr) => {
mod $name {
use byteorder::{ByteOrder, BigEndian, NativeEndian, LittleEndian};
use super::test::Bencher;
use super::test::black_box as bb;
use byteorder::{
BigEndian, ByteOrder, LittleEndian, NativeEndian,
};
use test::black_box as bb;
use test::Bencher;
const NITER: usize = 100_000;
@ -43,14 +43,16 @@ macro_rules! bench_num {
});
}
}
);
};
($ty:ident, $max:ident,
$read:ident, $write:ident, $size:expr, $data:expr) => (
$read:ident, $write:ident, $size:expr, $data:expr) => {
mod $ty {
use byteorder::{
BigEndian, ByteOrder, LittleEndian, NativeEndian,
};
use std::$ty;
use byteorder::{ByteOrder, BigEndian, NativeEndian, LittleEndian};
use super::test::Bencher;
use super::test::black_box as bb;
use test::black_box as bb;
use test::Bencher;
const NITER: usize = 100_000;
@ -117,7 +119,7 @@ macro_rules! bench_num {
});
}
}
);
};
}
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!(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!(f64, MAX, read_f64, write_f64, 8,
[1, 2, 3, 4, 5, 6, 7, 8]);
bench_num!(f64, MAX, read_f64, write_f64, 8, [1, 2, 3, 4, 5, 6, 7, 8]);
bench_num!(uint_1, read_uint, 1, [1]);
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_8, read_int, 8, [1, 2, 3, 4, 5, 6, 7, 8]);
#[cfg(byteorder_i128)]
bench_num!(u128, MAX, read_u128, write_u128,
16, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
#[cfg(byteorder_i128)]
bench_num!(i128, MAX, read_i128, write_i128,
16, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
bench_num!(
u128,
MAX,
read_u128,
write_u128,
16,
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
);
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]);
#[cfg(byteorder_i128)]
bench_num!(uint128_2, read_uint128,
2, [1, 2]);
#[cfg(byteorder_i128)]
bench_num!(uint128_3, read_uint128,
3, [1, 2, 3]);
#[cfg(byteorder_i128)]
bench_num!(uint128_4, read_uint128,
4, [1, 2, 3, 4]);
#[cfg(byteorder_i128)]
bench_num!(uint128_5, read_uint128,
5, [1, 2, 3, 4, 5]);
#[cfg(byteorder_i128)]
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]);
#[cfg(byteorder_i128)]
bench_num!(uint128_8, read_uint128,
8, [1, 2, 3, 4, 5, 6, 7, 8]);
#[cfg(byteorder_i128)]
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]);
#[cfg(byteorder_i128)]
bench_num!(uint128_11, read_uint128,
11, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
#[cfg(byteorder_i128)]
bench_num!(uint128_12, read_uint128,
12, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
#[cfg(byteorder_i128)]
bench_num!(uint128_13, read_uint128,
13, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);
#[cfg(byteorder_i128)]
bench_num!(uint128_14, read_uint128,
14, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]);
#[cfg(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!(uint128_1, read_uint128, 1, [1]);
bench_num!(uint128_2, read_uint128, 2, [1, 2]);
bench_num!(uint128_3, read_uint128, 3, [1, 2, 3]);
bench_num!(uint128_4, read_uint128, 4, [1, 2, 3, 4]);
bench_num!(uint128_5, read_uint128, 5, [1, 2, 3, 4, 5]);
bench_num!(uint128_6, read_uint128, 6, [1, 2, 3, 4, 5, 6]);
bench_num!(uint128_7, read_uint128, 7, [1, 2, 3, 4, 5, 6, 7]);
bench_num!(uint128_8, read_uint128, 8, [1, 2, 3, 4, 5, 6, 7, 8]);
bench_num!(uint128_9, read_uint128, 9, [1, 2, 3, 4, 5, 6, 7, 8, 9]);
bench_num!(uint128_10, read_uint128, 10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
bench_num!(uint128_11, read_uint128, 11, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
bench_num!(
uint128_12,
read_uint128,
12,
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
);
bench_num!(
uint128_13,
read_uint128,
13,
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
);
bench_num!(
uint128_14,
read_uint128,
14,
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
);
bench_num!(
uint128_15,
read_uint128,
15,
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
);
bench_num!(
uint128_16,
read_uint128,
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 {
($name:ident, $numty:ty, $read:ident, $write:ident) => {
mod $name {
use std::mem::size_of;
use byteorder::{ByteOrder, BigEndian, LittleEndian};
use rand::{self, Rng};
use byteorder::{BigEndian, ByteOrder, LittleEndian};
use rand::distributions;
use rand::{self, Rng};
use test::Bencher;
#[bench]
@ -322,7 +318,7 @@ macro_rules! bench_slice {
});
}
}
}
};
}
bench_slice!(slice_u64, u64, read_u64_into, write_u64_into);

View File

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

View File

@ -49,7 +49,7 @@ rust_library(
version = "0.6.5",
# buildifier: leave-alone
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",
],
)

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

View File

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

View File

@ -13,7 +13,7 @@
[package]
edition = "2018"
name = "cc"
version = "1.0.66"
version = "1.0.67"
authors = ["Alex Crichton <alex@alexcrichton.com>"]
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"

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`,
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
@ -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:
* 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`)
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
@ -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
[Win-builds](http://win-builds.org) installation system.
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
rustc. GCC from older [MinGW](http://www.mingw.org) project is compatible
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
@ -161,7 +161,7 @@ fn main() {
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`:
```rust,no-run
@ -209,9 +209,9 @@ fn main() {
This project is licensed under either of
* 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
http://opensource.org/licenses/MIT)
https://opensource.org/licenses/MIT)
at your option.

View File

@ -1414,7 +1414,7 @@ impl Build {
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("-fdata-sections".into());
}
@ -1468,6 +1468,20 @@ impl Build {
cmd.args
.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 {
cmd.args.push(format!("--target={}", target).into());
}
@ -1600,7 +1614,7 @@ impl Build {
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
// linker that we're generating 32-bit executables as well. This'll
// typically only be used for build scripts which transitively use
@ -1677,14 +1691,17 @@ impl Build {
let mut parts = target.split('-');
if let Some(arch) = parts.next() {
let arch = &arch[5..];
cmd.args.push(("-march=rv".to_owned() + arch).into());
if target.contains("linux") && arch.starts_with("64") {
cmd.args.push(("-march=rv64gc").into());
cmd.args.push("-mabi=lp64d".into());
} else if target.contains("linux") && arch.starts_with("32") {
cmd.args.push(("-march=rv32gc").into());
cmd.args.push("-mabi=ilp32d".into());
} else if arch.starts_with("64") {
cmd.args.push(("-march=rv".to_owned() + arch).into());
cmd.args.push("-mabi=lp64".into());
} else {
cmd.args.push(("-march=rv".to_owned() + arch).into());
cmd.args.push("-mabi=ilp32".into());
}
cmd.args.push("-mcmodel=medany".into());
@ -1693,9 +1710,7 @@ impl Build {
}
}
if target.contains("-ios") {
// FIXME: potential bug. iOS is always compiled with Clang, but Gcc compiler may be
// detected instead.
if target.contains("apple-ios") {
self.ios_flags(cmd)?;
}
@ -2044,6 +2059,8 @@ impl Build {
} else {
format!("{}.exe", gnu)
}
} else if target.contains("apple-ios") {
clang.to_string()
} else if target.contains("android") {
autodetect_android_compiler(&target, &host, gnu, clang)
} else if target.contains("cloudabi") {
@ -2420,6 +2437,9 @@ impl Build {
"riscv-none-embed",
]),
"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"),
"sparc-unknown-linux-gnu" => Some("sparc-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()) {
if fname.contains("clang-cl") {
ToolFamily::Msvc { clang_cl: true }
} else if fname.contains("cl")
&& !fname.contains("cloudabi")
&& !fname.contains("uclibc")
&& !fname.contains("clang")
{
} else if fname.ends_with("cl") || fname == "cl.exe" {
ToolFamily::Msvc { clang_cl: false }
} else if fname.contains("clang") {
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-graphics-0.19.2:core_graphics",
"//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",
],
)

View File

@ -63,7 +63,7 @@ rust_library(
"//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/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",
],
)

View File

@ -54,7 +54,7 @@ rust_library(
"//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/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",
],
)

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
deps = [
"//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
deps = [
"//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/core-foundation-0.7.0:core_foundation",
"//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-graphics-types-0.1.1:core_graphics_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/core-foundation-0.9.1:core_foundation",
"//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/core-foundation-sys-0.7.0:core_foundation_sys",
"//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",
],
)

View File

@ -61,7 +61,7 @@ rust_library(
# buildifier: leave-alone
deps = [
"//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
deps = [
"//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-utils-0.8.1:crossbeam_utils",
"//third_party/cargo/vendor/crossbeam-epoch-0.9.3:crossbeam_epoch",
"//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