mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Backed out 2 changesets (bug 1550640) for webrender bustages CLOSED TREE
Backed out changeset 00e5a40ee249 (bug 1550640) Backed out changeset 46c850f36c6f (bug 1550640)
This commit is contained in:
parent
be054e6278
commit
4b7c4bf220
65
Cargo.lock
generated
65
Cargo.lock
generated
@ -106,7 +106,7 @@ dependencies = [
|
||||
"mio-named-pipes 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (git+https://github.com/servo/serde?branch=deserialize_from_enums10)",
|
||||
"tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -315,7 +315,7 @@ dependencies = [
|
||||
"filetime_win 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"guid_win 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (git+https://github.com/servo/serde?branch=deserialize_from_enums10)",
|
||||
"winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)",
|
||||
]
|
||||
|
||||
@ -976,7 +976,7 @@ dependencies = [
|
||||
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (git+https://github.com/servo/serde?branch=deserialize_from_enums10)",
|
||||
"winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)",
|
||||
]
|
||||
|
||||
@ -1030,7 +1030,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "euclid"
|
||||
version = "0.19.9"
|
||||
version = "0.19.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"euclid_macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1183,7 +1183,7 @@ dependencies = [
|
||||
"mozversion 0.2.0",
|
||||
"regex 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (git+https://github.com/servo/serde?branch=deserialize_from_enums10)",
|
||||
"serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"webdriver 0.39.0",
|
||||
@ -1715,7 +1715,7 @@ version = "0.0.1"
|
||||
dependencies = [
|
||||
"app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.25.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hashglobe 0.1.0",
|
||||
"selectors 0.21.0",
|
||||
"servo_arc 0.1.1",
|
||||
@ -1911,7 +1911,7 @@ dependencies = [
|
||||
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (git+https://github.com/servo/serde?branch=deserialize_from_enums10)",
|
||||
"syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)",
|
||||
@ -2191,25 +2191,6 @@ dependencies = [
|
||||
"winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "peek-poke"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"peek-poke-derive 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "peek-poke-derive"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "peeking_take_while"
|
||||
version = "0.1.2"
|
||||
@ -2271,7 +2252,7 @@ version = "0.13.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"binary-space-partition 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -2592,7 +2573,7 @@ dependencies = [
|
||||
"lmdb-rkv 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ordered-float 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (git+https://github.com/servo/serde?branch=deserialize_from_enums10)",
|
||||
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -2759,7 +2740,7 @@ name = "serde"
|
||||
version = "1.0.88"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (git+https://github.com/servo/serde?branch=deserialize_from_enums10)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2773,7 +2754,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.88"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
source = "git+https://github.com/servo/serde?branch=deserialize_from_enums10#84b2795d2a7b5312125a99b1ef11c67fd8d17c35"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -2945,7 +2926,7 @@ dependencies = [
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.25.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fallible 0.0.1",
|
||||
"fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hashglobe 0.1.0",
|
||||
@ -3006,7 +2987,7 @@ dependencies = [
|
||||
"app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.25.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"malloc_size_of 0.0.1",
|
||||
"malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -3594,7 +3575,7 @@ dependencies = [
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (git+https://github.com/servo/serde?branch=deserialize_from_enums10)",
|
||||
"serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -3617,7 +3598,7 @@ dependencies = [
|
||||
"core-text 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dwrote 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -3648,17 +3629,17 @@ name = "webrender_api"
|
||||
version = "0.60.0"
|
||||
dependencies = [
|
||||
"app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"peek-poke 0.2.0",
|
||||
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (git+https://github.com/servo/serde?branch=deserialize_from_enums10)",
|
||||
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wr_malloc_size_of 0.0.1",
|
||||
]
|
||||
@ -3672,7 +3653,7 @@ dependencies = [
|
||||
"core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dwrote 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -3699,7 +3680,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (git+https://github.com/servo/serde?branch=deserialize_from_enums10)",
|
||||
"serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -3769,7 +3750,7 @@ name = "wr_malloc_size_of"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3967,7 +3948,7 @@ dependencies = [
|
||||
"checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed"
|
||||
"checksum env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0561146661ae44c579e993456bc76d11ce1e0c7d745e57b2fa7146b6e49fa2ad"
|
||||
"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
|
||||
"checksum euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)" = "596b99621b9477e7a5f94d2d8dd13a9c5c302ac358b822c67a42b6f1054450e1"
|
||||
"checksum euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d1a7698bdda3d7444a79d33bdc96e8b518d44ea3ff101d8492a6ca1207b886ea"
|
||||
"checksum euclid_macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcb84c18ea5037a1c5a23039b4ff29403abce2e0d6b1daa11cf0bde2b30be15"
|
||||
"checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7"
|
||||
"checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596"
|
||||
@ -4126,7 +4107,7 @@ dependencies = [
|
||||
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
"checksum serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "9f301d728f2b94c9a7691c90f07b0b4e8a4517181d9461be94c04bddeb4bd850"
|
||||
"checksum serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)" = "adb6e51a6b3696b301bc221d785f898b4457c619b51d7ce195a6d20baecb37b3"
|
||||
"checksum serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "beed18e6f5175aef3ba670e57c60ef3b1b74d250d962a26604bff4c80e970dd4"
|
||||
"checksum serde_derive 1.0.88 (git+https://github.com/servo/serde?branch=deserialize_from_enums10)" = "<none>"
|
||||
"checksum serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "44dd2cfde475037451fa99b7e5df77aa3cfd1536575fa8e7a538ab36dcde49ae"
|
||||
"checksum serde_repr 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "29a734c298df0346c4cd5919595981c266dabbf12dc747c85e1a95e96077a52b"
|
||||
"checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a"
|
||||
|
@ -58,6 +58,7 @@ codegen-units = 1
|
||||
|
||||
[patch.crates-io]
|
||||
libudev-sys = { path = "dom/webauthn/libudev-sys" }
|
||||
serde_derive = { git = "https://github.com/servo/serde", branch = "deserialize_from_enums10" }
|
||||
winapi = { git = "https://github.com/froydnj/winapi-rs", branch = "aarch64" }
|
||||
packed_simd = { git = "https://github.com/hsivonen/packed_simd", branch = "rust_1_32" }
|
||||
|
||||
|
79
gfx/wr/Cargo.lock
generated
79
gfx/wr/Cargo.lock
generated
@ -411,7 +411,7 @@ version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -428,7 +428,7 @@ dependencies = [
|
||||
name = "direct-composition"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mozangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"webrender 0.60.0",
|
||||
@ -462,7 +462,7 @@ dependencies = [
|
||||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (git+https://github.com/servo/serde?branch=deserialize_from_enums10)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -485,7 +485,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "euclid"
|
||||
version = "0.19.9"
|
||||
version = "0.19.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"euclid_macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -499,7 +499,7 @@ version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -891,7 +891,7 @@ version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -1046,7 +1046,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -1180,13 +1180,13 @@ dependencies = [
|
||||
"app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-text 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lyon_path 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (git+https://github.com/servo/serde?branch=deserialize_from_enums10)",
|
||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -1195,7 +1195,7 @@ name = "pathfinder_gfx_utils"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/pcwalton/pathfinder?branch=webrender#e8805413321edf85870deee5678751746ed61316"
|
||||
dependencies = [
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1208,14 +1208,14 @@ dependencies = [
|
||||
"bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"half 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lyon_geom 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lyon_path 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pathfinder_path_utils 0.2.0 (git+https://github.com/pcwalton/pathfinder?branch=webrender)",
|
||||
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (git+https://github.com/servo/serde?branch=deserialize_from_enums10)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1226,26 +1226,7 @@ dependencies = [
|
||||
"arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lyon_path 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "peek-poke"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"peek-poke-derive 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "peek-poke-derive"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (git+https://github.com/servo/serde?branch=deserialize_from_enums10)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1264,7 +1245,7 @@ version = "0.13.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"binary-space-partition 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -1300,7 +1281,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.6.12"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1575,7 +1556,7 @@ name = "serde"
|
||||
version = "1.0.88"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (git+https://github.com/servo/serde?branch=deserialize_from_enums10)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1589,10 +1570,10 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.88"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
source = "git+https://github.com/servo/serde?branch=deserialize_from_enums10#84b2795d2a7b5312125a99b1ef11c67fd8d17c35"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -1724,7 +1705,7 @@ version = "0.15.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -1734,7 +1715,7 @@ version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -1976,7 +1957,7 @@ dependencies = [
|
||||
"core-text 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cstr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dwrote 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -2015,7 +1996,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glutin 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -2028,18 +2009,18 @@ name = "webrender_api"
|
||||
version = "0.60.0"
|
||||
dependencies = [
|
||||
"app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"peek-poke 0.2.0",
|
||||
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.88 (git+https://github.com/servo/serde?branch=deserialize_from_enums10)",
|
||||
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wr_malloc_size_of 0.0.1",
|
||||
]
|
||||
@ -2125,7 +2106,7 @@ name = "wr_malloc_size_of"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2142,7 +2123,7 @@ dependencies = [
|
||||
"crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dwrote 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"font-loader 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glutin 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -2287,7 +2268,7 @@ dependencies = [
|
||||
"checksum dwrote 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0bd1369e02db5e9b842a9b67bce8a2fcc043beafb2ae8a799dd482d46ea1ff0d"
|
||||
"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
|
||||
"checksum env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0e6e40ebb0e66918a37b38c7acab4e10d299e0463fe2af5d29b9cc86710cfd2a"
|
||||
"checksum euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)" = "596b99621b9477e7a5f94d2d8dd13a9c5c302ac358b822c67a42b6f1054450e1"
|
||||
"checksum euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d1a7698bdda3d7444a79d33bdc96e8b518d44ea3ff101d8492a6ca1207b886ea"
|
||||
"checksum euclid_macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcb84c18ea5037a1c5a23039b4ff29403abce2e0d6b1daa11cf0bde2b30be15"
|
||||
"checksum expat-sys 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c470ccb972f2088549b023db8029ed9da9426f5affbf9b62efff7009ab8ed5b1"
|
||||
"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||
@ -2379,7 +2360,7 @@ dependencies = [
|
||||
"checksum proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)" = "d3797b7142c9aa74954e351fc089bbee7958cebbff6bf2815e7ffff0b19f547d"
|
||||
"checksum procedural-masquerade 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9a1574a51c3fd37b26d2c0032b649d08a7d51d4cca9c41bbc5bf7118fa4509d0"
|
||||
"checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4"
|
||||
"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db"
|
||||
"checksum quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e44651a0dc4cdd99f71c83b561e221f714912d11af1a4dff0631f923d53af035"
|
||||
"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5"
|
||||
"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c"
|
||||
"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
|
||||
@ -2413,7 +2394,7 @@ dependencies = [
|
||||
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
"checksum serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "9f301d728f2b94c9a7691c90f07b0b4e8a4517181d9461be94c04bddeb4bd850"
|
||||
"checksum serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)" = "adb6e51a6b3696b301bc221d785f898b4457c619b51d7ce195a6d20baecb37b3"
|
||||
"checksum serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "beed18e6f5175aef3ba670e57c60ef3b1b74d250d962a26604bff4c80e970dd4"
|
||||
"checksum serde_derive 1.0.88 (git+https://github.com/servo/serde?branch=deserialize_from_enums10)" = "<none>"
|
||||
"checksum serde_json 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "f3ad6d546e765177cf3dded3c2e424a8040f870083a0e64064746b958ece9cb1"
|
||||
"checksum servo-fontconfig 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a088f8d775a5c5314aae09bd77340bc9c67d72b9a45258be34c83548b4814cd9"
|
||||
"checksum servo-fontconfig-sys 4.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "38b494f03009ee81914b0e7d387ad7c145cafcd69747c2ec89b0e17bb94f303a"
|
||||
|
@ -13,3 +13,6 @@ panic = "abort"
|
||||
|
||||
[profile.dev]
|
||||
panic = "abort"
|
||||
|
||||
[patch.crates-io]
|
||||
serde_derive = { git = "https://github.com/servo/serde", branch = "deserialize_from_enums10" }
|
||||
|
@ -1,15 +0,0 @@
|
||||
[package]
|
||||
name = "peek-poke"
|
||||
version = "0.2.0"
|
||||
authors = ["Dan Glastonbury <dan.glastonbury@gmail.com>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
euclid = { version = "0.19", optional = true }
|
||||
peek-poke-derive = { version = "0.2", path = "./peek-poke-derive", optional = true }
|
||||
|
||||
[features]
|
||||
default = ["derive"]
|
||||
derive = ["peek-poke-derive"]
|
||||
extras = ["derive", "euclid"]
|
@ -1,201 +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
|
||||
|
||||
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.
|
@ -1,44 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Daniel Glastonbury
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
This work incorporates work covered by the following copyright and permission
|
||||
notice:
|
||||
|
||||
Copyright (c) 2019 Devashish Dixit
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -1,54 +0,0 @@
|
||||
# Peeks, Pokes, and Pointers
|
||||
|
||||
Peek from and poke structures into byte slices.
|
||||
|
||||
## Benchmark
|
||||
|
||||
Below are the benchmark results of comparison between `peek-poke` and `bincode` serializing and deserializing same `struct`:
|
||||
```
|
||||
struct MyPeekPokeStruct {
|
||||
a: u8,
|
||||
b: u16,
|
||||
c: MyPeekPokeEnum,
|
||||
d: Option<usize>,
|
||||
}
|
||||
|
||||
enum MyPeekPokeEnum {
|
||||
Variant1,
|
||||
Variant2(u16),
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
Benchmarking struct::serialize/peek_poke::poke_into: Collecting 100 samples in struct::serialize/peek_poke::poke_into
|
||||
time: [2.7267 ns 2.7321 ns 2.7380 ns]
|
||||
|
||||
Benchmarking struct::serialize/bincode::serialize: Collecting 100 samples in est struct::serialize/bincode::serialize
|
||||
time: [31.264 ns 31.326 ns 31.389 ns]
|
||||
|
||||
Benchmarking struct::deserialize/peek_poke::peek_from: Collecting 100 samples struct::deserialize/peek_poke::peek_from
|
||||
time: [5.3544 ns 5.3672 ns 5.3817 ns]
|
||||
|
||||
Benchmarking struct::deserialize/bincode::deserialize: Collecting 100 samples in struct::deserialize/bincode::deserialize
|
||||
time: [25.155 ns 26.439 ns 27.661 ns]
|
||||
```
|
||||
|
||||
You can run benchmarks by running following command:
|
||||
```
|
||||
cargo bench
|
||||
```
|
||||
|
||||
## License
|
||||
[license]: #license
|
||||
|
||||
Licensed under either of
|
||||
- Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
||||
- MIT license (http://opensource.org/licenses/MIT)
|
||||
|
||||
at your option.
|
||||
|
||||
see [LICENSE-APACHE](LICENSE-APACHE), [LICENSE-MIT](LICENSE-MIT) for details.
|
||||
|
||||
## Contribution
|
||||
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 about, without any additional terms or conditions.
|
@ -1,17 +0,0 @@
|
||||
[package]
|
||||
name = "peek-poke-derive"
|
||||
version = "0.2.0"
|
||||
authors = ["Dan Glastonbury <dan.glastonbury@gmail.com>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = "0.4"
|
||||
quote = "0.6"
|
||||
syn = "0.15"
|
||||
synstructure = "0.10"
|
||||
unicode-xid = "0.1"
|
@ -1,201 +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
|
||||
|
||||
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.
|
@ -1,44 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Daniel Glastonbury
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
This work incorporates work covered by the following copyright and permission
|
||||
notice:
|
||||
|
||||
Copyright (c) 2019 Devashish Dixit
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -1,54 +0,0 @@
|
||||
# Peeks, Pokes, and Pointers
|
||||
|
||||
Peek from and poke structures into byte slices.
|
||||
|
||||
## Benchmark
|
||||
|
||||
Below are the benchmark results of comparison between `peek-poke` and `bincode` serializing and deserializing same `struct`:
|
||||
```
|
||||
struct MyPeekPokeStruct {
|
||||
a: u8,
|
||||
b: u16,
|
||||
c: MyPeekPokeEnum,
|
||||
d: Option<usize>,
|
||||
}
|
||||
|
||||
enum MyPeekPokeEnum {
|
||||
Variant1,
|
||||
Variant2(u16),
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
Benchmarking struct::serialize/peek_poke::poke_into: Collecting 100 samples in struct::serialize/peek_poke::poke_into
|
||||
time: [2.7267 ns 2.7321 ns 2.7380 ns]
|
||||
|
||||
Benchmarking struct::serialize/bincode::serialize: Collecting 100 samples in est struct::serialize/bincode::serialize
|
||||
time: [31.264 ns 31.326 ns 31.389 ns]
|
||||
|
||||
Benchmarking struct::deserialize/peek_poke::peek_from: Collecting 100 samples struct::deserialize/peek_poke::peek_from
|
||||
time: [5.3544 ns 5.3672 ns 5.3817 ns]
|
||||
|
||||
Benchmarking struct::deserialize/bincode::deserialize: Collecting 100 samples in struct::deserialize/bincode::deserialize
|
||||
time: [25.155 ns 26.439 ns 27.661 ns]
|
||||
```
|
||||
|
||||
You can run benchmarks by running following command:
|
||||
```
|
||||
cargo bench
|
||||
```
|
||||
|
||||
## License
|
||||
[license]: #license
|
||||
|
||||
Licensed under either of
|
||||
- Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
||||
- MIT license (http://opensource.org/licenses/MIT)
|
||||
|
||||
at your option.
|
||||
|
||||
see [LICENSE-APACHE](LICENSE-APACHE), [LICENSE-MIT](LICENSE-MIT) for details.
|
||||
|
||||
## Contribution
|
||||
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 about, without any additional terms or conditions.
|
@ -1,259 +0,0 @@
|
||||
// Copyright 2019 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use quote::quote;
|
||||
use syn::{Ident, Index, TraitBound};
|
||||
use synstructure::{decl_derive, Structure, BindStyle, AddBounds};
|
||||
use unicode_xid::UnicodeXID;
|
||||
|
||||
// Internal method for sanitizing an identifier for hygiene purposes.
|
||||
fn sanitize_ident(s: &str) -> Ident {
|
||||
let mut res = String::with_capacity(s.len());
|
||||
for mut c in s.chars() {
|
||||
if !UnicodeXID::is_xid_continue(c) {
|
||||
c = '_'
|
||||
}
|
||||
// Deduplicate consecutive _ characters.
|
||||
if res.ends_with('_') && c == '_' {
|
||||
continue;
|
||||
}
|
||||
res.push(c);
|
||||
}
|
||||
Ident::new(&res, Span::call_site())
|
||||
}
|
||||
|
||||
/// Calculates size type for number of variants (used for enums)
|
||||
fn get_discriminant_size_type(len: usize) -> TokenStream {
|
||||
if len <= <u8>::max_value() as usize {
|
||||
quote! { u8 }
|
||||
} else if len <= <u16>::max_value() as usize {
|
||||
quote! { u16 }
|
||||
} else {
|
||||
quote! { u32 }
|
||||
}
|
||||
}
|
||||
|
||||
fn is_struct(s: &Structure) -> bool {
|
||||
// a single variant with no prefix is 'struct'
|
||||
match &s.variants()[..] {
|
||||
[v] if v.prefix.is_none() => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn derive_max_size(s: &Structure) -> TokenStream {
|
||||
let max_size = s.variants().iter().fold(quote!(0), |acc, vi| {
|
||||
let variant_size = vi.bindings().iter().fold(quote!(0), |acc, bi| {
|
||||
// compute size of each variant by summing the sizes of its bindings
|
||||
let ty = &bi.ast().ty;
|
||||
quote!(#acc + <#ty>::max_size())
|
||||
});
|
||||
|
||||
// find the maximum of each variant
|
||||
quote! {
|
||||
max(#acc, #variant_size)
|
||||
}
|
||||
});
|
||||
|
||||
let body = if is_struct(s) {
|
||||
max_size
|
||||
} else {
|
||||
let discriminant_size_type = get_discriminant_size_type(s.variants().len());
|
||||
quote! {
|
||||
#discriminant_size_type ::max_size() + #max_size
|
||||
}
|
||||
};
|
||||
|
||||
quote! {
|
||||
#[inline(always)]
|
||||
fn max_size() -> usize {
|
||||
use std::cmp::max;
|
||||
#body
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn derive_peek_from_for_enum(s: &mut Structure) -> TokenStream {
|
||||
assert!(!is_struct(s));
|
||||
s.bind_with(|_| BindStyle::Move);
|
||||
|
||||
let discriminant_size_type = get_discriminant_size_type(s.variants().len());
|
||||
let body = s
|
||||
.variants()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.fold(quote!(), |acc, (i, vi)| {
|
||||
let bindings = vi
|
||||
.bindings()
|
||||
.iter()
|
||||
.map(|bi| quote!(#bi))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let variant_pat = Index::from(i);
|
||||
let poke_exprs = bindings.iter().fold(quote!(), |acc, bi| {
|
||||
quote! {
|
||||
#acc
|
||||
let (#bi, bytes) = peek_poke::peek_from_default(bytes);
|
||||
}
|
||||
});
|
||||
let construct = vi.construct(|_, i| {
|
||||
let bi = &bindings[i];
|
||||
quote!(#bi)
|
||||
});
|
||||
|
||||
quote! {
|
||||
#acc
|
||||
#variant_pat => {
|
||||
#poke_exprs
|
||||
*output = #construct;
|
||||
bytes
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
quote! {
|
||||
#[inline(always)]
|
||||
unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
|
||||
let (variant, bytes) = peek_poke::peek_from_default::<#discriminant_size_type>(bytes);
|
||||
match variant {
|
||||
#body
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn derive_peek_from_for_struct(s: &mut Structure) -> TokenStream {
|
||||
assert!(is_struct(&s));
|
||||
|
||||
s.variants_mut()[0].bind_with(|_| BindStyle::RefMut);
|
||||
let pat = s.variants()[0].pat();
|
||||
let peek_exprs = s.variants()[0].bindings().iter().fold(quote!(), |acc, bi| {
|
||||
let ty = &bi.ast().ty;
|
||||
quote! {
|
||||
#acc
|
||||
let bytes = <#ty>::peek_from(bytes, #bi);
|
||||
}
|
||||
});
|
||||
|
||||
let body = quote! {
|
||||
#pat => {
|
||||
#peek_exprs
|
||||
bytes
|
||||
}
|
||||
};
|
||||
|
||||
quote! {
|
||||
#[inline(always)]
|
||||
unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
|
||||
match &mut (*output) {
|
||||
#body
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn derive_poke_into(s: &Structure) -> TokenStream {
|
||||
let is_struct = is_struct(&s);
|
||||
let discriminant_size_type = get_discriminant_size_type(s.variants().len());
|
||||
let body = s
|
||||
.variants()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.fold(quote!(), |acc, (i, vi)| {
|
||||
let init = if !is_struct {
|
||||
let index = Index::from(i);
|
||||
quote! {
|
||||
let bytes = #discriminant_size_type::poke_into(&#index, bytes);
|
||||
}
|
||||
} else {
|
||||
quote!()
|
||||
};
|
||||
let variant_pat = vi.pat();
|
||||
let poke_exprs = vi.bindings().iter().fold(init, |acc, bi| {
|
||||
quote! {
|
||||
#acc
|
||||
let bytes = #bi.poke_into(bytes);
|
||||
}
|
||||
});
|
||||
|
||||
quote! {
|
||||
#acc
|
||||
#variant_pat => {
|
||||
#poke_exprs
|
||||
bytes
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
quote! {
|
||||
#[inline(always)]
|
||||
unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
|
||||
match &*self {
|
||||
#body
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn peek_poke_derive(mut s: Structure) -> TokenStream {
|
||||
s.binding_name(|_, i| Ident::new(&format!("__self_{}", i), Span::call_site()));
|
||||
|
||||
let max_size_fn = derive_max_size(&s);
|
||||
let poke_into_fn = derive_poke_into(&s);
|
||||
let peek_from_fn = if is_struct(&s) {
|
||||
derive_peek_from_for_struct(&mut s)
|
||||
} else {
|
||||
derive_peek_from_for_enum(&mut s)
|
||||
};
|
||||
|
||||
let poke_impl = s.gen_impl(quote! {
|
||||
extern crate peek_poke;
|
||||
|
||||
gen unsafe impl peek_poke::Poke for @Self {
|
||||
#max_size_fn
|
||||
#poke_into_fn
|
||||
}
|
||||
});
|
||||
|
||||
// To implement `fn peek_from` we require that types implement `Default`
|
||||
// trait to create temporary values. This code does the addition all
|
||||
// manually until https://github.com/mystor/synstructure/issues/24 is fixed.
|
||||
let default_trait = syn::parse_str::<TraitBound>("::std::default::Default").unwrap();
|
||||
let peek_trait = syn::parse_str::<TraitBound>("peek_poke::Peek").unwrap();
|
||||
|
||||
let ast = s.ast();
|
||||
let name = &ast.ident;
|
||||
let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
|
||||
let mut where_clause = where_clause.cloned();
|
||||
s.add_trait_bounds(&default_trait, &mut where_clause, AddBounds::Generics);
|
||||
s.add_trait_bounds(&peek_trait, &mut where_clause, AddBounds::Generics);
|
||||
|
||||
let dummy_const: Ident = sanitize_ident(&format!("_DERIVE_peek_poke_Peek_FOR_{}", name));
|
||||
|
||||
let peek_impl = quote! {
|
||||
#[allow(non_upper_case_globals)]
|
||||
const #dummy_const: () = {
|
||||
extern crate peek_poke;
|
||||
|
||||
impl #impl_generics peek_poke::Peek for #name #ty_generics #where_clause {
|
||||
#peek_from_fn
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
quote! {
|
||||
#poke_impl
|
||||
#peek_impl
|
||||
}
|
||||
}
|
||||
|
||||
decl_derive!([PeekPoke] => peek_poke_derive);
|
@ -1,170 +0,0 @@
|
||||
// Copyright 2019 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use crate::{Peek, Poke};
|
||||
use euclid::{TypedPoint2D, TypedRect, TypedSideOffsets2D, TypedSize2D, TypedTransform3D, TypedVector2D};
|
||||
|
||||
unsafe impl<T: Poke, U> Poke for TypedPoint2D<T, U> {
|
||||
#[inline(always)]
|
||||
fn max_size() -> usize {
|
||||
2 * T::max_size()
|
||||
}
|
||||
#[inline(always)]
|
||||
unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
|
||||
let bytes = self.x.poke_into(bytes);
|
||||
let bytes = self.y.poke_into(bytes);
|
||||
bytes
|
||||
}
|
||||
}
|
||||
impl<T: Peek, U> Peek for TypedPoint2D<T, U> {
|
||||
#[inline(always)]
|
||||
unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
|
||||
let bytes = T::peek_from(bytes, &mut (*output).x);
|
||||
let bytes = T::peek_from(bytes, &mut (*output).y);
|
||||
bytes
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: Poke, U> Poke for TypedRect<T, U> {
|
||||
#[inline(always)]
|
||||
fn max_size() -> usize {
|
||||
TypedPoint2D::<T, U>::max_size() + TypedSize2D::<T, U>::max_size()
|
||||
}
|
||||
#[inline(always)]
|
||||
unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
|
||||
let bytes = self.origin.poke_into(bytes);
|
||||
let bytes = self.size.poke_into(bytes);
|
||||
bytes
|
||||
}
|
||||
}
|
||||
impl<T: Peek, U> Peek for TypedRect<T, U> {
|
||||
#[inline(always)]
|
||||
unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
|
||||
let bytes = TypedPoint2D::<T, U>::peek_from(bytes, &mut (*output).origin);
|
||||
let bytes = TypedSize2D::<T, U>::peek_from(bytes, &mut (*output).size);
|
||||
bytes
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: Poke, U> Poke for TypedSideOffsets2D<T, U> {
|
||||
#[inline(always)]
|
||||
fn max_size() -> usize {
|
||||
4 * T::max_size()
|
||||
}
|
||||
#[inline(always)]
|
||||
unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
|
||||
let bytes = self.top.poke_into(bytes);
|
||||
let bytes = self.right.poke_into(bytes);
|
||||
let bytes = self.bottom.poke_into(bytes);
|
||||
let bytes = self.left.poke_into(bytes);
|
||||
bytes
|
||||
}
|
||||
}
|
||||
impl<T: Peek, U> Peek for TypedSideOffsets2D<T, U> {
|
||||
#[inline(always)]
|
||||
unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
|
||||
let bytes = T::peek_from(bytes, &mut (*output).top);
|
||||
let bytes = T::peek_from(bytes, &mut (*output).right);
|
||||
let bytes = T::peek_from(bytes, &mut (*output).bottom);
|
||||
let bytes = T::peek_from(bytes, &mut (*output).left);
|
||||
bytes
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: Poke, U> Poke for TypedSize2D<T, U> {
|
||||
#[inline(always)]
|
||||
fn max_size() -> usize {
|
||||
2 * T::max_size()
|
||||
}
|
||||
#[inline(always)]
|
||||
unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
|
||||
let bytes = self.width.poke_into(bytes);
|
||||
let bytes = self.height.poke_into(bytes);
|
||||
bytes
|
||||
}
|
||||
}
|
||||
impl<T: Peek, U> Peek for TypedSize2D<T, U> {
|
||||
#[inline(always)]
|
||||
unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
|
||||
let bytes = T::peek_from(bytes, &mut (*output).width);
|
||||
let bytes = T::peek_from(bytes, &mut (*output).height);
|
||||
bytes
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: Poke, S, D> Poke for TypedTransform3D<T, S, D> {
|
||||
#[inline(always)]
|
||||
fn max_size() -> usize {
|
||||
16 * T::max_size()
|
||||
}
|
||||
#[inline(always)]
|
||||
unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
|
||||
let bytes = self.m11.poke_into(bytes);
|
||||
let bytes = self.m12.poke_into(bytes);
|
||||
let bytes = self.m13.poke_into(bytes);
|
||||
let bytes = self.m14.poke_into(bytes);
|
||||
let bytes = self.m21.poke_into(bytes);
|
||||
let bytes = self.m22.poke_into(bytes);
|
||||
let bytes = self.m23.poke_into(bytes);
|
||||
let bytes = self.m24.poke_into(bytes);
|
||||
let bytes = self.m31.poke_into(bytes);
|
||||
let bytes = self.m32.poke_into(bytes);
|
||||
let bytes = self.m33.poke_into(bytes);
|
||||
let bytes = self.m34.poke_into(bytes);
|
||||
let bytes = self.m41.poke_into(bytes);
|
||||
let bytes = self.m42.poke_into(bytes);
|
||||
let bytes = self.m43.poke_into(bytes);
|
||||
let bytes = self.m44.poke_into(bytes);
|
||||
bytes
|
||||
}
|
||||
}
|
||||
impl<T: Peek, S, D> Peek for TypedTransform3D<T, S, D> {
|
||||
#[inline(always)]
|
||||
unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
|
||||
let bytes = T::peek_from(bytes, &mut (*output).m11);
|
||||
let bytes = T::peek_from(bytes, &mut (*output).m12);
|
||||
let bytes = T::peek_from(bytes, &mut (*output).m13);
|
||||
let bytes = T::peek_from(bytes, &mut (*output).m14);
|
||||
let bytes = T::peek_from(bytes, &mut (*output).m21);
|
||||
let bytes = T::peek_from(bytes, &mut (*output).m22);
|
||||
let bytes = T::peek_from(bytes, &mut (*output).m23);
|
||||
let bytes = T::peek_from(bytes, &mut (*output).m24);
|
||||
let bytes = T::peek_from(bytes, &mut (*output).m31);
|
||||
let bytes = T::peek_from(bytes, &mut (*output).m32);
|
||||
let bytes = T::peek_from(bytes, &mut (*output).m33);
|
||||
let bytes = T::peek_from(bytes, &mut (*output).m34);
|
||||
let bytes = T::peek_from(bytes, &mut (*output).m41);
|
||||
let bytes = T::peek_from(bytes, &mut (*output).m42);
|
||||
let bytes = T::peek_from(bytes, &mut (*output).m43);
|
||||
let bytes = T::peek_from(bytes, &mut (*output).m44);
|
||||
bytes
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: Poke, U> Poke for TypedVector2D<T, U> {
|
||||
#[inline(always)]
|
||||
fn max_size() -> usize {
|
||||
2 * T::max_size()
|
||||
}
|
||||
#[inline(always)]
|
||||
unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
|
||||
let bytes = self.x.poke_into(bytes);
|
||||
let bytes = self.y.poke_into(bytes);
|
||||
bytes
|
||||
}
|
||||
}
|
||||
impl<T: Peek, U> Peek for TypedVector2D<T, U> {
|
||||
#[inline(always)]
|
||||
unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
|
||||
let bytes = T::peek_from(bytes, &mut (*output).x);
|
||||
let bytes = T::peek_from(bytes, &mut (*output).y);
|
||||
bytes
|
||||
}
|
||||
}
|
@ -1,427 +0,0 @@
|
||||
// Copyright 2019 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Fast binary serialization and deserialization for types with a known maximum size.
|
||||
//!
|
||||
//! ## Binary Encoding Scheme
|
||||
//!
|
||||
//! ## Usage
|
||||
//!
|
||||
//! ## Comparison to bincode
|
||||
|
||||
#[cfg(feature = "derive")]
|
||||
pub use peek_poke_derive::*;
|
||||
|
||||
use core::{marker::PhantomData, mem::size_of, slice};
|
||||
use crate::{slice_ext::*, vec_ext::*};
|
||||
|
||||
mod slice_ext;
|
||||
mod vec_ext;
|
||||
|
||||
union MaybeUninitShim<T: Copy> {
|
||||
uninit: (),
|
||||
init: T,
|
||||
}
|
||||
|
||||
/// Peek helper for constructing a `T` by `Copy`ing into an uninitialized stack
|
||||
/// allocation.
|
||||
pub unsafe fn peek_from_uninit<T: Copy + Peek>(bytes: *const u8) -> (T, *const u8) {
|
||||
let mut val = MaybeUninitShim { uninit: () };
|
||||
let bytes = <T>::peek_from(bytes, &mut val.init);
|
||||
(val.init, bytes)
|
||||
}
|
||||
|
||||
/// Peek helper for constructing a `T` by `Default` initialized stack
|
||||
/// allocation.
|
||||
pub unsafe fn peek_from_default<T: Default + Peek>(bytes: *const u8) -> (T, *const u8) {
|
||||
let mut val = T::default();
|
||||
let bytes = <T>::peek_from(bytes, &mut val);
|
||||
(val, bytes)
|
||||
}
|
||||
|
||||
/// Peek inplace a `T` from a slice of bytes, returning a slice of the remaining
|
||||
/// bytes. `src` must contain at least `T::max_size()` bytes.
|
||||
///
|
||||
/// [`ensure_red_zone`] can be used to add required padding.
|
||||
pub fn peek_from_slice<'a, T: Peek>(src: &'a [u8], dst: &mut T) -> &'a [u8] {
|
||||
unsafe {
|
||||
// If src.len() == T::max_size() then src is at the start of the red-zone.
|
||||
assert!(T::max_size() < src.len());
|
||||
let end_ptr = T::peek_from(src.as_ptr(), dst);
|
||||
let len = end_ptr as usize - src.as_ptr() as usize;
|
||||
// Did someone break the T::peek_from() can't read more than T::max_size()
|
||||
// bytes contract?
|
||||
assert!(len <= src.len());
|
||||
slice::from_raw_parts(end_ptr, src.len() - len)
|
||||
}
|
||||
}
|
||||
|
||||
/// Poke helper to insert a serialized version of `src` at the beginning for `dst`.
|
||||
pub fn poke_inplace_slice<T: Poke>(src: &T, dst: &mut [u8]) {
|
||||
assert!(T::max_size() <= dst.len());
|
||||
unsafe {
|
||||
src.poke_into(dst.as_mut_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
/// Poke helper to append a serialized version of `src` to the end of `dst`.
|
||||
pub fn poke_into_vec<T: Poke>(src: &T, dst: &mut Vec<u8>) {
|
||||
dst.reserve(T::max_size());
|
||||
unsafe {
|
||||
let ptr = dst.as_end_mut_ptr();
|
||||
let end_ptr = src.poke_into(ptr);
|
||||
dst.set_end_ptr(end_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Is returning the len of the iterator of any practical use?
|
||||
pub fn poke_extend_vec<I>(src: I, dst: &mut Vec<u8>) -> usize
|
||||
where
|
||||
I: ExactSizeIterator,
|
||||
I::Item: Poke,
|
||||
{
|
||||
let len = src.len();
|
||||
let max_size = len * I::Item::max_size();
|
||||
dst.reserve(max_size);
|
||||
unsafe {
|
||||
let ptr = dst.as_end_mut_ptr();
|
||||
// Guard against the possibility of a misbehaved implementation of
|
||||
// ExactSizeIterator by writing at most `len` items.
|
||||
let end_ptr = src.take(len).fold(ptr, |ptr, item| item.poke_into(ptr));
|
||||
dst.set_end_ptr(end_ptr);
|
||||
}
|
||||
|
||||
len
|
||||
}
|
||||
|
||||
/// Add `T::max_size()` "red zone" (padding of zeroes) to the end of the vec of
|
||||
/// `bytes`. This allows deserialization to assert that at least `T::max_size()`
|
||||
/// bytes exist at all times.
|
||||
pub fn ensure_red_zone<T: Poke>(bytes: &mut Vec<u8>) {
|
||||
bytes.reserve(T::max_size());
|
||||
unsafe {
|
||||
let end_ptr = bytes.as_end_mut_ptr();
|
||||
end_ptr.write_bytes(0, T::max_size());
|
||||
bytes.set_end_ptr(end_ptr.add(T::max_size()));
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn read_verbatim<T>(src: *const u8, dst: *mut T) -> *const u8 {
|
||||
*dst = (src as *const T).read_unaligned();
|
||||
src.add(size_of::<T>())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn write_verbatim<T>(src: T, dst: *mut u8) -> *mut u8 {
|
||||
(dst as *mut T).write_unaligned(src);
|
||||
dst.add(size_of::<T>())
|
||||
}
|
||||
|
||||
#[cfg(feature = "extras")]
|
||||
mod euclid;
|
||||
|
||||
/// A trait for values that provide serialization into buffers of bytes.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```no_run
|
||||
/// use peek_poke::Poke;
|
||||
///
|
||||
/// struct Bar {
|
||||
/// a: u32,
|
||||
/// b: u8,
|
||||
/// c: i16,
|
||||
/// }
|
||||
///
|
||||
/// unsafe impl Poke for Bar {
|
||||
/// fn max_size() -> usize {
|
||||
/// <u32>::max_size() + <u8>::max_size() + <i16>::max_size()
|
||||
/// }
|
||||
/// unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
|
||||
/// let bytes = self.a.poke_into(bytes);
|
||||
/// let bytes = self.b.poke_into(bytes);
|
||||
/// self.c.poke_into(bytes)
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The `Poke` trait is an `unsafe` trait for the reasons, and implementors must
|
||||
/// ensure that they adhere to these contracts:
|
||||
///
|
||||
/// * `max_size()` query and calculations in general must be correct. Callers
|
||||
/// of this trait are expected to rely on the contract defined on each
|
||||
/// method, and implementors must ensure such contracts remain true.
|
||||
pub unsafe trait Poke {
|
||||
/// Return the maximum number of bytes that the serialized version of `Self`
|
||||
/// will occupy.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Implementors of `Poke` guarantee to not write more than the result of
|
||||
/// calling `max_size()` into the buffer pointed to by `bytes` when
|
||||
/// `poke_into()` is called.
|
||||
fn max_size() -> usize;
|
||||
/// Serialize into the buffer pointed to by `bytes`.
|
||||
///
|
||||
/// Returns a pointer to the next byte after the serialized representation of `Self`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is unsafe because undefined behavior can result if the
|
||||
/// caller does not ensure all of the following:
|
||||
///
|
||||
/// * `bytes` must denote a valid pointer to a block of memory.
|
||||
///
|
||||
/// * `bytes` must pointer to at least the number of bytes returned by
|
||||
/// `max_size()`.
|
||||
unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8;
|
||||
}
|
||||
|
||||
/// A trait for values that provide deserialization from buffers of bytes.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```ignore
|
||||
/// use peek_poke::Peek;
|
||||
///
|
||||
/// struct Bar {
|
||||
/// a: u32,
|
||||
/// b: u8,
|
||||
/// c: i16,
|
||||
/// }
|
||||
///
|
||||
/// ...
|
||||
///
|
||||
/// impl Peek for Bar {
|
||||
/// unsafe fn peek_from(&mut self, bytes: *const u8) -> *const u8 {
|
||||
/// let bytes = self.a.peek_from(bytes);
|
||||
/// let bytes = self.b.peek_from(bytes);
|
||||
/// self.c.peek_from(bytes)
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The `Peek` trait contains unsafe methods for the following reasons, and
|
||||
/// implementors must ensure that they adhere to these contracts:
|
||||
///
|
||||
/// * Callers of this trait are expected to rely on the contract defined on each
|
||||
/// method, and implementors must ensure that `peek_from()` doesn't read more
|
||||
/// bytes from `bytes` than is returned by `Peek::max_size()`.
|
||||
pub trait Peek: Poke {
|
||||
/// Deserialize from the buffer pointed to by `bytes`.
|
||||
///
|
||||
/// Returns a pointer to the next byte after the unconsumed bytes not used
|
||||
/// to deserialize the representation of `Self`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is unsafe because undefined behavior can result if the
|
||||
/// caller does not ensure all of the following:
|
||||
///
|
||||
/// * `bytes` must denote a valid pointer to a block of memory.
|
||||
///
|
||||
/// * `bytes` must pointer to at least the number of bytes returned by
|
||||
/// `Poke::max_size()`.
|
||||
unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8;
|
||||
}
|
||||
|
||||
macro_rules! impl_poke_for_deref {
|
||||
(<$($desc:tt)+) => {
|
||||
unsafe impl <$($desc)+ {
|
||||
#[inline(always)]
|
||||
fn max_size() -> usize {
|
||||
<T>::max_size()
|
||||
}
|
||||
unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
|
||||
(**self).poke_into(bytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_poke_for_deref!(<'a, T: Poke> Poke for &'a T);
|
||||
impl_poke_for_deref!(<'a, T: Poke> Poke for &'a mut T);
|
||||
|
||||
macro_rules! impl_for_primitive {
|
||||
($($ty:ty)+) => {
|
||||
$(unsafe impl Poke for $ty {
|
||||
#[inline(always)]
|
||||
fn max_size() -> usize {
|
||||
size_of::<Self>()
|
||||
}
|
||||
#[inline(always)]
|
||||
unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
|
||||
write_verbatim(*self, bytes)
|
||||
}
|
||||
}
|
||||
impl Peek for $ty {
|
||||
#[inline(always)]
|
||||
unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
|
||||
read_verbatim(bytes, output)
|
||||
}
|
||||
})+
|
||||
};
|
||||
}
|
||||
|
||||
impl_for_primitive! {
|
||||
i8 i16 i32 i64 isize
|
||||
u8 u16 u32 u64 usize
|
||||
f32 f64
|
||||
}
|
||||
|
||||
unsafe impl Poke for bool {
|
||||
#[inline(always)]
|
||||
fn max_size() -> usize {
|
||||
u8::max_size()
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
|
||||
(*self as u8).poke_into(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl Peek for bool {
|
||||
#[inline]
|
||||
unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
|
||||
let mut int_bool = 0u8;
|
||||
let ptr = <u8>::peek_from(bytes, &mut int_bool);
|
||||
*output = int_bool != 0;
|
||||
ptr
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T> Poke for PhantomData<T> {
|
||||
#[inline(always)]
|
||||
fn max_size() -> usize {
|
||||
0
|
||||
}
|
||||
#[inline(always)]
|
||||
unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
|
||||
bytes
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Peek for PhantomData<T> {
|
||||
#[inline(always)]
|
||||
unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
|
||||
*output = PhantomData;
|
||||
bytes
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: Poke> Poke for Option<T> {
|
||||
#[inline(always)]
|
||||
fn max_size() -> usize {
|
||||
u8::max_size() + T::max_size()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
|
||||
match self {
|
||||
None => 0u8.poke_into(bytes),
|
||||
Some(ref v) => {
|
||||
let bytes = 1u8.poke_into(bytes);
|
||||
let bytes = v.poke_into(bytes);
|
||||
bytes
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default + Peek> Peek for Option<T> {
|
||||
#[inline]
|
||||
unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
|
||||
let (variant, bytes) = peek_from_default::<u8>(bytes);
|
||||
match variant {
|
||||
0 => {
|
||||
*output = None;
|
||||
bytes
|
||||
}
|
||||
1 => {
|
||||
let (val, bytes) = peek_from_default(bytes);
|
||||
*output = Some(val);
|
||||
bytes
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_for_arrays {
|
||||
($($len:tt)+) => {
|
||||
$(unsafe impl<T: Poke> Poke for [T; $len] {
|
||||
fn max_size() -> usize {
|
||||
$len * T::max_size()
|
||||
}
|
||||
unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
|
||||
self.iter().fold(bytes, |bytes, e| e.poke_into(bytes))
|
||||
}
|
||||
}
|
||||
impl<T: Peek> Peek for [T; $len] {
|
||||
unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
|
||||
(&mut *output).iter_mut().fold(bytes, |bytes, e| <T>::peek_from(bytes, e))
|
||||
}
|
||||
})+
|
||||
}
|
||||
}
|
||||
|
||||
impl_for_arrays! {
|
||||
01 02 03 04 05 06 07 08 09 10
|
||||
11 12 13 14 15 16 17 18 19 20
|
||||
21 22 23 24 25 26 27 28 29 30
|
||||
31 32
|
||||
}
|
||||
|
||||
unsafe impl Poke for () {
|
||||
fn max_size() -> usize {
|
||||
0
|
||||
}
|
||||
unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
|
||||
bytes
|
||||
}
|
||||
}
|
||||
impl Peek for () {
|
||||
unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
|
||||
*output = ();
|
||||
bytes
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_for_tuple {
|
||||
($($n:tt: $ty:ident),+) => {
|
||||
unsafe impl<$($ty: Poke),+> Poke for ($($ty,)+) {
|
||||
#[inline(always)]
|
||||
fn max_size() -> usize {
|
||||
0 $(+ <$ty>::max_size())+
|
||||
}
|
||||
unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
|
||||
$(let bytes = self.$n.poke_into(bytes);)+
|
||||
bytes
|
||||
}
|
||||
}
|
||||
impl<$($ty: Peek),+> Peek for ($($ty,)+) {
|
||||
unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
|
||||
$(let bytes = $ty::peek_from(bytes, &mut (*output).$n);)+
|
||||
bytes
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_for_tuple!(0: A);
|
||||
impl_for_tuple!(0: A, 1: B);
|
||||
impl_for_tuple!(0: A, 1: B, 2: C);
|
||||
impl_for_tuple!(0: A, 1: B, 2: C, 3: D);
|
||||
impl_for_tuple!(0: A, 1: B, 2: C, 3: D, 4: E);
|
@ -1,19 +0,0 @@
|
||||
// Copyright 2019 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
pub trait AsEndMutPtr<T> {
|
||||
fn as_end_mut_ptr(self) -> *mut T;
|
||||
}
|
||||
|
||||
impl<'a> AsEndMutPtr<u8> for &'a mut [u8] {
|
||||
fn as_end_mut_ptr(self) -> *mut u8 {
|
||||
unsafe { self.as_mut_ptr().add(self.len()) }
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
// Copyright 2019 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::vec::Vec;
|
||||
|
||||
pub trait VecExt {
|
||||
type Item;
|
||||
unsafe fn set_end_ptr(&mut self, end: *const Self::Item);
|
||||
}
|
||||
|
||||
impl<T> VecExt for Vec<T> {
|
||||
type Item = T;
|
||||
unsafe fn set_end_ptr(&mut self, end: *const T) {
|
||||
assert!(end as usize >= self.as_ptr() as usize);
|
||||
let new_len = end as usize - self.as_ptr() as usize;
|
||||
assert!(new_len <= self.capacity());
|
||||
self.set_len(new_len);
|
||||
}
|
||||
}
|
@ -1,117 +0,0 @@
|
||||
// Copyright 2019 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
use peek_poke::{PeekPoke, Poke};
|
||||
use std::{marker::PhantomData, mem::size_of};
|
||||
|
||||
#[test]
|
||||
fn test_numbers() {
|
||||
assert_eq!(u8::max_size(), size_of::<u8>());
|
||||
assert_eq!(u16::max_size(), size_of::<u16>());
|
||||
assert_eq!(u32::max_size(), size_of::<u32>());
|
||||
assert_eq!(u64::max_size(), size_of::<u64>());
|
||||
assert_eq!(usize::max_size(), size_of::<usize>());
|
||||
assert_eq!(i8::max_size(), size_of::<i8>());
|
||||
assert_eq!(i16::max_size(), size_of::<i16>());
|
||||
assert_eq!(i32::max_size(), size_of::<i32>());
|
||||
assert_eq!(i64::max_size(), size_of::<i64>());
|
||||
assert_eq!(isize::max_size(), size_of::<isize>());
|
||||
// floating
|
||||
assert_eq!(f32::max_size(), size_of::<f32>());
|
||||
assert_eq!(f64::max_size(), size_of::<f64>());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bool() {
|
||||
assert_eq!(bool::max_size(), size_of::<u8>());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_option() {
|
||||
assert_eq!(
|
||||
Option::<usize>::max_size(),
|
||||
<u8>::max_size() + <usize>::max_size()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fixed_size_array() {
|
||||
assert_eq!(<[u32; 32]>::max_size(), 32 * size_of::<u32>());
|
||||
assert_eq!(<[u64; 8]>::max_size(), 8 * size_of::<u64>());
|
||||
assert_eq!(<[u8; 19]>::max_size(), 19 * size_of::<u8>());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tuple() {
|
||||
assert_eq!(<(isize)>::max_size(), size_of::<isize>());
|
||||
assert_eq!(<(isize, isize, isize)>::max_size(), 3 * size_of::<isize>());
|
||||
assert_eq!(<(isize, ())>::max_size(), size_of::<isize>());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_basic_struct() {
|
||||
#[derive(Debug, PeekPoke)]
|
||||
struct Bar {
|
||||
a: u32,
|
||||
b: u32,
|
||||
c: u32,
|
||||
}
|
||||
|
||||
assert_eq!(<Bar>::max_size(), 3 * <u32>::max_size());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_enum() {
|
||||
#[derive(Clone, Copy, PeekPoke)]
|
||||
enum TestEnum {
|
||||
NoArg,
|
||||
OneArg(usize),
|
||||
Args(usize, usize),
|
||||
AnotherNoArg,
|
||||
StructLike { x: usize, y: f32 },
|
||||
}
|
||||
assert_eq!(
|
||||
TestEnum::max_size(),
|
||||
<u8>::max_size() + 2 * <usize>::max_size()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_enum_cstyle() {
|
||||
#[repr(u32)]
|
||||
#[derive(Clone, Copy, PeekPoke)]
|
||||
enum BorderStyle {
|
||||
None = 0,
|
||||
Solid = 1,
|
||||
Double = 2,
|
||||
Dotted = 3,
|
||||
Dashed = 4,
|
||||
Hidden = 5,
|
||||
Groove = 6,
|
||||
Ridge = 7,
|
||||
Inset = 8,
|
||||
Outset = 9,
|
||||
}
|
||||
assert_eq!(BorderStyle::max_size(), <u8>::max_size());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_phantom_data() {
|
||||
struct Bar;
|
||||
#[derive(PeekPoke)]
|
||||
struct Foo {
|
||||
x: u32,
|
||||
y: u32,
|
||||
_marker: PhantomData<Bar>,
|
||||
}
|
||||
assert_eq!(Foo::max_size(), 2 * size_of::<u32>())
|
||||
}
|
@ -1,275 +0,0 @@
|
||||
// Copyright 2019 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use peek_poke::{Peek, PeekPoke, Poke};
|
||||
use std::{fmt::Debug, marker::PhantomData};
|
||||
|
||||
fn poke_into<V: Peek + Poke>(a: &V) -> Vec<u8> {
|
||||
let mut v = <Vec<u8>>::with_capacity(<V>::max_size());
|
||||
let end_ptr = unsafe { a.poke_into(v.as_mut_ptr()) };
|
||||
let new_size = end_ptr as usize - v.as_ptr() as usize;
|
||||
assert!(new_size <= v.capacity());
|
||||
unsafe {
|
||||
v.set_len(new_size);
|
||||
}
|
||||
v
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "option_copy"))]
|
||||
fn the_same<V>(a: V)
|
||||
where
|
||||
V: Debug + Default + PartialEq + Peek + Poke,
|
||||
{
|
||||
let v = poke_into(&a);
|
||||
let (b, end_ptr) = unsafe { peek_poke::peek_from_default(v.as_ptr()) };
|
||||
let size = end_ptr as usize - v.as_ptr() as usize;
|
||||
assert_eq!(size, v.len());
|
||||
assert_eq!(a, b);
|
||||
}
|
||||
|
||||
#[cfg(feature = "option_copy")]
|
||||
fn the_same<V>(a: V)
|
||||
where
|
||||
V: Copy + Debug + PartialEq + Peek + Poke,
|
||||
{
|
||||
let v = poke_into(&a);
|
||||
let mut b = a;
|
||||
let end_ptr = unsafe { b.peek_from(v.as_ptr()) };
|
||||
let size = end_ptr as usize - v.as_ptr() as usize;
|
||||
assert_eq!(size, v.len());
|
||||
assert_eq!(a, b);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_numbers() {
|
||||
// unsigned positive
|
||||
the_same(5u8);
|
||||
the_same(5u16);
|
||||
the_same(5u32);
|
||||
the_same(5u64);
|
||||
the_same(5usize);
|
||||
// signed positive
|
||||
the_same(5i8);
|
||||
the_same(5i16);
|
||||
the_same(5i32);
|
||||
the_same(5i64);
|
||||
the_same(5isize);
|
||||
// signed negative
|
||||
the_same(-5i8);
|
||||
the_same(-5i16);
|
||||
the_same(-5i32);
|
||||
the_same(-5i64);
|
||||
the_same(-5isize);
|
||||
// floating
|
||||
the_same(-100f32);
|
||||
the_same(0f32);
|
||||
the_same(5f32);
|
||||
the_same(-100f64);
|
||||
the_same(5f64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bool() {
|
||||
the_same(true);
|
||||
the_same(false);
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "option_copy", feature = "option_default"))]
|
||||
#[test]
|
||||
fn test_option() {
|
||||
the_same(Some(5usize));
|
||||
//the_same(Some("foo bar".to_string()));
|
||||
the_same(None::<usize>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fixed_size_array() {
|
||||
the_same([24u32; 32]);
|
||||
the_same([1u64, 2, 3, 4, 5, 6, 7, 8]);
|
||||
the_same([0u8; 19]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tuple() {
|
||||
the_same((1isize, ));
|
||||
the_same((1isize, 2isize, 3isize));
|
||||
the_same((1isize, ()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_basic_struct() {
|
||||
#[derive(Copy, Clone, Debug, Default, PartialEq, PeekPoke)]
|
||||
struct Bar {
|
||||
a: u32,
|
||||
b: u32,
|
||||
c: u32,
|
||||
#[cfg(any(feature = "option_copy", feature = "option_default"))]
|
||||
d: Option<u32>,
|
||||
}
|
||||
|
||||
the_same(Bar {
|
||||
a: 2,
|
||||
b: 4,
|
||||
c: 42,
|
||||
#[cfg(any(feature = "option_copy", feature = "option_default"))]
|
||||
d: None,
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_enum() {
|
||||
#[derive(Clone, Copy, Debug, PartialEq, PeekPoke)]
|
||||
enum TestEnum {
|
||||
NoArg,
|
||||
OneArg(usize),
|
||||
Args(usize, usize),
|
||||
AnotherNoArg,
|
||||
StructLike { x: usize, y: f32 },
|
||||
}
|
||||
|
||||
impl Default for TestEnum {
|
||||
fn default() -> Self {
|
||||
TestEnum::NoArg
|
||||
}
|
||||
}
|
||||
|
||||
the_same(TestEnum::NoArg);
|
||||
the_same(TestEnum::OneArg(4));
|
||||
the_same(TestEnum::Args(4, 5));
|
||||
the_same(TestEnum::AnotherNoArg);
|
||||
the_same(TestEnum::StructLike { x: 4, y: 3.14159 });
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_enum_cstyle() {
|
||||
#[repr(u32)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PeekPoke)]
|
||||
enum BorderStyle {
|
||||
None = 0,
|
||||
Solid = 1,
|
||||
Double = 2,
|
||||
Dotted = 3,
|
||||
Dashed = 4,
|
||||
Hidden = 5,
|
||||
Groove = 6,
|
||||
Ridge = 7,
|
||||
Inset = 8,
|
||||
Outset = 9,
|
||||
}
|
||||
|
||||
impl Default for BorderStyle {
|
||||
fn default() -> Self {
|
||||
BorderStyle::None
|
||||
}
|
||||
}
|
||||
|
||||
the_same(BorderStyle::None);
|
||||
the_same(BorderStyle::Solid);
|
||||
the_same(BorderStyle::Double);
|
||||
the_same(BorderStyle::Dotted);
|
||||
the_same(BorderStyle::Dashed);
|
||||
the_same(BorderStyle::Hidden);
|
||||
the_same(BorderStyle::Groove);
|
||||
the_same(BorderStyle::Ridge);
|
||||
the_same(BorderStyle::Inset);
|
||||
the_same(BorderStyle::Outset);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_phantom_data() {
|
||||
struct Bar;
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PeekPoke)]
|
||||
struct Foo {
|
||||
x: u32,
|
||||
y: u32,
|
||||
_marker: PhantomData<Bar>,
|
||||
}
|
||||
the_same(Foo {
|
||||
x: 19,
|
||||
y: 42,
|
||||
_marker: PhantomData,
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generic() {
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PeekPoke)]
|
||||
struct Foo<T> {
|
||||
x: T,
|
||||
y: T,
|
||||
}
|
||||
the_same(Foo { x: 19.0, y: 42.0 });
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generic_enum() {
|
||||
#[derive(Clone, Copy, Debug, PartialEq, PeekPoke)]
|
||||
pub struct PropertyBindingKey<T> {
|
||||
pub id: usize,
|
||||
_phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, PeekPoke)]
|
||||
pub enum PropertyBinding<T> {
|
||||
Value(T),
|
||||
Binding(PropertyBindingKey<T>, T),
|
||||
}
|
||||
|
||||
impl<T: Default> Default for PropertyBinding<T> {
|
||||
fn default() -> Self {
|
||||
PropertyBinding::Value(Default::default())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "extras", feature = "option_copy"))]
|
||||
mod extra_tests {
|
||||
use super::*;
|
||||
use euclid::{Point2D, Rect, SideOffsets2D, Size2D, Transform3D, Vector2D};
|
||||
use std::mem::size_of;
|
||||
|
||||
#[test]
|
||||
fn euclid_types() {
|
||||
the_same(Point2D::<f32>::new(1.0, 2.0));
|
||||
assert_eq!(Point2D::<f32>::max_size(), 2 * size_of::<f32>());
|
||||
|
||||
the_same(Rect::<f32>::new(
|
||||
Point2D::<f32>::new(0.0, 0.0),
|
||||
Size2D::<f32>::new(100.0, 80.0),
|
||||
));
|
||||
assert_eq!(Rect::<f32>::max_size(), 4 * size_of::<f32>());
|
||||
|
||||
the_same(SideOffsets2D::<f32>::new(0.0, 10.0, -1.0, -10.0));
|
||||
assert_eq!(SideOffsets2D::<f32>::max_size(), 4 * size_of::<f32>());
|
||||
|
||||
the_same(Transform3D::<f32>::identity());
|
||||
assert_eq!(Transform3D::<f32>::max_size(), 16 * size_of::<f32>());
|
||||
|
||||
the_same(Vector2D::<f32>::new(1.0, 2.0));
|
||||
assert_eq!(Vector2D::<f32>::max_size(), 2 * size_of::<f32>());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn webrender_api_types() {
|
||||
type PipelineSourceId = i32;
|
||||
#[derive(Clone, Copy, Debug, PartialEq, PeekPoke)]
|
||||
struct PipelineId(pub PipelineSourceId, pub u32);
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, PeekPoke)]
|
||||
struct ClipChainId(pub u64, pub PipelineId);
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, PeekPoke)]
|
||||
struct SpatialId(pub usize, pub PipelineId);
|
||||
|
||||
the_same(PipelineId(42, 2));
|
||||
the_same(ClipChainId(19u64, PipelineId(42, 2)));
|
||||
the_same(SpatialId(19usize, PipelineId(42, 2)));
|
||||
}
|
||||
}
|
@ -16,18 +16,18 @@ display_list_stats = []
|
||||
|
||||
[dependencies]
|
||||
app_units = "0.7"
|
||||
bincode = "1.0"
|
||||
bitflags = "1.0"
|
||||
byteorder = "1.2.1"
|
||||
derive_more = "0.13"
|
||||
ipc-channel = {version = "0.11.0", optional = true}
|
||||
euclid = { version = "0.19.9", features = ["serde"] }
|
||||
euclid = { version = "0.19.5", features = ["serde"] }
|
||||
malloc_size_of_derive = "0.1"
|
||||
serde = { version = "=1.0.88", features = ["rc"] }
|
||||
serde_derive = "=1.0.88"
|
||||
serde_derive = { version = "=1.0.88", features = ["deserialize_in_place"] }
|
||||
serde_bytes = "0.10"
|
||||
time = "0.1"
|
||||
malloc_size_of = { version = "0.0.1", path = "../wr_malloc_size_of", package = "wr_malloc_size_of" }
|
||||
peek-poke = { version = "0.2", path = "../peek-poke", features = ["extras"] }
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
core-foundation = "0.6"
|
||||
|
@ -5,7 +5,6 @@
|
||||
extern crate serde_bytes;
|
||||
|
||||
use crate::channel::{self, MsgSender, Payload, PayloadSender, PayloadSenderHelperMethods};
|
||||
use peek_poke::PeekPoke;
|
||||
use std::cell::Cell;
|
||||
use std::fmt;
|
||||
use std::marker::PhantomData;
|
||||
@ -796,12 +795,11 @@ impl Epoch {
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, MallocSizeOf, PartialEq, Hash, Ord, PartialOrd, PeekPoke)]
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize)]
|
||||
pub struct IdNamespace(pub u32);
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
|
||||
pub struct DocumentId {
|
||||
pub namespace_id: IdNamespace,
|
||||
pub id: u32,
|
||||
@ -827,15 +825,9 @@ pub type PipelineSourceId = u32;
|
||||
/// From the point of view of WR, `PipelineId` is completely opaque and generic as long as
|
||||
/// it's clonable, serializable, comparable, and hashable.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
|
||||
pub struct PipelineId(pub PipelineSourceId, pub u32);
|
||||
|
||||
impl Default for PipelineId {
|
||||
fn default() -> Self {
|
||||
PipelineId::dummy()
|
||||
}
|
||||
}
|
||||
|
||||
impl PipelineId {
|
||||
pub fn dummy() -> Self {
|
||||
PipelineId(0, 0)
|
||||
@ -1424,7 +1416,7 @@ impl ZoomFactor {
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash)]
|
||||
pub struct PropertyBindingId {
|
||||
namespace: IdNamespace,
|
||||
uid: u32,
|
||||
@ -1442,7 +1434,7 @@ impl PropertyBindingId {
|
||||
/// A unique key that is used for connecting animated property
|
||||
/// values to bindings in the display list.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct PropertyBindingKey<T> {
|
||||
pub id: PropertyBindingId,
|
||||
_phantom: PhantomData<T>,
|
||||
@ -1471,18 +1463,12 @@ impl<T> PropertyBindingKey<T> {
|
||||
/// used for the case where the animation is still in-delay phase
|
||||
/// (i.e. the animation doesn't produce any animation values).
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub enum PropertyBinding<T> {
|
||||
Value(T),
|
||||
Binding(PropertyBindingKey<T>, T),
|
||||
}
|
||||
|
||||
impl<T: Default> Default for PropertyBinding<T> {
|
||||
fn default() -> Self {
|
||||
PropertyBinding::Value(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for PropertyBinding<T> {
|
||||
fn from(value: T) -> PropertyBinding<T> {
|
||||
PropertyBinding::Value(value)
|
||||
|
@ -2,7 +2,6 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use peek_poke::PeekPoke;
|
||||
use std::cmp;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
@ -38,7 +37,7 @@ impl PremultipliedColorF {
|
||||
/// All components must be between 0.0 and 1.0.
|
||||
/// An alpha value of 1.0 is opaque while 0.0 is fully transparent.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
|
||||
pub struct ColorF {
|
||||
pub r: f32,
|
||||
pub g: f32,
|
||||
|
@ -3,7 +3,6 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use euclid::SideOffsets2D;
|
||||
use peek_poke::PeekPoke;
|
||||
use std::ops::Not;
|
||||
// local imports
|
||||
use crate::font;
|
||||
@ -35,7 +34,7 @@ pub type ItemTag = (u64, u16);
|
||||
|
||||
/// A grouping of fields a lot of display items need, just to avoid
|
||||
/// repeating these over and over in this file.
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct CommonItemProperties {
|
||||
/// Bounds of the display item to clip to. Many items are logically
|
||||
/// infinite, and rely on this clip_rect to define their bounds
|
||||
@ -72,7 +71,7 @@ impl CommonItemProperties {
|
||||
/// Note: this is a separate struct from `PrimitiveInfo` because
|
||||
/// it needs indirectional mapping during the DL flattening phase,
|
||||
/// turning into `ScrollNodeAndClipChain`.
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct SpaceAndClipInfo {
|
||||
pub spatial_id: SpatialId,
|
||||
pub clip_id: ClipId,
|
||||
@ -90,7 +89,7 @@ impl SpaceAndClipInfo {
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub enum DisplayItem {
|
||||
// These are the "real content" display items
|
||||
Rectangle(RectangleDisplayItem),
|
||||
@ -168,7 +167,7 @@ pub enum DebugDisplayItem {
|
||||
PopAllShadows,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct ClipDisplayItem {
|
||||
pub id: ClipId,
|
||||
pub parent_space_and_clip: SpaceAndClipInfo,
|
||||
@ -178,7 +177,7 @@ pub struct ClipDisplayItem {
|
||||
|
||||
/// The minimum and maximum allowable offset for a sticky frame in a single dimension.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct StickyOffsetBounds {
|
||||
/// The minimum offset for this frame, typically a negative value, which specifies how
|
||||
/// far in the negative direction the sticky frame can offset its contents in this
|
||||
@ -197,7 +196,7 @@ impl StickyOffsetBounds {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct StickyFrameDisplayItem {
|
||||
pub id: SpatialId,
|
||||
pub parent_spatial_id: SpatialId,
|
||||
@ -228,13 +227,13 @@ pub struct StickyFrameDisplayItem {
|
||||
pub previously_applied_offset: LayoutVector2D,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub enum ScrollSensitivity {
|
||||
ScriptAndInputEvents,
|
||||
Script,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct ScrollFrameDisplayItem {
|
||||
/// The id of the clip this scroll frame creates
|
||||
pub clip_id: ClipId,
|
||||
@ -257,7 +256,7 @@ pub struct ScrollFrameDisplayItem {
|
||||
}
|
||||
|
||||
/// A solid color to draw (may not actually be a rectangle due to complex clips)
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct RectangleDisplayItem {
|
||||
pub common: CommonItemProperties,
|
||||
pub color: ColorF,
|
||||
@ -265,7 +264,7 @@ pub struct RectangleDisplayItem {
|
||||
|
||||
/// Clears all colors from the area, making it possible to cut holes in the window.
|
||||
/// (useful for things like the macos frosted-glass effect).
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct ClearRectangleDisplayItem {
|
||||
pub common: CommonItemProperties,
|
||||
}
|
||||
@ -273,12 +272,12 @@ pub struct ClearRectangleDisplayItem {
|
||||
/// A minimal hit-testable item for the parent browser's convenience, and is
|
||||
/// slimmer than a RectangleDisplayItem (no color). The existence of this as a
|
||||
/// distinct item also makes it easier to inspect/debug display items.
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct HitTestDisplayItem {
|
||||
pub common: CommonItemProperties,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct LineDisplayItem {
|
||||
pub common: CommonItemProperties,
|
||||
/// We need a separate rect from common.clip_rect to encode cute
|
||||
@ -300,14 +299,14 @@ pub struct LineDisplayItem {
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash)]
|
||||
pub enum LineOrientation {
|
||||
Vertical,
|
||||
Horizontal,
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash)]
|
||||
pub enum LineStyle {
|
||||
Solid,
|
||||
Dotted,
|
||||
@ -315,7 +314,7 @@ pub enum LineStyle {
|
||||
Wavy,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct TextDisplayItem {
|
||||
pub common: CommonItemProperties,
|
||||
/// The area all the glyphs should be found in. Strictly speaking this isn't
|
||||
@ -331,7 +330,7 @@ pub struct TextDisplayItem {
|
||||
pub glyph_options: Option<font::GlyphOptions>,
|
||||
} // IMPLICIT: glyphs: Vec<font::GlyphInstance>
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
|
||||
pub struct NormalBorder {
|
||||
pub left: BorderSide,
|
||||
pub right: BorderSide,
|
||||
@ -390,7 +389,7 @@ impl NormalBorder {
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Copy, Clone, MallocSizeOf, PartialEq, Serialize, Deserialize, Eq, Hash, PeekPoke)]
|
||||
#[derive(Debug, Copy, Clone, MallocSizeOf, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub enum RepeatMode {
|
||||
Stretch,
|
||||
Repeat,
|
||||
@ -398,14 +397,14 @@ pub enum RepeatMode {
|
||||
Space,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub enum NinePatchBorderSource {
|
||||
Image(ImageKey),
|
||||
Gradient(Gradient),
|
||||
RadialGradient(RadialGradient),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct NinePatchBorder {
|
||||
/// Describes what to use as the 9-patch source image. If this is an image,
|
||||
/// it will be stretched to fill the size given by width x height.
|
||||
@ -443,13 +442,13 @@ pub struct NinePatchBorder {
|
||||
pub outset: SideOffsets2D<f32>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub enum BorderDetails {
|
||||
Normal(NormalBorder),
|
||||
NinePatch(NinePatchBorder),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct BorderDisplayItem {
|
||||
pub common: CommonItemProperties,
|
||||
pub bounds: LayoutRect,
|
||||
@ -458,14 +457,14 @@ pub struct BorderDisplayItem {
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub enum BorderRadiusKind {
|
||||
Uniform,
|
||||
NonUniform,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
|
||||
pub struct BorderRadius {
|
||||
pub top_left: LayoutSize,
|
||||
pub top_right: LayoutSize,
|
||||
@ -473,26 +472,15 @@ pub struct BorderRadius {
|
||||
pub bottom_right: LayoutSize,
|
||||
}
|
||||
|
||||
impl Default for BorderRadius {
|
||||
fn default() -> Self {
|
||||
BorderRadius {
|
||||
top_left: LayoutSize::zero(),
|
||||
top_right: LayoutSize::zero(),
|
||||
bottom_left: LayoutSize::zero(),
|
||||
bottom_right: LayoutSize::zero(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
|
||||
pub struct BorderSide {
|
||||
pub color: ColorF,
|
||||
pub style: BorderStyle,
|
||||
}
|
||||
|
||||
#[repr(u32)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Hash, Eq, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Hash, Eq)]
|
||||
pub enum BorderStyle {
|
||||
None = 0,
|
||||
Solid = 1,
|
||||
@ -513,13 +501,13 @@ impl BorderStyle {
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
|
||||
pub enum BoxShadowClipMode {
|
||||
Outset = 0,
|
||||
Inset = 1,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct BoxShadowDisplayItem {
|
||||
pub common: CommonItemProperties,
|
||||
pub box_bounds: LayoutRect,
|
||||
@ -531,7 +519,7 @@ pub struct BoxShadowDisplayItem {
|
||||
pub clip_mode: BoxShadowClipMode,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct PushShadowDisplayItem {
|
||||
pub space_and_clip: SpaceAndClipInfo,
|
||||
pub shadow: Shadow,
|
||||
@ -539,7 +527,7 @@ pub struct PushShadowDisplayItem {
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct Shadow {
|
||||
pub offset: LayoutVector2D,
|
||||
pub color: ColorF,
|
||||
@ -547,13 +535,13 @@ pub struct Shadow {
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Copy, Clone, Hash, Eq, MallocSizeOf, PartialEq, Serialize, Deserialize, Ord, PartialOrd, PeekPoke)]
|
||||
#[derive(Debug, Copy, Clone, Hash, Eq, MallocSizeOf, PartialEq, Serialize, Deserialize, Ord, PartialOrd)]
|
||||
pub enum ExtendMode {
|
||||
Clamp,
|
||||
Repeat,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct Gradient {
|
||||
pub start_point: LayoutPoint,
|
||||
pub end_point: LayoutPoint,
|
||||
@ -561,7 +549,7 @@ pub struct Gradient {
|
||||
} // IMPLICIT: stops: Vec<GradientStop>
|
||||
|
||||
/// The area
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct GradientDisplayItem {
|
||||
/// NOTE: common.clip_rect is the area the gradient covers
|
||||
pub common: CommonItemProperties,
|
||||
@ -577,13 +565,13 @@ pub struct GradientDisplayItem {
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
|
||||
pub struct GradientStop {
|
||||
pub offset: f32,
|
||||
pub color: ColorF,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct RadialGradient {
|
||||
pub center: LayoutPoint,
|
||||
pub radius: LayoutSize,
|
||||
@ -593,13 +581,13 @@ pub struct RadialGradient {
|
||||
} // IMPLICIT stops: Vec<GradientStop>
|
||||
|
||||
/// Just an abstraction for bundling up a bunch of clips into a "super clip".
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct ClipChainItem {
|
||||
pub id: ClipChainId,
|
||||
pub parent: Option<ClipChainId>,
|
||||
} // IMPLICIT clip_ids: Vec<ClipId>
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct RadialGradientDisplayItem {
|
||||
pub common: CommonItemProperties,
|
||||
/// The area to tile the gradient over (first tile starts at origin of this rect)
|
||||
@ -611,14 +599,14 @@ pub struct RadialGradientDisplayItem {
|
||||
pub tile_spacing: LayoutSize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct ReferenceFrameDisplayListItem {
|
||||
pub origin: LayoutPoint,
|
||||
pub parent_spatial_id: SpatialId,
|
||||
pub reference_frame: ReferenceFrame,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub enum ReferenceFrameKind {
|
||||
Transform,
|
||||
Perspective {
|
||||
@ -626,7 +614,7 @@ pub enum ReferenceFrameKind {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct ReferenceFrame {
|
||||
pub kind: ReferenceFrameKind,
|
||||
pub transform_style: TransformStyle,
|
||||
@ -636,7 +624,7 @@ pub struct ReferenceFrame {
|
||||
pub id: SpatialId,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct PushStackingContextDisplayItem {
|
||||
pub origin: LayoutPoint,
|
||||
pub spatial_id: SpatialId,
|
||||
@ -644,7 +632,7 @@ pub struct PushStackingContextDisplayItem {
|
||||
pub stacking_context: StackingContext,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct StackingContext {
|
||||
pub transform_style: TransformStyle,
|
||||
pub mix_blend_mode: MixBlendMode,
|
||||
@ -655,7 +643,7 @@ pub struct StackingContext {
|
||||
} // IMPLICIT: filters: Vec<FilterOp>, filter_datas: Vec<FilterData>, filter_primitives: Vec<FilterPrimitive>
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub enum TransformStyle {
|
||||
Flat = 0,
|
||||
Preserve3D = 1,
|
||||
@ -667,7 +655,7 @@ pub enum TransformStyle {
|
||||
/// when we want to cache the output, and performance is
|
||||
/// important. Note that this is a performance hint only,
|
||||
/// which WR may choose to ignore.
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
#[repr(u8)]
|
||||
pub enum RasterSpace {
|
||||
// Rasterize in local-space, applying supplied scale to primitives.
|
||||
@ -691,7 +679,7 @@ impl RasterSpace {
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
|
||||
pub enum MixBlendMode {
|
||||
Normal = 0,
|
||||
Multiply = 1,
|
||||
@ -713,14 +701,14 @@ pub enum MixBlendMode {
|
||||
|
||||
/// An input to a SVG filter primitive.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
|
||||
pub enum ColorSpace {
|
||||
Srgb,
|
||||
LinearRgb,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
|
||||
pub enum FilterPrimitiveInput {
|
||||
/// The input is the original graphic that the filter is being applied to.
|
||||
Original,
|
||||
@ -743,7 +731,7 @@ impl FilterPrimitiveInput {
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct BlendPrimitive {
|
||||
pub input1: FilterPrimitiveInput,
|
||||
pub input2: FilterPrimitiveInput,
|
||||
@ -751,7 +739,7 @@ pub struct BlendPrimitive {
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct FloodPrimitive {
|
||||
pub color: ColorF,
|
||||
}
|
||||
@ -766,7 +754,7 @@ impl FloodPrimitive {
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct BlurPrimitive {
|
||||
pub input: FilterPrimitiveInput,
|
||||
pub radius: f32,
|
||||
@ -779,7 +767,7 @@ impl BlurPrimitive {
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct OpacityPrimitive {
|
||||
pub input: FilterPrimitiveInput,
|
||||
pub opacity: f32,
|
||||
@ -793,14 +781,14 @@ impl OpacityPrimitive {
|
||||
|
||||
/// cbindgen:derive-eq=false
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct ColorMatrixPrimitive {
|
||||
pub input: FilterPrimitiveInput,
|
||||
pub matrix: [f32; 20],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct DropShadowPrimitive {
|
||||
pub input: FilterPrimitiveInput,
|
||||
pub shadow: Shadow,
|
||||
@ -813,14 +801,14 @@ impl DropShadowPrimitive {
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct ComponentTransferPrimitive {
|
||||
pub input: FilterPrimitiveInput,
|
||||
// Component transfer data is stored in FilterData.
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct IdentityPrimitive {
|
||||
pub input: FilterPrimitiveInput,
|
||||
}
|
||||
@ -828,7 +816,7 @@ pub struct IdentityPrimitive {
|
||||
/// See: https://github.com/eqrion/cbindgen/issues/9
|
||||
/// cbindgen:derive-eq=false
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub enum FilterPrimitiveKind {
|
||||
Identity(IdentityPrimitive),
|
||||
Blend(BlendPrimitive),
|
||||
@ -842,12 +830,6 @@ pub enum FilterPrimitiveKind {
|
||||
ComponentTransfer(ComponentTransferPrimitive),
|
||||
}
|
||||
|
||||
impl Default for FilterPrimitiveKind {
|
||||
fn default() -> Self {
|
||||
FilterPrimitiveKind::Identity(IdentityPrimitive::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl FilterPrimitiveKind {
|
||||
pub fn sanitize(&mut self) {
|
||||
match self {
|
||||
@ -870,7 +852,7 @@ impl FilterPrimitiveKind {
|
||||
/// See: https://github.com/eqrion/cbindgen/issues/9
|
||||
/// cbindgen:derive-eq=false
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct FilterPrimitive {
|
||||
pub kind: FilterPrimitiveKind,
|
||||
pub color_space: ColorSpace,
|
||||
@ -884,7 +866,7 @@ impl FilterPrimitive {
|
||||
|
||||
/// CSS filter.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
|
||||
pub enum FilterOp {
|
||||
/// Filter that does no transformation of the colors, needed for
|
||||
/// debug purposes only.
|
||||
@ -907,7 +889,7 @@ pub enum FilterOp {
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Deserialize, Serialize)]
|
||||
pub enum ComponentTransferFuncType {
|
||||
Identity = 0,
|
||||
Table = 1,
|
||||
@ -1003,7 +985,7 @@ impl FilterData {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct IframeDisplayItem {
|
||||
pub bounds: LayoutRect,
|
||||
pub clip_rect: LayoutRect,
|
||||
@ -1014,7 +996,7 @@ pub struct IframeDisplayItem {
|
||||
|
||||
/// This describes an image or, more generally, a background-image and its tiling.
|
||||
/// (A background-image repeats in a grid to fill the specified area).
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct ImageDisplayItem {
|
||||
pub common: CommonItemProperties,
|
||||
/// The area to tile the image over (first tile starts at origin of this rect)
|
||||
@ -1033,20 +1015,20 @@ pub struct ImageDisplayItem {
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
|
||||
pub enum ImageRendering {
|
||||
Auto = 0,
|
||||
CrispEdges = 1,
|
||||
Pixelated = 2,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
|
||||
pub enum AlphaType {
|
||||
Alpha = 0,
|
||||
PremultipliedAlpha = 1,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct YuvImageDisplayItem {
|
||||
pub common: CommonItemProperties,
|
||||
pub bounds: LayoutRect,
|
||||
@ -1057,14 +1039,14 @@ pub struct YuvImageDisplayItem {
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
|
||||
pub enum YuvColorSpace {
|
||||
Rec601 = 0,
|
||||
Rec709 = 1,
|
||||
Rec2020 = 2,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub enum YuvData {
|
||||
NV12(ImageKey, ImageKey), // (Y channel, CbCr interleaved channel)
|
||||
PlanarYCbCr(ImageKey, ImageKey, ImageKey), // (Y channel, Cb channel, Cr Channel)
|
||||
@ -1081,7 +1063,7 @@ impl YuvData {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
|
||||
pub enum YuvFormat {
|
||||
NV12 = 0,
|
||||
PlanarYCbCr = 1,
|
||||
@ -1099,7 +1081,7 @@ impl YuvFormat {
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct ImageMask {
|
||||
pub image: ImageKey,
|
||||
pub rect: LayoutRect,
|
||||
@ -1118,7 +1100,7 @@ impl ImageMask {
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, MallocSizeOf, PartialEq, Serialize, Deserialize, Eq, Hash, PeekPoke)]
|
||||
#[derive(Copy, Clone, Debug, MallocSizeOf, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub enum ClipMode {
|
||||
Clip, // Pixels inside the region are visible.
|
||||
ClipOut, // Pixels outside the region are visible.
|
||||
@ -1136,7 +1118,7 @@ impl Not for ClipMode {
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct ComplexClipRegion {
|
||||
/// The boundaries of the rectangle.
|
||||
pub rect: LayoutRect,
|
||||
@ -1227,11 +1209,11 @@ impl ComplexClipRegion {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub struct ClipChainId(pub u64, pub PipelineId);
|
||||
|
||||
/// A reference to a clipping node defining how an item is clipped.
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub enum ClipId {
|
||||
Clip(usize, PipelineId),
|
||||
ClipChain(ClipChainId),
|
||||
@ -1274,7 +1256,7 @@ impl ClipId {
|
||||
}
|
||||
|
||||
/// A reference to a spatial node defining item positioning.
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub struct SpatialId(pub usize, PipelineId);
|
||||
|
||||
const ROOT_REFERENCE_FRAME_SPATIAL_ID: usize = 0;
|
||||
@ -1313,7 +1295,7 @@ impl SpatialId {
|
||||
///
|
||||
/// When setting display lists with the `preserve_frame_state` this id is used to preserve scroll
|
||||
/// offsets between different sets of ClipScrollNodes which are ScrollFrames.
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
#[repr(C)]
|
||||
pub struct ExternalScrollId(pub u64, pub PipelineId);
|
||||
|
||||
@ -1359,44 +1341,3 @@ impl DisplayItem {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_default_for_enums {
|
||||
($($enum:ident => $init:expr ),+) => {
|
||||
$(impl Default for $enum {
|
||||
#[allow(unused_imports)]
|
||||
fn default() -> Self {
|
||||
use $enum::*;
|
||||
$init
|
||||
}
|
||||
})*
|
||||
}
|
||||
}
|
||||
|
||||
impl_default_for_enums! {
|
||||
DisplayItem => PopStackingContext,
|
||||
ScrollSensitivity => ScriptAndInputEvents,
|
||||
LineOrientation => Vertical,
|
||||
LineStyle => Solid,
|
||||
RepeatMode => Stretch,
|
||||
NinePatchBorderSource => Image(ImageKey::default()),
|
||||
BorderDetails => Normal(NormalBorder::default()),
|
||||
BorderRadiusKind => Uniform,
|
||||
BorderStyle => None,
|
||||
BoxShadowClipMode => Outset,
|
||||
ExtendMode => Clamp,
|
||||
FilterOp => Identity,
|
||||
ComponentTransferFuncType => Identity,
|
||||
ClipMode => Clip,
|
||||
ClipId => ClipId::invalid(),
|
||||
ReferenceFrameKind => Transform,
|
||||
TransformStyle => Flat,
|
||||
RasterSpace => Local(f32::default()),
|
||||
MixBlendMode => Normal,
|
||||
ImageRendering => Auto,
|
||||
AlphaType => Alpha,
|
||||
YuvColorSpace => Rec601,
|
||||
YuvData => NV12(ImageKey::default(), ImageKey::default()),
|
||||
YuvFormat => NV12,
|
||||
FilterPrimitiveInput => Original,
|
||||
ColorSpace => Srgb
|
||||
}
|
||||
|
@ -2,18 +2,17 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use bincode;
|
||||
use euclid::SideOffsets2D;
|
||||
use peek_poke::{ensure_red_zone, peek_from_slice, poke_extend_vec};
|
||||
use peek_poke::{poke_inplace_slice, poke_into_vec, Poke};
|
||||
#[cfg(feature = "deserialize")]
|
||||
use serde::de::Deserializer;
|
||||
#[cfg(feature = "serialize")]
|
||||
use serde::ser::{Serializer, SerializeSeq};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io::{stdout, Write};
|
||||
use std::io::{Read, stdout, Write};
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::Range;
|
||||
use std::mem;
|
||||
use std::{io, mem, ptr, slice};
|
||||
use std::collections::HashMap;
|
||||
use time::precise_time_ns;
|
||||
// local imports
|
||||
@ -68,15 +67,18 @@ impl<'a, T> ItemRange<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Default> ItemRange<'a, T> {
|
||||
impl<'a, T> ItemRange<'a, T>
|
||||
where
|
||||
for<'de> T: Deserialize<'de>,
|
||||
{
|
||||
pub fn iter(&self) -> AuxIter<'a, T> {
|
||||
AuxIter::new(T::default(), self.bytes)
|
||||
AuxIter::new(self.bytes)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for ItemRange<'a, T>
|
||||
where
|
||||
T: Copy + Default + peek_poke::Peek,
|
||||
for<'de> T: Deserialize<'de>,
|
||||
{
|
||||
type Item = T;
|
||||
type IntoIter = AuxIter<'a, T>;
|
||||
@ -174,7 +176,7 @@ impl DebugStats {
|
||||
|
||||
/// Logs the stats for the given serialized slice
|
||||
#[cfg(feature = "display_list_stats")]
|
||||
fn log_slice<T: Peek>(
|
||||
fn log_slice<T: for<'de> Deserialize<'de>>(
|
||||
&mut self,
|
||||
slice_name: &'static str,
|
||||
range: &ItemRange<T>,
|
||||
@ -184,7 +186,7 @@ impl DebugStats {
|
||||
// processed, and the `range` has everything we need.
|
||||
self.last_addr = range.bytes.as_ptr() as usize + range.bytes.len();
|
||||
|
||||
self._update_entry(slice_name, range.iter().len(), range.bytes.len());
|
||||
self._update_entry(slice_name, range.iter().size_hint().0, range.bytes.len());
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "display_list_stats"))]
|
||||
@ -215,10 +217,9 @@ enum Peek {
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AuxIter<'a, T> {
|
||||
item: T,
|
||||
data: &'a [u8],
|
||||
size: usize,
|
||||
// _boo: PhantomData<T>,
|
||||
_boo: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl BuiltDisplayListDescriptor {}
|
||||
@ -267,10 +268,11 @@ impl BuiltDisplayList {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the byte-range the slice occupied.
|
||||
fn skip_slice<'a, T: peek_poke::Peek>(data: &mut &'a [u8]) -> ItemRange<'a, T> {
|
||||
let mut skip_offset = 0usize;
|
||||
*data = peek_from_slice(data, &mut skip_offset);
|
||||
/// Returns the byte-range the slice occupied, and the number of elements
|
||||
/// in the slice.
|
||||
fn skip_slice<'a, T: for<'de> Deserialize<'de>>(mut data: &mut &'a [u8]) -> ItemRange<'a, T> {
|
||||
let skip_offset: usize = bincode::deserialize_from(&mut data).expect("MEH: malicious input?");
|
||||
|
||||
let (skip, rest) = data.split_at(skip_offset);
|
||||
|
||||
// Adjust data pointer to skip read values
|
||||
@ -355,14 +357,16 @@ impl<'a> BuiltDisplayListIter<'a> {
|
||||
pub fn next_raw<'b>(&'b mut self) -> Option<DisplayItemRef<'a, 'b>> {
|
||||
use crate::DisplayItem::*;
|
||||
|
||||
// A "red zone" of DisplayItem::max_size() bytes has been added to the
|
||||
// end of the serialized display list. If this amount, or less, is
|
||||
// remaining then we've reached the end of the display list.
|
||||
if self.data.len() <= di::DisplayItem::max_size() {
|
||||
if self.data.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
self.data = peek_from_slice(self.data, &mut self.cur_item);
|
||||
{
|
||||
let reader = bincode::IoReader::new(UnsafeReader::new(&mut self.data));
|
||||
bincode::deserialize_in_place(reader, &mut self.cur_item)
|
||||
.expect("MEH: malicious process?");
|
||||
}
|
||||
|
||||
self.log_item_stats();
|
||||
|
||||
match self.cur_item {
|
||||
@ -523,32 +527,34 @@ impl<'a, 'b> DisplayItemRef<'a, 'b> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> AuxIter<'a, T> {
|
||||
pub fn new(item: T, mut data: &'a [u8]) -> Self {
|
||||
let mut size = 0usize;
|
||||
if !data.is_empty() {
|
||||
data = peek_from_slice(data, &mut size);
|
||||
impl<'de, 'a, T: Deserialize<'de>> AuxIter<'a, T> {
|
||||
pub fn new(mut data: &'a [u8]) -> Self {
|
||||
let size: usize = if data.is_empty() {
|
||||
0 // Accept empty ItemRanges pointing anywhere
|
||||
} else {
|
||||
bincode::deserialize_from(&mut UnsafeReader::new(&mut data)).expect("MEH: malicious input?")
|
||||
};
|
||||
|
||||
AuxIter {
|
||||
item,
|
||||
data,
|
||||
size,
|
||||
// _boo: PhantomData,
|
||||
_boo: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Copy + peek_poke::Peek> Iterator for AuxIter<'a, T> {
|
||||
impl<'a, T: for<'de> Deserialize<'de>> Iterator for AuxIter<'a, T> {
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
fn next(&mut self) -> Option<T> {
|
||||
if self.size == 0 {
|
||||
None
|
||||
} else {
|
||||
self.size -= 1;
|
||||
self.data = peek_from_slice(self.data, &mut self.item);
|
||||
Some(self.item)
|
||||
Some(
|
||||
bincode::deserialize_from(&mut UnsafeReader::new(&mut self.data))
|
||||
.expect("MEH: malicious input?"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -557,7 +563,7 @@ impl<'a, T: Copy + peek_poke::Peek> Iterator for AuxIter<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Copy + peek_poke::Peek> ::std::iter::ExactSizeIterator for AuxIter<'a, T> {}
|
||||
impl<'a, T: for<'de> Deserialize<'de>> ::std::iter::ExactSizeIterator for AuxIter<'a, T> {}
|
||||
|
||||
|
||||
#[cfg(feature = "serialize")]
|
||||
@ -734,7 +740,7 @@ impl<'de> Deserialize<'de> for BuiltDisplayList {
|
||||
Debug::PopReferenceFrame => Real::PopReferenceFrame,
|
||||
Debug::PopAllShadows => Real::PopAllShadows,
|
||||
};
|
||||
poke_into_vec(&item, &mut data);
|
||||
serialize_fast(&mut data, &item);
|
||||
// the aux data is serialized after the item, hence the temporary
|
||||
data.extend(temp.drain(..));
|
||||
}
|
||||
@ -752,6 +758,221 @@ impl<'de> Deserialize<'de> for BuiltDisplayList {
|
||||
}
|
||||
}
|
||||
|
||||
// This is a replacement for bincode::serialize_into(&vec)
|
||||
// The default implementation Write for Vec will basically
|
||||
// call extend_from_slice(). Serde ends up calling that for every
|
||||
// field of a struct that we're serializing. extend_from_slice()
|
||||
// does not get inlined and thus we end up calling a generic memcpy()
|
||||
// implementation. If we instead reserve enough room for the serialized
|
||||
// struct in the Vec ahead of time we can rely on that and use
|
||||
// the following UnsafeVecWriter to write into the vec without
|
||||
// any checks. This writer assumes that size returned by the
|
||||
// serialize function will not change between calls to serialize_into:
|
||||
//
|
||||
// For example, the following struct will cause memory unsafety when
|
||||
// used with UnsafeVecWriter.
|
||||
//
|
||||
// struct S {
|
||||
// first: Cell<bool>,
|
||||
// }
|
||||
//
|
||||
// impl Serialize for S {
|
||||
// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
// where S: Serializer
|
||||
// {
|
||||
// if self.first.get() {
|
||||
// self.first.set(false);
|
||||
// ().serialize(serializer)
|
||||
// } else {
|
||||
// 0.serialize(serializer)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
|
||||
struct UnsafeVecWriter(*mut u8);
|
||||
|
||||
impl Write for UnsafeVecWriter {
|
||||
#[inline(always)]
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping(buf.as_ptr(), self.0, buf.len());
|
||||
self.0 = self.0.add(buf.len());
|
||||
}
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping(buf.as_ptr(), self.0, buf.len());
|
||||
self.0 = self.0.add(buf.len());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn flush(&mut self) -> io::Result<()> { Ok(()) }
|
||||
}
|
||||
|
||||
struct SizeCounter(usize);
|
||||
|
||||
impl<'a> Write for SizeCounter {
|
||||
#[inline(always)]
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.0 += buf.len();
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
|
||||
self.0 += buf.len();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn flush(&mut self) -> io::Result<()> { Ok(()) }
|
||||
}
|
||||
|
||||
/// Serializes a value assuming the Serialize impl has a stable size across two
|
||||
/// invocations.
|
||||
///
|
||||
/// If this assumption is incorrect, the result will be Undefined Behaviour. This
|
||||
/// assumption should hold for all derived Serialize impls, which is all we currently
|
||||
/// use.
|
||||
fn serialize_fast<T: Serialize>(vec: &mut Vec<u8>, e: T) {
|
||||
// manually counting the size is faster than vec.reserve(bincode::serialized_size(&e) as usize) for some reason
|
||||
let mut size = SizeCounter(0);
|
||||
bincode::serialize_into(&mut size, &e).unwrap();
|
||||
vec.reserve(size.0);
|
||||
|
||||
let old_len = vec.len();
|
||||
let ptr = unsafe { vec.as_mut_ptr().add(old_len) };
|
||||
let mut w = UnsafeVecWriter(ptr);
|
||||
bincode::serialize_into(&mut w, &e).unwrap();
|
||||
|
||||
// fix up the length
|
||||
unsafe { vec.set_len(old_len + size.0); }
|
||||
|
||||
// make sure we wrote the right amount
|
||||
debug_assert_eq!(((w.0 as usize) - (vec.as_ptr() as usize)), vec.len());
|
||||
}
|
||||
|
||||
/// Serializes an iterator, assuming:
|
||||
///
|
||||
/// * The Clone impl is trivial (e.g. we're just memcopying a slice iterator)
|
||||
/// * The ExactSizeIterator impl is stable and correct across a Clone
|
||||
/// * The Serialize impl has a stable size across two invocations
|
||||
///
|
||||
/// If the first is incorrect, WebRender will be very slow. If the other two are
|
||||
/// incorrect, the result will be Undefined Behaviour! The ExactSizeIterator
|
||||
/// bound would ideally be replaced with a TrustedLen bound to protect us a bit
|
||||
/// better, but that trait isn't stable (and won't be for a good while, if ever).
|
||||
///
|
||||
/// Debug asserts are included that should catch all Undefined Behaviour, but
|
||||
/// we can't afford to include these in release builds.
|
||||
fn serialize_iter_fast<I>(vec: &mut Vec<u8>, iter: I) -> usize
|
||||
where I: ExactSizeIterator + Clone,
|
||||
I::Item: Serialize,
|
||||
{
|
||||
// manually counting the size is faster than vec.reserve(bincode::serialized_size(&e) as usize) for some reason
|
||||
let mut size = SizeCounter(0);
|
||||
let mut count1 = 0;
|
||||
|
||||
for e in iter.clone() {
|
||||
bincode::serialize_into(&mut size, &e).unwrap();
|
||||
count1 += 1;
|
||||
}
|
||||
|
||||
vec.reserve(size.0);
|
||||
|
||||
let old_len = vec.len();
|
||||
let ptr = unsafe { vec.as_mut_ptr().add(old_len) };
|
||||
let mut w = UnsafeVecWriter(ptr);
|
||||
let mut count2 = 0;
|
||||
|
||||
for e in iter {
|
||||
bincode::serialize_into(&mut w, &e).unwrap();
|
||||
count2 += 1;
|
||||
}
|
||||
|
||||
// fix up the length
|
||||
unsafe { vec.set_len(old_len + size.0); }
|
||||
|
||||
// make sure we wrote the right amount
|
||||
debug_assert_eq!(((w.0 as usize) - (vec.as_ptr() as usize)), vec.len());
|
||||
debug_assert_eq!(count1, count2);
|
||||
|
||||
count1
|
||||
}
|
||||
|
||||
// This uses a (start, end) representation instead of (start, len) so that
|
||||
// only need to update a single field as we read through it. This
|
||||
// makes it easier for llvm to understand what's going on. (https://github.com/rust-lang/rust/issues/45068)
|
||||
// We update the slice only once we're done reading
|
||||
struct UnsafeReader<'a: 'b, 'b> {
|
||||
start: *const u8,
|
||||
end: *const u8,
|
||||
slice: &'b mut &'a [u8],
|
||||
}
|
||||
|
||||
impl<'a, 'b> UnsafeReader<'a, 'b> {
|
||||
#[inline(always)]
|
||||
fn new(buf: &'b mut &'a [u8]) -> UnsafeReader<'a, 'b> {
|
||||
unsafe {
|
||||
let end = buf.as_ptr().add(buf.len());
|
||||
let start = buf.as_ptr();
|
||||
UnsafeReader { start, end, slice: buf }
|
||||
}
|
||||
}
|
||||
|
||||
// This read implementation is significantly faster than the standard &[u8] one.
|
||||
//
|
||||
// First, it only supports reading exactly buf.len() bytes. This ensures that
|
||||
// the argument to memcpy is always buf.len() and will allow a constant buf.len()
|
||||
// to be propagated through to memcpy which LLVM will turn into explicit loads and
|
||||
// stores. The standard implementation does a len = min(slice.len(), buf.len())
|
||||
//
|
||||
// Second, we only need to adjust 'start' after reading and it's only adjusted by a
|
||||
// constant. This allows LLVM to avoid adjusting the length field after ever read
|
||||
// and lets it be aggregated into a single adjustment.
|
||||
#[inline(always)]
|
||||
fn read_internal(&mut self, buf: &mut [u8]) {
|
||||
// this is safe because we panic if start + buf.len() > end
|
||||
unsafe {
|
||||
assert!(self.start.add(buf.len()) <= self.end, "UnsafeReader: read past end of target");
|
||||
ptr::copy_nonoverlapping(self.start, buf.as_mut_ptr(), buf.len());
|
||||
self.start = self.start.add(buf.len());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> Drop for UnsafeReader<'a, 'b> {
|
||||
// this adjusts input slice so that it properly represents the amount that's left.
|
||||
#[inline(always)]
|
||||
fn drop(&mut self) {
|
||||
// this is safe because we know that start and end are contained inside the original slice
|
||||
unsafe {
|
||||
*self.slice = slice::from_raw_parts(self.start, (self.end as usize) - (self.start as usize));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> Read for UnsafeReader<'a, 'b> {
|
||||
// These methods were not being inlined and we need them to be so that the memcpy
|
||||
// is for a constant size
|
||||
#[inline(always)]
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.read_internal(buf);
|
||||
Ok(buf.len())
|
||||
}
|
||||
#[inline(always)]
|
||||
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
|
||||
self.read_internal(buf);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SaveState {
|
||||
dl_len: usize,
|
||||
@ -887,39 +1108,38 @@ impl DisplayListBuilder {
|
||||
/// result in WebRender panicking or behaving in unexpected ways.
|
||||
#[inline]
|
||||
pub fn push_item(&mut self, item: &di::DisplayItem) {
|
||||
poke_into_vec(item, &mut self.data);
|
||||
serialize_fast(&mut self.data, item);
|
||||
}
|
||||
|
||||
fn push_iter_impl<I>(data: &mut Vec<u8>, iter_source: I)
|
||||
where
|
||||
I: IntoIterator,
|
||||
I::IntoIter: ExactSizeIterator,
|
||||
I::Item: Poke,
|
||||
I::IntoIter: ExactSizeIterator + Clone,
|
||||
I::Item: Serialize,
|
||||
{
|
||||
let iter = iter_source.into_iter();
|
||||
let len = iter.len();
|
||||
// Format:
|
||||
// payload_byte_size: usize, item_count: usize, [I; item_count]
|
||||
|
||||
// Track the the location of where to write byte size with offsets
|
||||
// instead of pointers because data may be moved in memory during
|
||||
// `serialize_iter_fast`.
|
||||
let byte_size_offset = data.len();
|
||||
|
||||
// We write a dummy value so there's room for later
|
||||
poke_into_vec(&0usize, data);
|
||||
poke_into_vec(&len, data);
|
||||
let count = poke_extend_vec(iter, data);
|
||||
debug_assert_eq!(len, count);
|
||||
|
||||
// Add red zone
|
||||
ensure_red_zone::<I::Item>(data);
|
||||
let byte_size_offset = data.len();
|
||||
serialize_fast(data, &0usize);
|
||||
let payload_offset = data.len();
|
||||
serialize_fast(data, &len);
|
||||
let count = serialize_iter_fast(data, iter);
|
||||
|
||||
// Now write the actual byte_size
|
||||
let final_offset = data.len();
|
||||
debug_assert!(final_offset >= (byte_size_offset + mem::size_of::<usize>()));
|
||||
let byte_size = final_offset - byte_size_offset - mem::size_of::<usize>();
|
||||
poke_inplace_slice(&byte_size, &mut data[byte_size_offset..]);
|
||||
let byte_size = final_offset - payload_offset;
|
||||
|
||||
// Note we don't use serialize_fast because we don't want to change the Vec's len
|
||||
bincode::serialize_into(
|
||||
&mut &mut data[byte_size_offset..],
|
||||
&byte_size,
|
||||
).unwrap();
|
||||
|
||||
debug_assert_eq!(len, count);
|
||||
}
|
||||
|
||||
/// Push items from an iterator to the display list.
|
||||
@ -929,8 +1149,8 @@ impl DisplayListBuilder {
|
||||
pub fn push_iter<I>(&mut self, iter: I)
|
||||
where
|
||||
I: IntoIterator,
|
||||
I::IntoIter: ExactSizeIterator,
|
||||
I::Item: Poke,
|
||||
I::IntoIter: ExactSizeIterator + Clone,
|
||||
I::Item: Serialize,
|
||||
{
|
||||
Self::push_iter_impl(&mut self.data, iter);
|
||||
}
|
||||
@ -1464,14 +1684,9 @@ impl DisplayListBuilder {
|
||||
self.push_item(&di::DisplayItem::PopAllShadows);
|
||||
}
|
||||
|
||||
pub fn finalize(mut self) -> (PipelineId, LayoutSize, BuiltDisplayList) {
|
||||
pub fn finalize(self) -> (PipelineId, LayoutSize, BuiltDisplayList) {
|
||||
assert!(self.save_state.is_none(), "Finalized DisplayListBuilder with a pending save");
|
||||
|
||||
// Add `DisplayItem::max_size` zone of zeroes to the end of display list
|
||||
// so there is at least this amount available in the display list during
|
||||
// serialization.
|
||||
ensure_red_zone::<di::DisplayItem>(&mut self.data);
|
||||
|
||||
let end_time = precise_time_ns();
|
||||
|
||||
(
|
||||
|
@ -7,7 +7,6 @@ use app_units::Au;
|
||||
use core_foundation::string::CFString;
|
||||
#[cfg(target_os = "macos")]
|
||||
use core_graphics::font::CGFont;
|
||||
use peek_poke::PeekPoke;
|
||||
#[cfg(target_os = "macos")]
|
||||
use serde::de::{self, Deserialize, Deserializer};
|
||||
#[cfg(target_os = "macos")]
|
||||
@ -98,19 +97,13 @@ pub enum FontTemplate {
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Copy, Clone, Hash, Eq, MallocSizeOf, PartialEq, Serialize, Deserialize, Ord, PartialOrd, PeekPoke)]
|
||||
#[derive(Debug, Copy, Clone, Hash, Eq, MallocSizeOf, PartialEq, Serialize, Deserialize, Ord, PartialOrd)]
|
||||
pub enum FontRenderMode {
|
||||
Mono = 0,
|
||||
Alpha,
|
||||
Subpixel,
|
||||
}
|
||||
|
||||
impl Default for FontRenderMode {
|
||||
fn default() -> Self {
|
||||
FontRenderMode::Mono
|
||||
}
|
||||
}
|
||||
|
||||
impl FontRenderMode {
|
||||
// Combine two font render modes such that the lesser amount of AA limits the AA of the result.
|
||||
pub fn limit_by(self, other: FontRenderMode) -> FontRenderMode {
|
||||
@ -152,7 +145,7 @@ impl Hash for FontVariation {
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize)]
|
||||
pub struct GlyphOptions {
|
||||
pub render_mode: FontRenderMode,
|
||||
pub flags: FontInstanceFlags,
|
||||
@ -169,7 +162,7 @@ impl Default for GlyphOptions {
|
||||
|
||||
bitflags! {
|
||||
#[repr(C)]
|
||||
#[derive(Deserialize, MallocSizeOf, Serialize, PeekPoke)]
|
||||
#[derive(Deserialize, MallocSizeOf, Serialize)]
|
||||
pub struct FontInstanceFlags: u32 {
|
||||
// Common flags
|
||||
const SYNTHETIC_BOLD = 1 << 1;
|
||||
@ -355,8 +348,7 @@ impl Default for FontInstancePlatformOptions {
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq, Ord, PartialOrd, MallocSizeOf, PeekPoke)]
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, Ord, PartialOrd, MallocSizeOf)]
|
||||
pub struct FontInstanceKey(pub IdNamespace, pub u32);
|
||||
|
||||
impl FontInstanceKey {
|
||||
@ -381,21 +373,12 @@ pub struct FontInstanceData {
|
||||
pub type GlyphIndex = u32;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
|
||||
pub struct GlyphInstance {
|
||||
pub index: GlyphIndex,
|
||||
pub point: LayoutPoint,
|
||||
}
|
||||
|
||||
impl Default for GlyphInstance {
|
||||
fn default() -> Self {
|
||||
GlyphInstance {
|
||||
index: 0,
|
||||
point: LayoutPoint::zero(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for GlyphInstance {}
|
||||
|
||||
impl Hash for GlyphInstance {
|
||||
|
@ -5,7 +5,6 @@
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use euclid::{size2, TypedRect, num::Zero};
|
||||
use peek_poke::PeekPoke;
|
||||
use std::ops::{Add, Sub};
|
||||
use std::sync::Arc;
|
||||
// local imports
|
||||
@ -17,15 +16,9 @@ use crate::units::*;
|
||||
/// This is used as a handle to reference images, and is used as the
|
||||
/// hash map key for the actual image storage in the `ResourceCache`.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
|
||||
pub struct ImageKey(pub IdNamespace, pub u32);
|
||||
|
||||
impl Default for ImageKey {
|
||||
fn default() -> Self {
|
||||
ImageKey::DUMMY
|
||||
}
|
||||
}
|
||||
|
||||
impl ImageKey {
|
||||
/// Placeholder Image key, used to represent None.
|
||||
pub const DUMMY: Self = ImageKey(IdNamespace(0), 0);
|
||||
@ -149,7 +142,7 @@ impl ImageFormat {
|
||||
|
||||
/// Specifies the color depth of an image. Currently only used for YUV images.
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
|
||||
pub enum ColorDepth {
|
||||
/// 8 bits image (most common)
|
||||
Color8,
|
||||
@ -161,12 +154,6 @@ pub enum ColorDepth {
|
||||
Color16,
|
||||
}
|
||||
|
||||
impl Default for ColorDepth {
|
||||
fn default() -> Self {
|
||||
ColorDepth::Color8
|
||||
}
|
||||
}
|
||||
|
||||
impl ColorDepth {
|
||||
/// Return the numerical bit depth value for the type.
|
||||
pub fn bit_depth(self) -> u32 {
|
||||
|
@ -15,6 +15,7 @@
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(float_cmp, too_many_arguments, unreadable_literal))]
|
||||
|
||||
extern crate app_units;
|
||||
extern crate bincode;
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
extern crate byteorder;
|
||||
@ -37,7 +38,6 @@ extern crate serde_derive;
|
||||
extern crate time;
|
||||
|
||||
extern crate malloc_size_of;
|
||||
extern crate peek_poke;
|
||||
|
||||
mod api;
|
||||
pub mod channel;
|
||||
|
@ -16,7 +16,6 @@ pub use app_units::Au;
|
||||
use euclid::{Length, TypedRect, TypedScale, TypedSize2D, TypedTransform3D, TypedTranslation2D};
|
||||
use euclid::{TypedPoint2D, TypedPoint3D, TypedVector2D, TypedVector3D, TypedSideOffsets2D};
|
||||
use euclid::HomogeneousVector;
|
||||
use peek_poke::PeekPoke;
|
||||
// local imports
|
||||
use crate::image::DirtyRect;
|
||||
|
||||
@ -78,7 +77,7 @@ pub type RasterVector2D = TypedVector2D<f32, RasterPixel>;
|
||||
pub type RasterVector3D = TypedVector3D<f32, RasterPixel>;
|
||||
|
||||
/// Geometry in a stacking context's local coordinate space (logical pixels).
|
||||
#[derive(Hash, Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Ord, PartialOrd, Deserialize, Serialize, PeekPoke)]
|
||||
#[derive(Hash, Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Ord, PartialOrd, Deserialize, Serialize)]
|
||||
pub struct LayoutPixel;
|
||||
|
||||
pub type LayoutRect = TypedRect<f32, LayoutPixel>;
|
||||
|
2
third_party/rust/euclid/.cargo-checksum.json
vendored
2
third_party/rust/euclid/.cargo-checksum.json
vendored
@ -1 +1 @@
|
||||
{"files":{"COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"6ed8512d0e0c349a53eddd15a806e67e84359c1071d7d4a404f513cca091d5f5","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"625bec69c76ce5423fdd05cfe46922b2680ec517f97c5854ce34798d1d8a9541","src/approxeq.rs":"6594377e8f6c20f88f628520d8de9b9a59c5892a0ee9a6ccd13c8400c1499911","src/approxord.rs":"087e0a8d24b8a9bed4c1cc571eec5e50cc7afa184c6ac4961c7409a69456ec7b","src/box2d.rs":"5e2d634cf2181fd9f556a600d4339cb6a098341ac71f72e0bc7521b3b3fb2f19","src/box3d.rs":"8d87e7e487d0772462cc2c6033bcd05f4fee44127c4aa0a4d72407ac6a02e03b","src/homogen.rs":"7b02aa671fffcb554557ad790f598bd5d7440dc1aa4a6d1c5a97d8bc3c8f64d6","src/length.rs":"3171315822707728b1bfbdd04a4190ffb7206b4bfc59e9dd072bb2caa05ff292","src/lib.rs":"e8bbae14e1b284fba3529af44396e488cbc48f8b3d20ddb26da5919d9c02601b","src/macros.rs":"3b475e84d00cceee6c7e96e9f2c97ba15d8dc7f4094efb82c5ed10bd60d86a64","src/num.rs":"4439479fad5729073e0bfe0b96b547672a237430d48e564519759b9550baa033","src/point.rs":"b51cf9b7713d9a48452d833cfbc97bb95e0c2202c4f77cadd02633ce80a600df","src/rect.rs":"2e4036f3f7e2ca62e6f9a52787ca9b9765b401a11cf1e70dff6c81142bdd91ed","src/rigid.rs":"e50a5df42add328ed5164e1954592406ce6d8f564beb4ca375c5cca920e93fbc","src/rotation.rs":"3d1a934a7c59bd7ca8501d17d463d5af41fb529c5aa8fe8c3bb8a2b236d4abc0","src/scale.rs":"fc07bcf47f3a1215023c830059f0d270e570cbd37fe8c367ef4a47b191f4ae3e","src/side_offsets.rs":"d9b1463672e1204bf8e7dd6fe0f7601eb75b6690ec6eb18debcee07f5ca92ee3","src/size.rs":"c4e38966c280ab5b4963961eebdbb12e0f448aea624cbe760b02ca2221a004e5","src/transform2d.rs":"7657d447993dc820e404ea9fbde6cb2900d874d4f5c735e85c6225c9f3b4110d","src/transform3d.rs":"af3d909ee103d02fec5f59599055cc3cee5217975b030e0089e1f1d99ad5139e","src/translation.rs":"b21d1d81a34b80d3285d42f33e8039fdb787749f017d2a7a2295d036c2f50548","src/trig.rs":"97a263c4f178b0332501659ca8143f9f637a0755aca189dd31ac551bcd4cb73c","src/vector.rs":"dcd0904757ed0e7d12da1c612746da3e32c56e2248ec13041d1f3786811af51c"},"package":"596b99621b9477e7a5f94d2d8dd13a9c5c302ac358b822c67a42b6f1054450e1"}
|
||||
{"files":{"COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"4c50cb6cf03b2ab58cf9c017fdeee3f3d918b6143adeb529910f329bb07e7fd3","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"625bec69c76ce5423fdd05cfe46922b2680ec517f97c5854ce34798d1d8a9541","src/approxeq.rs":"6594377e8f6c20f88f628520d8de9b9a59c5892a0ee9a6ccd13c8400c1499911","src/homogen.rs":"7b02aa671fffcb554557ad790f598bd5d7440dc1aa4a6d1c5a97d8bc3c8f64d6","src/length.rs":"3171315822707728b1bfbdd04a4190ffb7206b4bfc59e9dd072bb2caa05ff292","src/lib.rs":"e8b1317127ec281fd42318f2c470558c2ecbb2e1459cebd4f9c63a2af807eb3d","src/macros.rs":"3b475e84d00cceee6c7e96e9f2c97ba15d8dc7f4094efb82c5ed10bd60d86a64","src/num.rs":"4439479fad5729073e0bfe0b96b547672a237430d48e564519759b9550baa033","src/point.rs":"689a8348428d12f6c5262965c505395bde37b4b1776369d93e93d73406d5344b","src/rect.rs":"ae16bb9ccb95cf329439d0ea4eb4c3821c4cd769cce4a544904b65d7e4af04b7","src/rotation.rs":"3d765a8e8e8c7181cc10d39be617779a8676d2611b408c69c841c3a10ce78a47","src/scale.rs":"fc07bcf47f3a1215023c830059f0d270e570cbd37fe8c367ef4a47b191f4ae3e","src/side_offsets.rs":"b79d43cca4c2e9fac7482a95661f72cb3ed51008f1d3e0c3f4fe608c68ef3658","src/size.rs":"49088bf3bf0e1ce740c1fe92761c18a43a6287d1d81a945bc92b21af63ef3416","src/transform2d.rs":"641acc1c9de9368bdbe0bb64b5ba4c1069ebeda6d6ad31463c81bdf85d678043","src/transform3d.rs":"c47dda0759629c1a836861fabf65e889001cf2d5ab59258544c1c04167cd7a67","src/translation.rs":"9787de1bccdd402774ba9a5bc55ec6d4b2ee36e0a146baecee417ee9cc753db5","src/trig.rs":"97a263c4f178b0332501659ca8143f9f637a0755aca189dd31ac551bcd4cb73c","src/vector.rs":"d57493649da9d8a728dcba49bb80c579a4d2bf6f3557dd4b4c770cfcef6ee395"},"package":"d1a7698bdda3d7444a79d33bdc96e8b518d44ea3ff101d8492a6ca1207b886ea"}
|
4
third_party/rust/euclid/Cargo.toml
vendored
4
third_party/rust/euclid/Cargo.toml
vendored
@ -3,7 +3,7 @@
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g., crates.io) dependencies
|
||||
# to registry (e.g. crates.io) dependencies
|
||||
#
|
||||
# If you believe there's an error in this file please file an
|
||||
# issue against the rust-lang/cargo repository. If you're
|
||||
@ -12,7 +12,7 @@
|
||||
|
||||
[package]
|
||||
name = "euclid"
|
||||
version = "0.19.9"
|
||||
version = "0.19.5"
|
||||
authors = ["The Servo Project Developers"]
|
||||
description = "Geometry primitives"
|
||||
documentation = "https://docs.rs/euclid/"
|
||||
|
43
third_party/rust/euclid/src/approxord.rs
vendored
43
third_party/rust/euclid/src/approxord.rs
vendored
@ -1,43 +0,0 @@
|
||||
// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
/// Utilities for testing approximate ordering - especially true for
|
||||
/// floating point types, where NaN's cannot be ordered.
|
||||
pub fn min<T: PartialOrd>(x: T, y: T) -> T {
|
||||
if x <= y {
|
||||
x
|
||||
} else {
|
||||
y
|
||||
}
|
||||
}
|
||||
|
||||
pub fn max<T: PartialOrd>(x: T, y: T) -> T {
|
||||
if x >= y {
|
||||
x
|
||||
} else {
|
||||
y
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_min() {
|
||||
assert!(min(0u32, 1u32) == 0u32);
|
||||
assert!(min(-1.0f32, 0.0f32) == -1.0f32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_max() {
|
||||
assert!(max(0u32, 1u32) == 1u32);
|
||||
assert!(max(-1.0f32, 0.0f32) == 0.0f32);
|
||||
}
|
||||
}
|
793
third_party/rust/euclid/src/box2d.rs
vendored
793
third_party/rust/euclid/src/box2d.rs
vendored
@ -1,793 +0,0 @@
|
||||
// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use super::UnknownUnit;
|
||||
use scale::TypedScale;
|
||||
use num::*;
|
||||
use rect::TypedRect;
|
||||
use point::{point2, TypedPoint2D};
|
||||
use vector::{vec2, TypedVector2D};
|
||||
use side_offsets::TypedSideOffsets2D;
|
||||
use size::TypedSize2D;
|
||||
use approxord::{min, max};
|
||||
|
||||
use num_traits::NumCast;
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use core::borrow::Borrow;
|
||||
use core::cmp::PartialOrd;
|
||||
use core::fmt;
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::ops::{Add, Div, Mul, Sub};
|
||||
|
||||
|
||||
/// An axis aligned rectangle represented by its minimum and maximum coordinates.
|
||||
#[repr(C)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "serde", serde(bound(serialize = "T: Serialize", deserialize = "T: Deserialize<'de>")))]
|
||||
pub struct TypedBox2D<T, U> {
|
||||
pub min: TypedPoint2D<T, U>,
|
||||
pub max: TypedPoint2D<T, U>,
|
||||
}
|
||||
|
||||
/// The default box 2d type with no unit.
|
||||
pub type Box2D<T> = TypedBox2D<T, UnknownUnit>;
|
||||
|
||||
impl<T: Hash, U> Hash for TypedBox2D<T, U> {
|
||||
fn hash<H: Hasher>(&self, h: &mut H) {
|
||||
self.min.hash(h);
|
||||
self.max.hash(h);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> Copy for TypedBox2D<T, U> {}
|
||||
|
||||
impl<T: Copy, U> Clone for TypedBox2D<T, U> {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PartialEq, U> PartialEq<TypedBox2D<T, U>> for TypedBox2D<T, U> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.min.eq(&other.min) && self.max.eq(&other.max)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Eq, U> Eq for TypedBox2D<T, U> {}
|
||||
|
||||
impl<T: fmt::Debug, U> fmt::Debug for TypedBox2D<T, U> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "TypedBox2D({:?}, {:?})", self.min, self.max)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Display, U> fmt::Display for TypedBox2D<T, U> {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(formatter, "Box2D({}, {})", self.min, self.max)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U> {
|
||||
/// Constructor.
|
||||
pub fn new(min: TypedPoint2D<T, U>, max: TypedPoint2D<T, U>) -> Self {
|
||||
TypedBox2D {
|
||||
min,
|
||||
max,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
where
|
||||
T: Copy + Zero + PartialOrd,
|
||||
{
|
||||
/// Creates a Box2D of the given size, at offset zero.
|
||||
#[inline]
|
||||
pub fn from_size(size: TypedSize2D<T, U>) -> Self {
|
||||
let zero = TypedPoint2D::zero();
|
||||
let point = size.to_vector().to_point();
|
||||
TypedBox2D::from_points(&[zero, point])
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
where
|
||||
T: Copy + PartialOrd,
|
||||
{
|
||||
/// Returns true if the box has a negative area.
|
||||
///
|
||||
/// The common interpretation for a negative box is to consider it empty. It can be obtained
|
||||
/// by calculating the intersection of two boxes that do not intersect.
|
||||
#[inline]
|
||||
pub fn is_negative(&self) -> bool {
|
||||
self.max.x < self.min.x || self.max.y < self.min.y
|
||||
}
|
||||
|
||||
/// Returns true if the size is zero or negative.
|
||||
#[inline]
|
||||
pub fn is_empty_or_negative(&self) -> bool {
|
||||
self.max.x <= self.min.x || self.max.y <= self.min.y
|
||||
}
|
||||
|
||||
/// Returns true if the two boxes intersect.
|
||||
#[inline]
|
||||
pub fn intersects(&self, other: &Self) -> bool {
|
||||
self.min.x < other.max.x
|
||||
&& self.max.x > other.min.x
|
||||
&& self.min.y < other.max.y
|
||||
&& self.max.y > other.min.y
|
||||
}
|
||||
|
||||
/// Computes the intersection of two boxes.
|
||||
///
|
||||
/// The result is a negative box if the boxes do not intersect.
|
||||
#[inline]
|
||||
pub fn intersection(&self, other: &Self) -> Self {
|
||||
TypedBox2D {
|
||||
min: point2(
|
||||
max(self.min.x, other.min.x),
|
||||
max(self.min.y, other.min.y),
|
||||
),
|
||||
max: point2(
|
||||
min(self.max.x, other.max.x),
|
||||
min(self.max.y, other.max.y),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the intersection of two boxes, returning `None` if the boxes do not intersect.
|
||||
#[inline]
|
||||
pub fn try_intersection(&self, other: &Self) -> Option<Self> {
|
||||
let intersection = self.intersection(other);
|
||||
|
||||
if intersection.is_negative() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(intersection)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
where
|
||||
T: Copy + Add<T, Output = T>,
|
||||
{
|
||||
/// Returns the same box, translated by a vector.
|
||||
#[inline]
|
||||
pub fn translate(&self, by: &TypedVector2D<T, U>) -> Self {
|
||||
Self::new(self.min + *by, self.max + *by)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
where
|
||||
T: Copy + PartialOrd + Zero,
|
||||
{
|
||||
/// Returns true if this box contains the point. Points are considered
|
||||
/// in the box if they are on the front, left or top faces, but outside if they
|
||||
/// are on the back, right or bottom faces.
|
||||
#[inline]
|
||||
pub fn contains(&self, p: &TypedPoint2D<T, U>) -> bool {
|
||||
self.min.x <= p.x && p.x < self.max.x
|
||||
&& self.min.y <= p.y && p.y < self.max.y
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
where
|
||||
T: Copy + PartialOrd + Zero + Sub<T, Output = T>,
|
||||
{
|
||||
/// Returns true if this box contains the interior of the other box. Always
|
||||
/// returns true if other is empty, and always returns false if other is
|
||||
/// nonempty but this box is empty.
|
||||
#[inline]
|
||||
pub fn contains_box(&self, other: &Self) -> bool {
|
||||
other.is_empty_or_negative()
|
||||
|| (self.min.x <= other.min.x && other.max.x <= self.max.x
|
||||
&& self.min.y <= other.min.y && other.max.y <= self.max.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
where
|
||||
T: Copy + Sub<T, Output = T>,
|
||||
{
|
||||
#[inline]
|
||||
pub fn size(&self)-> TypedSize2D<T, U> {
|
||||
(self.max - self.min).to_size()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_rect(&self) -> TypedRect<T, U> {
|
||||
TypedRect {
|
||||
origin: self.min,
|
||||
size: self.size(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
where
|
||||
T: Copy + PartialEq + Add<T, Output = T> + Sub<T, Output = T>,
|
||||
{
|
||||
/// Inflates the box by the specified sizes on each side respectively.
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn inflate(&self, width: T, height: T) -> Self {
|
||||
TypedBox2D {
|
||||
min: point2(self.min.x - width, self.min.y - height),
|
||||
max: point2(self.max.x + width, self.max.y + height),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
where
|
||||
T: Copy + Zero + PartialOrd + Add<T, Output = T> + Sub<T, Output = T>,
|
||||
{
|
||||
/// Calculate the size and position of an inner box.
|
||||
///
|
||||
/// Subtracts the side offsets from all sides. The horizontal, vertical
|
||||
/// and applicate offsets must not be larger than the original side length.
|
||||
pub fn inner_box(&self, offsets: TypedSideOffsets2D<T, U>) -> Self {
|
||||
TypedBox2D {
|
||||
min: self.min + vec2(offsets.left, offsets.top),
|
||||
max: self.max - vec2(offsets.right, offsets.bottom),
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculate the b and position of an outer box.
|
||||
///
|
||||
/// Add the offsets to all sides. The expanded box is returned.
|
||||
pub fn outer_box(&self, offsets: TypedSideOffsets2D<T, U>) -> Self {
|
||||
TypedBox2D {
|
||||
min: self.min - vec2(offsets.left, offsets.top),
|
||||
max: self.max + vec2(offsets.right, offsets.bottom),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
where
|
||||
T: Copy + Zero + PartialOrd,
|
||||
{
|
||||
/// Returns the smallest box containing all of the provided points.
|
||||
pub fn from_points<I>(points: I) -> Self
|
||||
where
|
||||
I: IntoIterator,
|
||||
I::Item: Borrow<TypedPoint2D<T, U>>,
|
||||
{
|
||||
let mut points = points.into_iter();
|
||||
|
||||
// Need at least 2 different points for a valid box (ie: volume > 0).
|
||||
let (mut min_x, mut min_y) = match points.next() {
|
||||
Some(first) => (first.borrow().x, first.borrow().y),
|
||||
None => return TypedBox2D::zero(),
|
||||
};
|
||||
let (mut max_x, mut max_y) = (min_x, min_y);
|
||||
|
||||
{
|
||||
let mut assign_min_max = |point: I::Item| {
|
||||
let p = point.borrow();
|
||||
if p.x < min_x {
|
||||
min_x = p.x
|
||||
}
|
||||
if p.x > max_x {
|
||||
max_x = p.x
|
||||
}
|
||||
if p.y < min_y {
|
||||
min_y = p.y
|
||||
}
|
||||
if p.y > max_y {
|
||||
max_y = p.y
|
||||
}
|
||||
};
|
||||
|
||||
match points.next() {
|
||||
Some(second) => assign_min_max(second),
|
||||
None => return TypedBox2D::zero(),
|
||||
}
|
||||
|
||||
for point in points {
|
||||
assign_min_max(point);
|
||||
}
|
||||
}
|
||||
|
||||
TypedBox2D {
|
||||
min: point2(min_x, min_y),
|
||||
max: point2(max_x, max_y),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
where
|
||||
T: Copy + One + Add<Output = T> + Sub<Output = T> + Mul<Output = T>,
|
||||
{
|
||||
/// Linearly interpolate between this box and another box.
|
||||
///
|
||||
/// `t` is expected to be between zero and one.
|
||||
#[inline]
|
||||
pub fn lerp(&self, other: Self, t: T) -> Self {
|
||||
Self::new(
|
||||
self.min.lerp(other.min, t),
|
||||
self.max.lerp(other.max, t),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
where
|
||||
T: Copy + One + Add<Output = T> + Div<Output = T>,
|
||||
{
|
||||
pub fn center(&self) -> TypedPoint2D<T, U> {
|
||||
let two = T::one() + T::one();
|
||||
(self.min + self.max.to_vector()) / two
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
where
|
||||
T: Copy + PartialOrd,
|
||||
{
|
||||
#[inline]
|
||||
pub fn union(&self, other: &Self) -> Self {
|
||||
TypedBox2D {
|
||||
min: point2(
|
||||
min(self.min.x, other.min.x),
|
||||
min(self.min.y, other.min.y),
|
||||
),
|
||||
max: point2(
|
||||
max(self.max.x, other.max.x),
|
||||
max(self.max.y, other.max.y),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
#[inline]
|
||||
pub fn scale<S: Copy>(&self, x: S, y: S) -> Self
|
||||
where
|
||||
T: Mul<S, Output = T>
|
||||
{
|
||||
TypedBox2D {
|
||||
min: point2(self.min.x * x, self.min.y * y),
|
||||
max: point2(self.max.x * x, self.max.y * y),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
where
|
||||
T: Copy + Mul<T, Output = T> + Sub<T, Output = T>,
|
||||
{
|
||||
#[inline]
|
||||
pub fn area(&self) -> T {
|
||||
let size = self.size();
|
||||
size.width * size.height
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
where
|
||||
T: Copy + Zero,
|
||||
{
|
||||
/// Constructor, setting all sides to zero.
|
||||
pub fn zero() -> Self {
|
||||
TypedBox2D::new(TypedPoint2D::zero(), TypedPoint2D::zero())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
where
|
||||
T: PartialEq,
|
||||
{
|
||||
/// Returns true if the size is zero.
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.min.x == self.max.x || self.min.y == self.max.y
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Mul<T> for TypedBox2D<T, U>
|
||||
where
|
||||
T: Copy + Mul<T, Output = T>,
|
||||
{
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn mul(self, scale: T) -> Self {
|
||||
TypedBox2D::new(self.min * scale, self.max * scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Div<T> for TypedBox2D<T, U>
|
||||
where
|
||||
T: Copy + Div<T, Output = T>,
|
||||
{
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn div(self, scale: T) -> Self {
|
||||
TypedBox2D::new(self.min / scale, self.max / scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U1, U2> Mul<TypedScale<T, U1, U2>> for TypedBox2D<T, U1>
|
||||
where
|
||||
T: Copy + Mul<T, Output = T>,
|
||||
{
|
||||
type Output = TypedBox2D<T, U2>;
|
||||
#[inline]
|
||||
fn mul(self, scale: TypedScale<T, U1, U2>) -> TypedBox2D<T, U2> {
|
||||
TypedBox2D::new(self.min * scale, self.max * scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U1, U2> Div<TypedScale<T, U1, U2>> for TypedBox2D<T, U2>
|
||||
where
|
||||
T: Copy + Div<T, Output = T>,
|
||||
{
|
||||
type Output = TypedBox2D<T, U1>;
|
||||
#[inline]
|
||||
fn div(self, scale: TypedScale<T, U1, U2>) -> TypedBox2D<T, U1> {
|
||||
TypedBox2D::new(self.min / scale, self.max / scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Unit> TypedBox2D<T, Unit>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
/// Drop the units, preserving only the numeric value.
|
||||
pub fn to_untyped(&self) -> Box2D<T> {
|
||||
TypedBox2D::new(self.min.to_untyped(), self.max.to_untyped())
|
||||
}
|
||||
|
||||
/// Tag a unitless value with units.
|
||||
pub fn from_untyped(c: &Box2D<T>) -> TypedBox2D<T, Unit> {
|
||||
TypedBox2D::new(
|
||||
TypedPoint2D::from_untyped(&c.min),
|
||||
TypedPoint2D::from_untyped(&c.max),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T0, Unit> TypedBox2D<T0, Unit>
|
||||
where
|
||||
T0: NumCast + Copy,
|
||||
{
|
||||
/// Cast from one numeric representation to another, preserving the units.
|
||||
///
|
||||
/// When casting from floating point to integer coordinates, the decimals are truncated
|
||||
/// as one would expect from a simple cast, but this behavior does not always make sense
|
||||
/// geometrically. Consider using round(), round_in or round_out() before casting.
|
||||
pub fn cast<T1: NumCast + Copy>(&self) -> TypedBox2D<T1, Unit> {
|
||||
TypedBox2D::new(
|
||||
self.min.cast(),
|
||||
self.max.cast(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Fallible cast from one numeric representation to another, preserving the units.
|
||||
///
|
||||
/// When casting from floating point to integer coordinates, the decimals are truncated
|
||||
/// as one would expect from a simple cast, but this behavior does not always make sense
|
||||
/// geometrically. Consider using round(), round_in or round_out() before casting.
|
||||
pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<TypedBox2D<T1, Unit>> {
|
||||
match (self.min.try_cast(), self.max.try_cast()) {
|
||||
(Some(a), Some(b)) => Some(TypedBox2D::new(a, b)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
where
|
||||
T: Round,
|
||||
{
|
||||
/// Return a box with edges rounded to integer coordinates, such that
|
||||
/// the returned box has the same set of pixel centers as the original
|
||||
/// one.
|
||||
/// Values equal to 0.5 round up.
|
||||
/// Suitable for most places where integral device coordinates
|
||||
/// are needed, but note that any translation should be applied first to
|
||||
/// avoid pixel rounding errors.
|
||||
/// Note that this is *not* rounding to nearest integer if the values are negative.
|
||||
/// They are always rounding as floor(n + 0.5).
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn round(&self) -> Self {
|
||||
TypedBox2D::new(self.min.round(), self.max.round())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
where
|
||||
T: Floor + Ceil,
|
||||
{
|
||||
/// Return a box with faces/edges rounded to integer coordinates, such that
|
||||
/// the original box contains the resulting box.
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn round_in(&self) -> Self {
|
||||
let min = self.min.ceil();
|
||||
let max = self.max.floor();
|
||||
TypedBox2D { min, max }
|
||||
}
|
||||
|
||||
/// Return a box with faces/edges rounded to integer coordinates, such that
|
||||
/// the original box is contained in the resulting box.
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn round_out(&self) -> Self {
|
||||
let min = self.min.floor();
|
||||
let max = self.max.ceil();
|
||||
TypedBox2D { min, max }
|
||||
}
|
||||
}
|
||||
|
||||
// Convenience functions for common casts
|
||||
impl<T: NumCast + Copy, Unit> TypedBox2D<T, Unit> {
|
||||
/// Cast into an `f32` box.
|
||||
pub fn to_f32(&self) -> TypedBox2D<f32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `f64` box.
|
||||
pub fn to_f64(&self) -> TypedBox2D<f64, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `usize` box, truncating decimals if any.
|
||||
///
|
||||
/// When casting from floating point boxes, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_usize(&self) -> TypedBox2D<usize, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `u32` box, truncating decimals if any.
|
||||
///
|
||||
/// When casting from floating point boxes, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_u32(&self) -> TypedBox2D<u32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `i32` box, truncating decimals if any.
|
||||
///
|
||||
/// When casting from floating point boxes, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_i32(&self) -> TypedBox2D<i32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `i64` box, truncating decimals if any.
|
||||
///
|
||||
/// When casting from floating point boxes, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_i64(&self) -> TypedBox2D<i64, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> From<TypedSize2D<T, U>> for TypedBox2D<T, U>
|
||||
where
|
||||
T: Copy + Zero + PartialOrd,
|
||||
{
|
||||
fn from(b: TypedSize2D<T, U>) -> Self {
|
||||
Self::from_size(b)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use side_offsets::SideOffsets2D;
|
||||
use size::size2;
|
||||
use point::Point2D;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_size() {
|
||||
let b = Box2D::new(point2(-10.0, -10.0), point2(10.0, 10.0));
|
||||
assert_eq!(b.size().width, 20.0);
|
||||
assert_eq!(b.size().height, 20.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_center() {
|
||||
let b = Box2D::new(point2(-10.0, -10.0), point2(10.0, 10.0));
|
||||
assert_eq!(b.center(), Point2D::zero());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_area() {
|
||||
let b = Box2D::new(point2(-10.0, -10.0), point2(10.0, 10.0));
|
||||
assert_eq!(b.area(), 400.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_points() {
|
||||
let b = Box2D::from_points(&[point2(50.0, 160.0), point2(100.0, 25.0)]);
|
||||
assert_eq!(b.min, point2(50.0, 25.0));
|
||||
assert_eq!(b.max, point2(100.0, 160.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_round_in() {
|
||||
let b = Box2D::from_points(&[point2(-25.5, -40.4), point2(60.3, 36.5)]).round_in();
|
||||
assert_eq!(b.min.x, -25.0);
|
||||
assert_eq!(b.min.y, -40.0);
|
||||
assert_eq!(b.max.x, 60.0);
|
||||
assert_eq!(b.max.y, 36.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_round_out() {
|
||||
let b = Box2D::from_points(&[point2(-25.5, -40.4), point2(60.3, 36.5)]).round_out();
|
||||
assert_eq!(b.min.x,-26.0);
|
||||
assert_eq!(b.min.y, -41.0);
|
||||
assert_eq!(b.max.x, 61.0);
|
||||
assert_eq!(b.max.y, 37.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_round() {
|
||||
let b = Box2D::from_points(&[point2(-25.5, -40.4), point2(60.3, 36.5)]).round();
|
||||
assert_eq!(b.min.x,-26.0);
|
||||
assert_eq!(b.min.y, -40.0);
|
||||
assert_eq!(b.max.x, 60.0);
|
||||
assert_eq!(b.max.y, 37.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_size() {
|
||||
let b = Box2D::from_size(size2(30.0, 40.0));
|
||||
assert!(b.min == Point2D::zero());
|
||||
assert!(b.size().width == 30.0);
|
||||
assert!(b.size().height == 40.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inner_box() {
|
||||
let b = Box2D::from_points(&[point2(50.0, 25.0), point2(100.0, 160.0)]);
|
||||
let b = b.inner_box(SideOffsets2D::new(10.0, 20.0, 5.0, 10.0));
|
||||
assert_eq!(b.max.x, 80.0);
|
||||
assert_eq!(b.max.y, 155.0);
|
||||
assert_eq!(b.min.x, 60.0);
|
||||
assert_eq!(b.min.y, 35.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_outer_box() {
|
||||
let b = Box2D::from_points(&[point2(50.0, 25.0), point2(100.0, 160.0)]);
|
||||
let b = b.outer_box(SideOffsets2D::new(10.0, 20.0, 5.0, 10.0));
|
||||
assert_eq!(b.max.x, 120.0);
|
||||
assert_eq!(b.max.y, 165.0);
|
||||
assert_eq!(b.min.x, 40.0);
|
||||
assert_eq!(b.min.y, 15.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_translate() {
|
||||
let size = size2(15.0, 15.0);
|
||||
let mut center = (size / 2.0).to_vector().to_point();
|
||||
let b = Box2D::from_size(size);
|
||||
assert_eq!(b.center(), center);
|
||||
let translation = vec2(10.0, 2.5);
|
||||
let b = b.translate(&translation);
|
||||
center += translation;
|
||||
assert_eq!(b.center(), center);
|
||||
assert_eq!(b.max.x, 25.0);
|
||||
assert_eq!(b.max.y, 17.5);
|
||||
assert_eq!(b.min.x, 10.0);
|
||||
assert_eq!(b.min.y, 2.5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_union() {
|
||||
let b1 = Box2D::from_points(&[point2(-20.0, -20.0), point2(0.0, 20.0)]);
|
||||
let b2 = Box2D::from_points(&[point2(0.0, 20.0), point2(20.0, -20.0)]);
|
||||
let b = b1.union(&b2);
|
||||
assert_eq!(b.max.x, 20.0);
|
||||
assert_eq!(b.max.y, 20.0);
|
||||
assert_eq!(b.min.x, -20.0);
|
||||
assert_eq!(b.min.y, -20.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_intersects() {
|
||||
let b1 = Box2D::from_points(&[point2(-15.0, -20.0), point2(10.0, 20.0)]);
|
||||
let b2 = Box2D::from_points(&[point2(-10.0, 20.0), point2(15.0, -20.0)]);
|
||||
assert!(b1.intersects(&b2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_intersection() {
|
||||
let b1 = Box2D::from_points(&[point2(-15.0, -20.0), point2(10.0, 20.0)]);
|
||||
let b2 = Box2D::from_points(&[point2(-10.0, 20.0), point2(15.0, -20.0)]);
|
||||
let b = b1.intersection(&b2);
|
||||
assert_eq!(b.max.x, 10.0);
|
||||
assert_eq!(b.max.y, 20.0);
|
||||
assert_eq!(b.min.x, -10.0);
|
||||
assert_eq!(b.min.y, -20.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_intersection() {
|
||||
let b1 = Box2D::from_points(&[point2(-15.0, -20.0), point2(10.0, 20.0)]);
|
||||
let b2 = Box2D::from_points(&[point2(-10.0, 20.0), point2(15.0, -20.0)]);
|
||||
assert!(b1.try_intersection(&b2).is_some());
|
||||
|
||||
let b1 = Box2D::from_points(&[point2(-15.0, -20.0), point2(-10.0, 20.0)]);
|
||||
let b2 = Box2D::from_points(&[point2(10.0, 20.0), point2(15.0, -20.0)]);
|
||||
assert!(b1.try_intersection(&b2).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_scale() {
|
||||
let b = Box2D::from_points(&[point2(-10.0, -10.0), point2(10.0, 10.0)]);
|
||||
let b = b.scale(0.5, 0.5);
|
||||
assert_eq!(b.max.x, 5.0);
|
||||
assert_eq!(b.max.y, 5.0);
|
||||
assert_eq!(b.min.x, -5.0);
|
||||
assert_eq!(b.min.y, -5.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lerp() {
|
||||
let b1 = Box2D::from_points(&[point2(-20.0, -20.0), point2(-10.0, -10.0)]);
|
||||
let b2 = Box2D::from_points(&[point2(10.0, 10.0), point2(20.0, 20.0)]);
|
||||
let b = b1.lerp(b2, 0.5);
|
||||
assert_eq!(b.center(), Point2D::zero());
|
||||
assert_eq!(b.size().width, 10.0);
|
||||
assert_eq!(b.size().height, 10.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_contains() {
|
||||
let b = Box2D::from_points(&[point2(-20.0, -20.0), point2(20.0, 20.0)]);
|
||||
assert!(b.contains(&point2(-15.3, 10.5)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_contains_box() {
|
||||
let b1 = Box2D::from_points(&[point2(-20.0, -20.0), point2(20.0, 20.0)]);
|
||||
let b2 = Box2D::from_points(&[point2(-14.3, -16.5), point2(6.7, 17.6)]);
|
||||
assert!(b1.contains_box(&b2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inflate() {
|
||||
let b = Box2D::from_points(&[point2(-20.0, -20.0), point2(20.0, 20.0)]);
|
||||
let b = b.inflate(10.0, 5.0);
|
||||
assert_eq!(b.size().width, 60.0);
|
||||
assert_eq!(b.size().height, 50.0);
|
||||
assert_eq!(b.center(), Point2D::zero());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_empty() {
|
||||
for i in 0..2 {
|
||||
let mut coords_neg = [-20.0, -20.0];
|
||||
let mut coords_pos = [20.0, 20.0];
|
||||
coords_neg[i] = 0.0;
|
||||
coords_pos[i] = 0.0;
|
||||
let b = Box2D::from_points(&[Point2D::from(coords_neg), Point2D::from(coords_pos)]);
|
||||
assert!(b.is_empty());
|
||||
}
|
||||
}
|
||||
}
|
842
third_party/rust/euclid/src/box3d.rs
vendored
842
third_party/rust/euclid/src/box3d.rs
vendored
@ -1,842 +0,0 @@
|
||||
// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use super::UnknownUnit;
|
||||
use length::Length;
|
||||
use scale::TypedScale;
|
||||
use num::*;
|
||||
use point::TypedPoint3D;
|
||||
use vector::TypedVector3D;
|
||||
use size::TypedSize3D;
|
||||
use approxord::{min, max};
|
||||
|
||||
use num_traits::NumCast;
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use core::borrow::Borrow;
|
||||
use core::cmp::PartialOrd;
|
||||
use core::fmt;
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::ops::{Add, Div, Mul, Sub};
|
||||
|
||||
|
||||
/// An axis aligned 3D box represented by its minimum and maximum coordinates.
|
||||
#[repr(C)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "serde", serde(bound(serialize = "T: Serialize", deserialize = "T: Deserialize<'de>")))]
|
||||
pub struct TypedBox3D<T, U> {
|
||||
pub min: TypedPoint3D<T, U>,
|
||||
pub max: TypedPoint3D<T, U>,
|
||||
}
|
||||
|
||||
/// The default box 3d type with no unit.
|
||||
pub type Box3D<T> = TypedBox3D<T, UnknownUnit>;
|
||||
|
||||
impl<T: Hash, U> Hash for TypedBox3D<T, U> {
|
||||
fn hash<H: Hasher>(&self, h: &mut H) {
|
||||
self.min.hash(h);
|
||||
self.max.hash(h);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> Copy for TypedBox3D<T, U> {}
|
||||
|
||||
impl<T: Copy, U> Clone for TypedBox3D<T, U> {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PartialEq, U> PartialEq<TypedBox3D<T, U>> for TypedBox3D<T, U> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.min.eq(&other.min) && self.max.eq(&other.max)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Eq, U> Eq for TypedBox3D<T, U> {}
|
||||
|
||||
impl<T: fmt::Debug, U> fmt::Debug for TypedBox3D<T, U> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "TypedBox3D({:?}, {:?})", self.min, self.max)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Display, U> fmt::Display for TypedBox3D<T, U> {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(formatter, "Box3D({}, {})", self.min, self.max)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U> {
|
||||
/// Constructor.
|
||||
pub fn new(min: TypedPoint3D<T, U>, max: TypedPoint3D<T, U>) -> Self {
|
||||
TypedBox3D {
|
||||
min,
|
||||
max,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
where
|
||||
T: Copy + Zero + PartialOrd,
|
||||
{
|
||||
/// Creates a Box3D of the given size, at offset zero.
|
||||
#[inline]
|
||||
pub fn from_size(size: TypedSize3D<T, U>) -> Self {
|
||||
let zero = TypedPoint3D::zero();
|
||||
let point = size.to_vector().to_point();
|
||||
TypedBox3D::from_points(&[zero, point])
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
where
|
||||
T: Copy + PartialOrd,
|
||||
{
|
||||
/// Returns true if the box has a negative volume.
|
||||
///
|
||||
/// The common interpretation for a negative box is to consider it empty. It can be obtained
|
||||
/// by calculating the intersection of two boxes that do not intersect.
|
||||
#[inline]
|
||||
pub fn is_negative(&self) -> bool {
|
||||
self.max.x < self.min.x || self.max.y < self.min.y || self.max.z < self.min.z
|
||||
}
|
||||
|
||||
/// Returns true if the size is zero or negative.
|
||||
#[inline]
|
||||
pub fn is_empty_or_negative(&self) -> bool {
|
||||
self.max.x <= self.min.x || self.max.y <= self.min.y || self.max.z <= self.min.z
|
||||
}
|
||||
|
||||
|
||||
#[inline]
|
||||
pub fn intersects(&self, other: &Self) -> bool {
|
||||
self.min.x < other.max.x
|
||||
&& self.max.x > other.min.x
|
||||
&& self.min.y < other.max.y
|
||||
&& self.max.y > other.min.y
|
||||
&& self.min.z < other.max.z
|
||||
&& self.max.z > other.min.z
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn try_intersection(&self, other: &Self) -> Option<Self> {
|
||||
if !self.intersects(other) {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(self.intersection(other))
|
||||
}
|
||||
|
||||
pub fn intersection(&self, other: &Self) -> Self {
|
||||
let intersection_min = TypedPoint3D::new(
|
||||
max(self.min.x, other.min.x),
|
||||
max(self.min.y, other.min.y),
|
||||
max(self.min.z, other.min.z),
|
||||
);
|
||||
|
||||
let intersection_max = TypedPoint3D::new(
|
||||
min(self.max.x, other.max.x),
|
||||
min(self.max.y, other.max.y),
|
||||
min(self.max.z, other.max.z),
|
||||
);
|
||||
|
||||
TypedBox3D::new(
|
||||
intersection_min,
|
||||
intersection_max,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
where
|
||||
T: Copy + Add<T, Output = T>,
|
||||
{
|
||||
/// Returns the same box3d, translated by a vector.
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn translate(&self, by: &TypedVector3D<T, U>) -> Self {
|
||||
Self::new(self.min + *by, self.max + *by)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
where
|
||||
T: Copy + PartialOrd + Zero,
|
||||
{
|
||||
/// Returns true if this box3d contains the point. Points are considered
|
||||
/// in the box3d if they are on the front, left or top faces, but outside if they
|
||||
/// are on the back, right or bottom faces.
|
||||
#[inline]
|
||||
pub fn contains(&self, other: &TypedPoint3D<T, U>) -> bool {
|
||||
self.min.x <= other.x && other.x < self.max.x
|
||||
&& self.min.y <= other.y && other.y < self.max.y
|
||||
&& self.min.z <= other.z && other.z < self.max.z
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
where
|
||||
T: Copy + PartialOrd + Zero + Sub<T, Output = T>,
|
||||
{
|
||||
/// Returns true if this box3d contains the interior of the other box3d. Always
|
||||
/// returns true if other is empty, and always returns false if other is
|
||||
/// nonempty but this box3d is empty.
|
||||
#[inline]
|
||||
pub fn contains_box(&self, other: &Self) -> bool {
|
||||
other.is_empty_or_negative()
|
||||
|| (self.min.x <= other.min.x && other.max.x <= self.max.x
|
||||
&& self.min.y <= other.min.y && other.max.y <= self.max.y
|
||||
&& self.min.z <= other.min.z && other.max.z <= self.max.z)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
where
|
||||
T: Copy + Sub<T, Output = T>,
|
||||
{
|
||||
#[inline]
|
||||
pub fn size(&self)-> TypedSize3D<T, U> {
|
||||
TypedSize3D::new(
|
||||
self.max.x - self.min.x,
|
||||
self.max.y - self.min.y,
|
||||
self.max.z - self.min.z,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
where
|
||||
T: Copy + PartialEq + Add<T, Output = T> + Sub<T, Output = T>,
|
||||
{
|
||||
/// Inflates the box by the specified sizes on each side respectively.
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn inflate(&self, width: T, height: T, depth: T) -> Self {
|
||||
TypedBox3D::new(
|
||||
TypedPoint3D::new(self.min.x - width, self.min.y - height, self.min.z - depth),
|
||||
TypedPoint3D::new(self.max.x + width, self.max.y + height, self.max.z + depth),
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn inflate_typed(&self, width: Length<T, U>, height: Length<T, U>, depth: Length<T, U>) -> Self {
|
||||
self.inflate(width.get(), height.get(), depth.get())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
where
|
||||
T: Copy + Zero + PartialOrd,
|
||||
{
|
||||
/// Returns the smallest box containing all of the provided points.
|
||||
pub fn from_points<I>(points: I) -> Self
|
||||
where
|
||||
I: IntoIterator,
|
||||
I::Item: Borrow<TypedPoint3D<T, U>>,
|
||||
{
|
||||
let mut points = points.into_iter();
|
||||
|
||||
// Need at least 2 different points for a valid box3d (ie: volume > 0).
|
||||
let (mut min_x, mut min_y, mut min_z) = match points.next() {
|
||||
Some(first) => (first.borrow().x, first.borrow().y, first.borrow().z),
|
||||
None => return TypedBox3D::zero(),
|
||||
};
|
||||
let (mut max_x, mut max_y, mut max_z) = (min_x, min_y, min_z);
|
||||
|
||||
{
|
||||
let mut assign_min_max = |point: I::Item| {
|
||||
let p = point.borrow();
|
||||
if p.x < min_x {
|
||||
min_x = p.x
|
||||
}
|
||||
if p.x > max_x {
|
||||
max_x = p.x
|
||||
}
|
||||
if p.y < min_y {
|
||||
min_y = p.y
|
||||
}
|
||||
if p.y > max_y {
|
||||
max_y = p.y
|
||||
}
|
||||
if p.z < min_z {
|
||||
min_z = p.z
|
||||
}
|
||||
if p.z > max_z {
|
||||
max_z = p.z
|
||||
}
|
||||
};
|
||||
|
||||
match points.next() {
|
||||
Some(second) => assign_min_max(second),
|
||||
None => return TypedBox3D::zero(),
|
||||
}
|
||||
|
||||
for point in points {
|
||||
assign_min_max(point);
|
||||
}
|
||||
}
|
||||
|
||||
Self::new(TypedPoint3D::new(min_x, min_y, min_z), TypedPoint3D::new(max_x, max_y, max_z))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
where
|
||||
T: Copy + One + Add<Output = T> + Sub<Output = T> + Mul<Output = T>,
|
||||
{
|
||||
/// Linearly interpolate between this box3d and another box3d.
|
||||
///
|
||||
/// `t` is expected to be between zero and one.
|
||||
#[inline]
|
||||
pub fn lerp(&self, other: Self, t: T) -> Self {
|
||||
Self::new(
|
||||
self.min.lerp(other.min, t),
|
||||
self.max.lerp(other.max, t),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
where
|
||||
T: Copy + One + Add<Output = T> + Div<Output = T>,
|
||||
{
|
||||
pub fn center(&self) -> TypedPoint3D<T, U> {
|
||||
let two = T::one() + T::one();
|
||||
(self.min + self.max.to_vector()) / two
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
where
|
||||
T: Copy + Clone + PartialOrd + Add<T, Output = T> + Sub<T, Output = T> + Zero,
|
||||
{
|
||||
#[inline]
|
||||
pub fn union(&self, other: &Self) -> Self {
|
||||
TypedBox3D::new(
|
||||
TypedPoint3D::new(
|
||||
min(self.min.x, other.min.x),
|
||||
min(self.min.y, other.min.y),
|
||||
min(self.min.z, other.min.z),
|
||||
),
|
||||
TypedPoint3D::new(
|
||||
max(self.max.x, other.max.x),
|
||||
max(self.max.y, other.max.y),
|
||||
max(self.max.z, other.max.z),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
#[inline]
|
||||
pub fn scale<S: Copy>(&self, x: S, y: S, z: S) -> Self
|
||||
where
|
||||
T: Mul<S, Output = T>
|
||||
{
|
||||
TypedBox3D::new(
|
||||
TypedPoint3D::new(self.min.x * x, self.min.y * y, self.min.z * z),
|
||||
TypedPoint3D::new(self.max.x * x, self.max.y * y, self.max.z * z),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
where
|
||||
T: Copy + Mul<T, Output = T> + Sub<T, Output = T>,
|
||||
{
|
||||
#[inline]
|
||||
pub fn volume(&self) -> T {
|
||||
let size = self.size();
|
||||
size.width * size.height * size.depth
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn xy_area(&self) -> T {
|
||||
let size = self.size();
|
||||
size.width * size.height
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn yz_area(&self) -> T {
|
||||
let size = self.size();
|
||||
size.depth * size.height
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn xz_area(&self) -> T {
|
||||
let size = self.size();
|
||||
size.depth * size.width
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
where
|
||||
T: Copy + Zero,
|
||||
{
|
||||
/// Constructor, setting all sides to zero.
|
||||
pub fn zero() -> Self {
|
||||
TypedBox3D::new(TypedPoint3D::zero(), TypedPoint3D::zero())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
where
|
||||
T: PartialEq,
|
||||
{
|
||||
/// Returns true if the volume is zero.
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.min.x == self.max.x || self.min.y == self.max.y || self.min.z == self.max.z
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Mul<T> for TypedBox3D<T, U>
|
||||
where
|
||||
T: Copy + Mul<T, Output = T>,
|
||||
{
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn mul(self, scale: T) -> Self {
|
||||
TypedBox3D::new(self.min * scale, self.max * scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Div<T> for TypedBox3D<T, U>
|
||||
where
|
||||
T: Copy + Div<T, Output = T>,
|
||||
{
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn div(self, scale: T) -> Self {
|
||||
TypedBox3D::new(self.min / scale, self.max / scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U1, U2> Mul<TypedScale<T, U1, U2>> for TypedBox3D<T, U1>
|
||||
where
|
||||
T: Copy + Mul<T, Output = T>,
|
||||
{
|
||||
type Output = TypedBox3D<T, U2>;
|
||||
#[inline]
|
||||
fn mul(self, scale: TypedScale<T, U1, U2>) -> TypedBox3D<T, U2> {
|
||||
TypedBox3D::new(self.min * scale, self.max * scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U1, U2> Div<TypedScale<T, U1, U2>> for TypedBox3D<T, U2>
|
||||
where
|
||||
T: Copy + Div<T, Output = T>,
|
||||
{
|
||||
type Output = TypedBox3D<T, U1>;
|
||||
#[inline]
|
||||
fn div(self, scale: TypedScale<T, U1, U2>) -> TypedBox3D<T, U1> {
|
||||
TypedBox3D::new(self.min / scale, self.max / scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Unit> TypedBox3D<T, Unit>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
/// Drop the units, preserving only the numeric value.
|
||||
pub fn to_untyped(&self) -> Box3D<T> {
|
||||
TypedBox3D::new(self.min.to_untyped(), self.max.to_untyped())
|
||||
}
|
||||
|
||||
/// Tag a unitless value with units.
|
||||
pub fn from_untyped(c: &Box3D<T>) -> TypedBox3D<T, Unit> {
|
||||
TypedBox3D::new(
|
||||
TypedPoint3D::from_untyped(&c.min),
|
||||
TypedPoint3D::from_untyped(&c.max),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T0, Unit> TypedBox3D<T0, Unit>
|
||||
where
|
||||
T0: NumCast + Copy,
|
||||
{
|
||||
/// Cast from one numeric representation to another, preserving the units.
|
||||
///
|
||||
/// When casting from floating point to integer coordinates, the decimals are truncated
|
||||
/// as one would expect from a simple cast, but this behavior does not always make sense
|
||||
/// geometrically. Consider using round(), round_in or round_out() before casting.
|
||||
pub fn cast<T1: NumCast + Copy>(&self) -> TypedBox3D<T1, Unit> {
|
||||
TypedBox3D::new(
|
||||
self.min.cast(),
|
||||
self.max.cast(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Fallible cast from one numeric representation to another, preserving the units.
|
||||
///
|
||||
/// When casting from floating point to integer coordinates, the decimals are truncated
|
||||
/// as one would expect from a simple cast, but this behavior does not always make sense
|
||||
/// geometrically. Consider using round(), round_in or round_out() before casting.
|
||||
pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<TypedBox3D<T1, Unit>> {
|
||||
match (self.min.try_cast(), self.max.try_cast()) {
|
||||
(Some(a), Some(b)) => Some(TypedBox3D::new(a, b)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
where
|
||||
T: Round,
|
||||
{
|
||||
/// Return a box3d with edges rounded to integer coordinates, such that
|
||||
/// the returned box3d has the same set of pixel centers as the original
|
||||
/// one.
|
||||
/// Values equal to 0.5 round up.
|
||||
/// Suitable for most places where integral device coordinates
|
||||
/// are needed, but note that any translation should be applied first to
|
||||
/// avoid pixel rounding errors.
|
||||
/// Note that this is *not* rounding to nearest integer if the values are negative.
|
||||
/// They are always rounding as floor(n + 0.5).
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn round(&self) -> Self {
|
||||
TypedBox3D::new(self.min.round(), self.max.round())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
where
|
||||
T: Floor + Ceil,
|
||||
{
|
||||
/// Return a box3d with faces/edges rounded to integer coordinates, such that
|
||||
/// the original box3d contains the resulting box3d.
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn round_in(&self) -> Self {
|
||||
TypedBox3D {
|
||||
min: self.min.ceil(),
|
||||
max: self.max.floor(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a box3d with faces/edges rounded to integer coordinates, such that
|
||||
/// the original box3d is contained in the resulting box3d.
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn round_out(&self) -> Self {
|
||||
TypedBox3D {
|
||||
min: self.min.floor(),
|
||||
max: self.max.ceil(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convenience functions for common casts
|
||||
impl<T: NumCast + Copy, Unit> TypedBox3D<T, Unit> {
|
||||
/// Cast into an `f32` box3d.
|
||||
pub fn to_f32(&self) -> TypedBox3D<f32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `f64` box3d.
|
||||
pub fn to_f64(&self) -> TypedBox3D<f64, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `usize` box3d, truncating decimals if any.
|
||||
///
|
||||
/// When casting from floating point cuboids, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_usize(&self) -> TypedBox3D<usize, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `u32` box3d, truncating decimals if any.
|
||||
///
|
||||
/// When casting from floating point cuboids, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_u32(&self) -> TypedBox3D<u32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `i32` box3d, truncating decimals if any.
|
||||
///
|
||||
/// When casting from floating point cuboids, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_i32(&self) -> TypedBox3D<i32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `i64` box3d, truncating decimals if any.
|
||||
///
|
||||
/// When casting from floating point cuboids, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_i64(&self) -> TypedBox3D<i64, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> From<TypedSize3D<T, U>> for TypedBox3D<T, U>
|
||||
where
|
||||
T: Copy + Zero + PartialOrd,
|
||||
{
|
||||
fn from(b: TypedSize3D<T, U>) -> Self {
|
||||
Self::from_size(b)
|
||||
}
|
||||
}
|
||||
|
||||
/// Shorthand for `TypedBox3D::new(TypedPoint3D::new(x1, y1, z1), TypedPoint3D::new(x2, y2, z2))`.
|
||||
pub fn box3d<T: Copy, U>(min_x: T, min_y: T, min_z: T, max_x: T, max_y: T, max_z: T) -> TypedBox3D<T, U> {
|
||||
TypedBox3D::new(TypedPoint3D::new(min_x, min_y, min_z), TypedPoint3D::new(max_x, max_y, max_z))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use vector::vec3;
|
||||
use size::size3;
|
||||
use point::{point3, Point3D};
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_new() {
|
||||
let b = Box3D::new(point3(-1.0, -1.0, -1.0), point3(1.0, 1.0, 1.0));
|
||||
assert!(b.min.x == -1.0);
|
||||
assert!(b.min.y == -1.0);
|
||||
assert!(b.min.z == -1.0);
|
||||
assert!(b.max.x == 1.0);
|
||||
assert!(b.max.y == 1.0);
|
||||
assert!(b.max.z == 1.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_size() {
|
||||
let b = Box3D::new(point3(-10.0, -10.0, -10.0), point3(10.0, 10.0, 10.0));
|
||||
assert!(b.size().width == 20.0);
|
||||
assert!(b.size().height == 20.0);
|
||||
assert!(b.size().depth == 20.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_center() {
|
||||
let b = Box3D::new(point3(-10.0, -10.0, -10.0), point3(10.0, 10.0, 10.0));
|
||||
assert!(b.center() == Point3D::zero());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_volume() {
|
||||
let b = Box3D::new(point3(-10.0, -10.0, -10.0), point3(10.0, 10.0, 10.0));
|
||||
assert!(b.volume() == 8000.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_area() {
|
||||
let b = Box3D::new(point3(-10.0, -10.0, -10.0), point3(10.0, 10.0, 10.0));
|
||||
assert!(b.xy_area() == 400.0);
|
||||
assert!(b.yz_area() == 400.0);
|
||||
assert!(b.xz_area() == 400.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_points() {
|
||||
let b = Box3D::from_points(&[point3(50.0, 160.0, 12.5), point3(100.0, 25.0, 200.0)]);
|
||||
assert!(b.min == point3(50.0, 25.0, 12.5));
|
||||
assert!(b.max == point3(100.0, 160.0, 200.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_min_max() {
|
||||
let b = Box3D::from_points(&[point3(50.0, 25.0, 12.5), point3(100.0, 160.0, 200.0)]);
|
||||
assert!(b.min.x == 50.0);
|
||||
assert!(b.min.y == 25.0);
|
||||
assert!(b.min.z == 12.5);
|
||||
assert!(b.max.x == 100.0);
|
||||
assert!(b.max.y == 160.0);
|
||||
assert!(b.max.z == 200.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_round_in() {
|
||||
let b = Box3D::from_points(&[point3(-25.5, -40.4, -70.9), point3(60.3, 36.5, 89.8)]).round_in();
|
||||
assert!(b.min.x == -25.0);
|
||||
assert!(b.min.y == -40.0);
|
||||
assert!(b.min.z == -70.0);
|
||||
assert!(b.max.x == 60.0);
|
||||
assert!(b.max.y == 36.0);
|
||||
assert!(b.max.z == 89.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_round_out() {
|
||||
let b = Box3D::from_points(&[point3(-25.5, -40.4, -70.9), point3(60.3, 36.5, 89.8)]).round_out();
|
||||
assert!(b.min.x == -26.0);
|
||||
assert!(b.min.y == -41.0);
|
||||
assert!(b.min.z == -71.0);
|
||||
assert!(b.max.x == 61.0);
|
||||
assert!(b.max.y == 37.0);
|
||||
assert!(b.max.z == 90.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_round() {
|
||||
let b = Box3D::from_points(&[point3(-25.5, -40.4, -70.9), point3(60.3, 36.5, 89.8)]).round();
|
||||
assert!(b.min.x == -26.0);
|
||||
assert!(b.min.y == -40.0);
|
||||
assert!(b.min.z == -71.0);
|
||||
assert!(b.max.x == 60.0);
|
||||
assert!(b.max.y == 37.0);
|
||||
assert!(b.max.z == 90.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_size() {
|
||||
let b = Box3D::from_size(size3(30.0, 40.0, 50.0));
|
||||
assert!(b.min == Point3D::zero());
|
||||
assert!(b.size().width == 30.0);
|
||||
assert!(b.size().height == 40.0);
|
||||
assert!(b.size().depth == 50.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_translate() {
|
||||
let size = size3(15.0, 15.0, 200.0);
|
||||
let mut center = (size / 2.0).to_vector().to_point();
|
||||
let b = Box3D::from_size(size);
|
||||
assert!(b.center() == center);
|
||||
let translation = vec3(10.0, 2.5, 9.5);
|
||||
let b = b.translate(&translation);
|
||||
center += translation;
|
||||
assert!(b.center() == center);
|
||||
assert!(b.max.x == 25.0);
|
||||
assert!(b.max.y == 17.5);
|
||||
assert!(b.max.z == 209.5);
|
||||
assert!(b.min.x == 10.0);
|
||||
assert!(b.min.y == 2.5);
|
||||
assert!(b.min.z == 9.5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_union() {
|
||||
let b1 = Box3D::from_points(&[point3(-20.0, -20.0, -20.0), point3(0.0, 20.0, 20.0)]);
|
||||
let b2 = Box3D::from_points(&[point3(0.0, 20.0, 20.0), point3(20.0, -20.0, -20.0)]);
|
||||
let b = b1.union(&b2);
|
||||
assert!(b.max.x == 20.0);
|
||||
assert!(b.max.y == 20.0);
|
||||
assert!(b.max.z == 20.0);
|
||||
assert!(b.min.x == -20.0);
|
||||
assert!(b.min.y == -20.0);
|
||||
assert!(b.min.z == -20.0);
|
||||
assert!(b.volume() == (40.0 * 40.0 * 40.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_intersects() {
|
||||
let b1 = Box3D::from_points(&[point3(-15.0, -20.0, -20.0), point3(10.0, 20.0, 20.0)]);
|
||||
let b2 = Box3D::from_points(&[point3(-10.0, 20.0, 20.0), point3(15.0, -20.0, -20.0)]);
|
||||
assert!(b1.intersects(&b2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_intersection() {
|
||||
let b1 = Box3D::from_points(&[point3(-15.0, -20.0, -20.0), point3(10.0, 20.0, 20.0)]);
|
||||
let b2 = Box3D::from_points(&[point3(-10.0, 20.0, 20.0), point3(15.0, -20.0, -20.0)]);
|
||||
let b = b1.intersection(&b2);
|
||||
assert!(b.max.x == 10.0);
|
||||
assert!(b.max.y == 20.0);
|
||||
assert!(b.max.z == 20.0);
|
||||
assert!(b.min.x == -10.0);
|
||||
assert!(b.min.y == -20.0);
|
||||
assert!(b.min.z == -20.0);
|
||||
assert!(b.volume() == (20.0 * 40.0 * 40.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_intersection() {
|
||||
let b1 = Box3D::from_points(&[point3(-15.0, -20.0, -20.0), point3(10.0, 20.0, 20.0)]);
|
||||
let b2 = Box3D::from_points(&[point3(-10.0, 20.0, 20.0), point3(15.0, -20.0, -20.0)]);
|
||||
assert!(b1.try_intersection(&b2).is_some());
|
||||
|
||||
let b1 = Box3D::from_points(&[point3(-15.0, -20.0, -20.0), point3(-10.0, 20.0, 20.0)]);
|
||||
let b2 = Box3D::from_points(&[point3(10.0, 20.0, 20.0), point3(15.0, -20.0, -20.0)]);
|
||||
assert!(b1.try_intersection(&b2).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_scale() {
|
||||
let b = Box3D::from_points(&[point3(-10.0, -10.0, -10.0), point3(10.0, 10.0, 10.0)]);
|
||||
let b = b.scale(0.5, 0.5, 0.5);
|
||||
assert!(b.max.x == 5.0);
|
||||
assert!(b.max.y == 5.0);
|
||||
assert!(b.max.z == 5.0);
|
||||
assert!(b.min.x == -5.0);
|
||||
assert!(b.min.y == -5.0);
|
||||
assert!(b.min.z == -5.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_zero() {
|
||||
let b = Box3D::<f64>::zero();
|
||||
assert!(b.max.x == 0.0);
|
||||
assert!(b.max.y == 0.0);
|
||||
assert!(b.max.z == 0.0);
|
||||
assert!(b.min.x == 0.0);
|
||||
assert!(b.min.y == 0.0);
|
||||
assert!(b.min.z == 0.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lerp() {
|
||||
let b1 = Box3D::from_points(&[point3(-20.0, -20.0, -20.0), point3(-10.0, -10.0, -10.0)]);
|
||||
let b2 = Box3D::from_points(&[point3(10.0, 10.0, 10.0), point3(20.0, 20.0, 20.0)]);
|
||||
let b = b1.lerp(b2, 0.5);
|
||||
assert!(b.center() == Point3D::zero());
|
||||
assert!(b.size().width == 10.0);
|
||||
assert!(b.size().height == 10.0);
|
||||
assert!(b.size().depth == 10.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_contains() {
|
||||
let b = Box3D::from_points(&[point3(-20.0, -20.0, -20.0), point3(20.0, 20.0, 20.0)]);
|
||||
assert!(b.contains(&point3(-15.3, 10.5, 18.4)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_contains_box() {
|
||||
let b1 = Box3D::from_points(&[point3(-20.0, -20.0, -20.0), point3(20.0, 20.0, 20.0)]);
|
||||
let b2 = Box3D::from_points(&[point3(-14.3, -16.5, -19.3), point3(6.7, 17.6, 2.5)]);
|
||||
assert!(b1.contains_box(&b2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_inflate() {
|
||||
let b = Box3D::from_points(&[point3(-20.0, -20.0, -20.0), point3(20.0, 20.0, 20.0)]);
|
||||
let b = b.inflate(10.0, 5.0, 2.0);
|
||||
assert!(b.size().width == 60.0);
|
||||
assert!(b.size().height == 50.0);
|
||||
assert!(b.size().depth == 44.0);
|
||||
assert!(b.center() == Point3D::zero());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_empty() {
|
||||
for i in 0..3 {
|
||||
let mut coords_neg = [-20.0, -20.0, -20.0];
|
||||
let mut coords_pos = [20.0, 20.0, 20.0];
|
||||
coords_neg[i] = 0.0;
|
||||
coords_pos[i] = 0.0;
|
||||
let b = Box3D::from_points(&[Point3D::from(coords_neg), Point3D::from(coords_pos)]);
|
||||
assert!(b.is_empty());
|
||||
}
|
||||
}
|
||||
}
|
9
third_party/rust/euclid/src/lib.rs
vendored
9
third_party/rust/euclid/src/lib.rs
vendored
@ -70,7 +70,6 @@ extern crate rand;
|
||||
#[cfg(test)]
|
||||
use std as core;
|
||||
|
||||
pub use box2d::{TypedBox2D, Box2D};
|
||||
pub use length::Length;
|
||||
pub use scale::TypedScale;
|
||||
pub use transform2d::{Transform2D, TypedTransform2D};
|
||||
@ -81,8 +80,6 @@ pub use vector::{BoolVector2D, BoolVector3D, bvec2, bvec3};
|
||||
pub use homogen::HomogeneousVector;
|
||||
|
||||
pub use rect::{rect, Rect, TypedRect};
|
||||
pub use rigid::{RigidTransform3D, TypedRigidTransform3D};
|
||||
pub use box3d::{box3d, Box3D, TypedBox3D};
|
||||
pub use translation::{TypedTranslation2D, TypedTranslation3D};
|
||||
pub use rotation::{Angle, Rotation2D, Rotation3D, TypedRotation2D, TypedRotation3D};
|
||||
pub use side_offsets::{SideOffsets2D, TypedSideOffsets2D};
|
||||
@ -93,14 +90,11 @@ pub use trig::Trig;
|
||||
mod macros;
|
||||
|
||||
pub mod approxeq;
|
||||
pub mod approxord;
|
||||
mod box2d;
|
||||
mod homogen;
|
||||
pub mod num;
|
||||
mod length;
|
||||
mod point;
|
||||
mod rect;
|
||||
mod rigid;
|
||||
mod rotation;
|
||||
mod scale;
|
||||
mod side_offsets;
|
||||
@ -110,10 +104,9 @@ mod transform3d;
|
||||
mod translation;
|
||||
mod trig;
|
||||
mod vector;
|
||||
mod box3d;
|
||||
|
||||
/// The default unit.
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct UnknownUnit;
|
||||
|
||||
/// Temporary alias to facilitate the transition to the new naming scheme
|
||||
|
81
third_party/rust/euclid/src/point.rs
vendored
81
third_party/rust/euclid/src/point.rs
vendored
@ -11,7 +11,7 @@ use super::UnknownUnit;
|
||||
use approxeq::ApproxEq;
|
||||
use length::Length;
|
||||
use scale::TypedScale;
|
||||
use size::{TypedSize2D, TypedSize3D};
|
||||
use size::TypedSize2D;
|
||||
#[cfg(feature = "mint")]
|
||||
use mint;
|
||||
use num::*;
|
||||
@ -69,12 +69,6 @@ impl<T: fmt::Display, U> fmt::Display for TypedPoint2D<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default, U> Default for TypedPoint2D<T, U> {
|
||||
fn default() -> Self {
|
||||
TypedPoint2D::new(Default::default(), Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedPoint2D<T, U> {
|
||||
/// Constructor taking scalar values directly.
|
||||
#[inline]
|
||||
@ -142,11 +136,6 @@ impl<T: Copy, U> TypedPoint2D<T, U> {
|
||||
pub fn to_array(&self) -> [T; 2] {
|
||||
[self.x, self.y]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_tuple(&self) -> (T, T) {
|
||||
(self.x, self.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Add<T, Output = T>, U> TypedPoint2D<T, U> {
|
||||
@ -422,18 +411,6 @@ impl<T: Copy, U> From<[T; 2]> for TypedPoint2D<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> Into<(T, T)> for TypedPoint2D<T, U> {
|
||||
fn into(self) -> (T, T) {
|
||||
self.to_tuple()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> From<(T, T)> for TypedPoint2D<T, U> {
|
||||
fn from(tuple: (T, T)) -> Self {
|
||||
point2(tuple.0, tuple.1)
|
||||
}
|
||||
}
|
||||
|
||||
/// A 3d Point tagged with a unit.
|
||||
#[derive(EuclidMatrix)]
|
||||
#[repr(C)]
|
||||
@ -458,11 +435,6 @@ impl<T: Copy + Zero, U> TypedPoint3D<T, U> {
|
||||
pub fn origin() -> Self {
|
||||
point3(Zero::zero(), Zero::zero(), Zero::zero())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn zero() -> Self {
|
||||
Self::origin()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + One, U> TypedPoint3D<T, U> {
|
||||
@ -470,11 +442,6 @@ impl<T: Copy + One, U> TypedPoint3D<T, U> {
|
||||
pub fn to_array_4d(&self) -> [T; 4] {
|
||||
[self.x, self.y, self.z, One::one()]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_tuple_4d(&self) -> (T, T, T, T) {
|
||||
(self.x, self.y, self.z, One::one())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedPoint3D<T, U>
|
||||
@ -507,12 +474,6 @@ impl<T: fmt::Display, U> fmt::Display for TypedPoint3D<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Default, U> Default for TypedPoint3D<T, U> {
|
||||
fn default() -> Self {
|
||||
TypedPoint3D::new(Default::default(), Default::default(), Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> TypedPoint3D<T, U> {
|
||||
/// Constructor taking scalar values directly.
|
||||
#[inline]
|
||||
@ -580,11 +541,6 @@ impl<T: Copy, U> TypedPoint3D<T, U> {
|
||||
[self.x, self.y, self.z]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_tuple(&self) -> (T, T, T) {
|
||||
(self.x, self.y, self.z)
|
||||
}
|
||||
|
||||
/// Drop the units, preserving only the numeric value.
|
||||
#[inline]
|
||||
pub fn to_untyped(&self) -> Point3D<T> {
|
||||
@ -604,13 +560,6 @@ impl<T: Copy, U> TypedPoint3D<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Add<T, Output = T>, U> TypedPoint3D<T, U> {
|
||||
#[inline]
|
||||
pub fn add_size(&self, other: &TypedSize3D<T, U>) -> Self {
|
||||
point3(self.x + other.width, self.y + other.height, self.z + other.depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Add<T, Output = T>, U> AddAssign<TypedVector3D<T, U>> for TypedPoint3D<T, U> {
|
||||
#[inline]
|
||||
fn add_assign(&mut self, other: TypedVector3D<T, U>) {
|
||||
@ -657,14 +606,6 @@ impl<T: Copy + Mul<T, Output = T>, U> Mul<T> for TypedPoint3D<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Mul<T, Output = T>, U1, U2> Mul<TypedScale<T, U1, U2>> for TypedPoint3D<T, U1> {
|
||||
type Output = TypedPoint3D<T, U2>;
|
||||
#[inline]
|
||||
fn mul(self, scale: TypedScale<T, U1, U2>) -> TypedPoint3D<T, U2> {
|
||||
point3(self.x * scale.get(), self.y * scale.get(), self.z * scale.get())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Div<T, Output = T>, U> Div<T> for TypedPoint3D<T, U> {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
@ -673,14 +614,6 @@ impl<T: Copy + Div<T, Output = T>, U> Div<T> for TypedPoint3D<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Div<T, Output = T>, U1, U2> Div<TypedScale<T, U1, U2>> for TypedPoint3D<T, U2> {
|
||||
type Output = TypedPoint3D<T, U1>;
|
||||
#[inline]
|
||||
fn div(self, scale: TypedScale<T, U1, U2>) -> TypedPoint3D<T, U1> {
|
||||
point3(self.x / scale.get(), self.y / scale.get(), self.z / scale.get())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Float, U> TypedPoint3D<T, U> {
|
||||
#[inline]
|
||||
pub fn min(self, other: Self) -> Self {
|
||||
@ -856,18 +789,6 @@ impl<T: Copy, U> From<[T; 3]> for TypedPoint3D<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> Into<(T, T, T)> for TypedPoint3D<T, U> {
|
||||
fn into(self) -> (T, T, T) {
|
||||
self.to_tuple()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> From<(T, T, T)> for TypedPoint3D<T, U> {
|
||||
fn from(tuple: (T, T, T)) -> Self {
|
||||
point3(tuple.0, tuple.1, tuple.2)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn point2<T: Copy, U>(x: T, y: T) -> TypedPoint2D<T, U> {
|
||||
TypedPoint2D::new(x, y)
|
||||
}
|
||||
|
41
third_party/rust/euclid/src/rect.rs
vendored
41
third_party/rust/euclid/src/rect.rs
vendored
@ -11,12 +11,10 @@ use super::UnknownUnit;
|
||||
use length::Length;
|
||||
use scale::TypedScale;
|
||||
use num::*;
|
||||
use box2d::TypedBox2D;
|
||||
use point::TypedPoint2D;
|
||||
use vector::TypedVector2D;
|
||||
use side_offsets::TypedSideOffsets2D;
|
||||
use size::TypedSize2D;
|
||||
use approxord::{min, max};
|
||||
|
||||
use num_traits::NumCast;
|
||||
#[cfg(feature = "serde")]
|
||||
@ -95,12 +93,6 @@ impl<T: fmt::Display, U> fmt::Display for TypedRect<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default, U> Default for TypedRect<T, U> {
|
||||
fn default() -> Self {
|
||||
TypedRect::new(Default::default(), Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedRect<T, U> {
|
||||
/// Constructor.
|
||||
pub fn new(origin: TypedPoint2D<T, U>, size: TypedSize2D<T, U>) -> Self {
|
||||
@ -264,14 +256,6 @@ where
|
||||
TypedPoint2D::new(self.max_x(), self.max_y())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_box2d(&self) -> TypedBox2D<T, U> {
|
||||
TypedBox2D {
|
||||
min: self.origin,
|
||||
max: self.bottom_right(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn translate_by_size(&self, size: &TypedSize2D<T, U>) -> Self {
|
||||
@ -444,6 +428,22 @@ impl<T: Copy + PartialEq + Zero, U> TypedRect<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn min<T: Clone + PartialOrd>(x: T, y: T) -> T {
|
||||
if x <= y {
|
||||
x
|
||||
} else {
|
||||
y
|
||||
}
|
||||
}
|
||||
|
||||
pub fn max<T: Clone + PartialOrd>(x: T, y: T) -> T {
|
||||
if x >= y {
|
||||
x
|
||||
} else {
|
||||
y
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Mul<T, Output = T>, U> Mul<T> for TypedRect<T, U> {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
@ -623,6 +623,15 @@ mod tests {
|
||||
use size::Size2D;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_min_max() {
|
||||
assert!(min(0u32, 1u32) == 0u32);
|
||||
assert!(min(-1.0f32, 0.0f32) == -1.0f32);
|
||||
|
||||
assert!(max(0u32, 1u32) == 1u32);
|
||||
assert!(max(-1.0f32, 0.0f32) == 0.0f32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_translate() {
|
||||
let p = Rect::new(Point2D::new(0u32, 0u32), Size2D::new(50u32, 40u32));
|
||||
|
261
third_party/rust/euclid/src/rigid.rs
vendored
261
third_party/rust/euclid/src/rigid.rs
vendored
@ -1,261 +0,0 @@
|
||||
use approxeq::ApproxEq;
|
||||
use num_traits::Float;
|
||||
use trig::Trig;
|
||||
use {TypedRotation3D, TypedTransform3D, TypedVector3D, UnknownUnit};
|
||||
|
||||
/// A rigid transformation. All lengths are preserved under such a transformation.
|
||||
///
|
||||
///
|
||||
/// Internally, this is a rotation and a translation, with the rotation
|
||||
/// applied first (i.e. `Rotation * Translation`, in row-vector notation)
|
||||
///
|
||||
/// This can be more efficient to use over full matrices, especially if you
|
||||
/// have to deal with the decomposed quantities often.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[repr(C)]
|
||||
pub struct TypedRigidTransform3D<T, Src, Dst> {
|
||||
pub rotation: TypedRotation3D<T, Src, Dst>,
|
||||
pub translation: TypedVector3D<T, Dst>,
|
||||
}
|
||||
|
||||
pub type RigidTransform3D<T> = TypedRigidTransform3D<T, UnknownUnit, UnknownUnit>;
|
||||
|
||||
// All matrix multiplication in this file is in row-vector notation,
|
||||
// i.e. a vector `v` is transformed with `v * T`, and if you want to apply `T1`
|
||||
// before `T2` you use `T1 * T2`
|
||||
|
||||
impl<T: Float + ApproxEq<T>, Src, Dst> TypedRigidTransform3D<T, Src, Dst> {
|
||||
/// Construct a new rigid transformation, where the `rotation` applies first
|
||||
#[inline]
|
||||
pub fn new(rotation: TypedRotation3D<T, Src, Dst>, translation: TypedVector3D<T, Dst>) -> Self {
|
||||
Self {
|
||||
rotation,
|
||||
translation,
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct an identity transform
|
||||
#[inline]
|
||||
pub fn identity() -> Self {
|
||||
Self {
|
||||
rotation: TypedRotation3D::identity(),
|
||||
translation: TypedVector3D::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a new rigid transformation, where the `translation` applies first
|
||||
#[inline]
|
||||
pub fn new_from_reversed(
|
||||
translation: TypedVector3D<T, Src>,
|
||||
rotation: TypedRotation3D<T, Src, Dst>,
|
||||
) -> Self {
|
||||
// T * R
|
||||
// = (R * R^-1) * T * R
|
||||
// = R * (R^-1 * T * R)
|
||||
// = R * T'
|
||||
//
|
||||
// T' = (R^-1 * T * R) is also a translation matrix
|
||||
// It is equivalent to the translation matrix obtained by rotating the
|
||||
// translation by R
|
||||
|
||||
let translation = rotation.rotate_vector3d(&translation);
|
||||
Self {
|
||||
rotation,
|
||||
translation,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_rotation(rotation: TypedRotation3D<T, Src, Dst>) -> Self {
|
||||
Self {
|
||||
rotation,
|
||||
translation: TypedVector3D::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_translation(translation: TypedVector3D<T, Dst>) -> Self {
|
||||
Self {
|
||||
translation,
|
||||
rotation: TypedRotation3D::identity(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Decompose this into a translation and an rotation to be applied in the opposite order
|
||||
///
|
||||
/// i.e., the translation is applied _first_
|
||||
#[inline]
|
||||
pub fn decompose_reversed(&self) -> (TypedVector3D<T, Src>, TypedRotation3D<T, Src, Dst>) {
|
||||
// self = R * T
|
||||
// = R * T * (R^-1 * R)
|
||||
// = (R * T * R^-1) * R)
|
||||
// = T' * R
|
||||
//
|
||||
// T' = (R^ * T * R^-1) is T rotated by R^-1
|
||||
|
||||
let translation = self.rotation.inverse().rotate_vector3d(&self.translation);
|
||||
(translation, self.rotation)
|
||||
}
|
||||
|
||||
/// Returns the multiplication of the two transforms such that
|
||||
/// other's transformation applies after self's transformation.
|
||||
///
|
||||
/// i.e., this produces `self * other` in row-vector notation
|
||||
#[inline]
|
||||
pub fn post_mul<Dst2>(
|
||||
&self,
|
||||
other: &TypedRigidTransform3D<T, Dst, Dst2>,
|
||||
) -> TypedRigidTransform3D<T, Src, Dst2> {
|
||||
// self = R1 * T1
|
||||
// other = R2 * T2
|
||||
// result = R1 * T1 * R2 * T2
|
||||
// = R1 * (R2 * R2^-1) * T1 * R2 * T2
|
||||
// = (R1 * R2) * (R2^-1 * T1 * R2) * T2
|
||||
// = R' * T' * T2
|
||||
// = R' * T''
|
||||
//
|
||||
// (R2^-1 * T2 * R2^) = T' = T2 rotated by R2
|
||||
// R1 * R2 = R'
|
||||
// T' * T2 = T'' = vector addition of translations T2 and T'
|
||||
|
||||
let t_prime = other
|
||||
.rotation
|
||||
.rotate_vector3d(&self.translation);
|
||||
let r_prime = self.rotation.post_rotate(&other.rotation);
|
||||
let t_prime2 = t_prime + other.translation;
|
||||
TypedRigidTransform3D {
|
||||
rotation: r_prime,
|
||||
translation: t_prime2,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the multiplication of the two transforms such that
|
||||
/// self's transformation applies after other's transformation.
|
||||
///
|
||||
/// i.e., this produces `other * self` in row-vector notation
|
||||
#[inline]
|
||||
pub fn pre_mul<Src2>(
|
||||
&self,
|
||||
other: &TypedRigidTransform3D<T, Src2, Src>,
|
||||
) -> TypedRigidTransform3D<T, Src2, Dst> {
|
||||
other.post_mul(&self)
|
||||
}
|
||||
|
||||
/// Inverts the transformation
|
||||
#[inline]
|
||||
pub fn inverse(&self) -> TypedRigidTransform3D<T, Dst, Src> {
|
||||
// result = (self)^-1
|
||||
// = (R * T)^-1
|
||||
// = T^-1 * R^-1
|
||||
// = (R^-1 * R) * T^-1 * R^-1
|
||||
// = R^-1 * (R * T^-1 * R^-1)
|
||||
// = R' * T'
|
||||
//
|
||||
// T' = (R * T^-1 * R^-1) = (-T) rotated by R^-1
|
||||
// R' = R^-1
|
||||
//
|
||||
// An easier way of writing this is to use new_from_reversed() with R^-1 and T^-1
|
||||
|
||||
TypedRigidTransform3D::new_from_reversed(
|
||||
-self.translation,
|
||||
self.rotation.inverse(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn to_transform(&self) -> TypedTransform3D<T, Src, Dst>
|
||||
where
|
||||
T: Trig,
|
||||
{
|
||||
self.translation
|
||||
.to_transform()
|
||||
.pre_mul(&self.rotation.to_transform())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Float + ApproxEq<T>, Src, Dst> From<TypedRotation3D<T, Src, Dst>>
|
||||
for TypedRigidTransform3D<T, Src, Dst>
|
||||
{
|
||||
fn from(rot: TypedRotation3D<T, Src, Dst>) -> Self {
|
||||
Self::from_rotation(rot)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Float + ApproxEq<T>, Src, Dst> From<TypedVector3D<T, Dst>>
|
||||
for TypedRigidTransform3D<T, Src, Dst>
|
||||
{
|
||||
fn from(t: TypedVector3D<T, Dst>) -> Self {
|
||||
Self::from_translation(t)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::RigidTransform3D;
|
||||
use {Rotation3D, TypedTransform3D, Vector3D};
|
||||
|
||||
#[test]
|
||||
fn test_rigid_construction() {
|
||||
let translation = Vector3D::new(12.1, 17.8, -5.5);
|
||||
let rotation = Rotation3D::unit_quaternion(0.5, -7.8, 2.2, 4.3);
|
||||
|
||||
let rigid = RigidTransform3D::new(rotation, translation);
|
||||
assert!(rigid
|
||||
.to_transform()
|
||||
.approx_eq(&translation.to_transform().pre_mul(&rotation.to_transform())));
|
||||
|
||||
let rigid = RigidTransform3D::new_from_reversed(translation, rotation);
|
||||
assert!(rigid.to_transform().approx_eq(
|
||||
&translation
|
||||
.to_transform()
|
||||
.post_mul(&rotation.to_transform())
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rigid_decomposition() {
|
||||
let translation = Vector3D::new(12.1, 17.8, -5.5);
|
||||
let rotation = Rotation3D::unit_quaternion(0.5, -7.8, 2.2, 4.3);
|
||||
|
||||
let rigid = RigidTransform3D::new(rotation, translation);
|
||||
let (t2, r2) = rigid.decompose_reversed();
|
||||
assert!(rigid
|
||||
.to_transform()
|
||||
.approx_eq(&t2.to_transform().post_mul(&r2.to_transform())));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rigid_inverse() {
|
||||
let translation = Vector3D::new(12.1, 17.8, -5.5);
|
||||
let rotation = Rotation3D::unit_quaternion(0.5, -7.8, 2.2, 4.3);
|
||||
|
||||
let rigid = RigidTransform3D::new(rotation, translation);
|
||||
let inverse = rigid.inverse();
|
||||
assert!(rigid
|
||||
.post_mul(&inverse)
|
||||
.to_transform()
|
||||
.approx_eq(&TypedTransform3D::identity()));
|
||||
assert!(inverse
|
||||
.to_transform()
|
||||
.approx_eq(&rigid.to_transform().inverse().unwrap()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rigid_multiply() {
|
||||
let translation = Vector3D::new(12.1, 17.8, -5.5);
|
||||
let rotation = Rotation3D::unit_quaternion(0.5, -7.8, 2.2, 4.3);
|
||||
let translation2 = Vector3D::new(9.3, -3.9, 1.1);
|
||||
let rotation2 = Rotation3D::unit_quaternion(0.1, 0.2, 0.3, -0.4);
|
||||
let rigid = RigidTransform3D::new(rotation, translation);
|
||||
let rigid2 = RigidTransform3D::new(rotation2, translation2);
|
||||
|
||||
assert!(rigid
|
||||
.post_mul(&rigid2)
|
||||
.to_transform()
|
||||
.approx_eq(&rigid.to_transform().post_mul(&rigid2.to_transform())));
|
||||
assert!(rigid
|
||||
.pre_mul(&rigid2)
|
||||
.to_transform()
|
||||
.approx_eq(&rigid.to_transform().pre_mul(&rigid2.to_transform())));
|
||||
}
|
||||
}
|
8
third_party/rust/euclid/src/rotation.rs
vendored
8
third_party/rust/euclid/src/rotation.rs
vendored
@ -8,7 +8,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
use approxeq::ApproxEq;
|
||||
use num_traits::{Float, FloatConst, One, Zero, NumCast};
|
||||
use num_traits::{Float, FloatConst, One, Zero};
|
||||
use core::fmt;
|
||||
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, Sub, SubAssign};
|
||||
use core::marker::PhantomData;
|
||||
@ -475,8 +475,8 @@ where
|
||||
where
|
||||
T: ApproxEq<T>,
|
||||
{
|
||||
let eps = NumCast::from(1.0e-5).unwrap();
|
||||
self.square_norm().approx_eq_eps(&T::one(), &eps)
|
||||
// TODO: we might need to relax the threshold here, because of floating point imprecision.
|
||||
self.square_norm().approx_eq(&T::one())
|
||||
}
|
||||
|
||||
/// Spherical linear interpolation between this rotation and another rotation.
|
||||
@ -560,7 +560,7 @@ where
|
||||
self.rotate_point3d(&point.to_3d()).xy()
|
||||
}
|
||||
|
||||
/// Returns the given 3d vector transformed by this rotation.
|
||||
/// Returns the given 3d vector transformed by this rotation then projected on the xy plane.
|
||||
///
|
||||
/// The input vector must be use the unit Src, and the returned point has the unit Dst.
|
||||
#[inline]
|
||||
|
16
third_party/rust/euclid/src/side_offsets.rs
vendored
16
third_party/rust/euclid/src/side_offsets.rs
vendored
@ -17,7 +17,7 @@ use core::fmt;
|
||||
use core::ops::Add;
|
||||
use core::marker::PhantomData;
|
||||
|
||||
/// A group of 2D side offsets, which correspond to top/left/bottom/right for borders, padding,
|
||||
/// A group of side offsets, which correspond to top/left/bottom/right for borders, padding,
|
||||
/// and margins in CSS, optionally tagged with a unit.
|
||||
#[derive(EuclidMatrix)]
|
||||
#[repr(C)]
|
||||
@ -40,19 +40,7 @@ impl<T: fmt::Debug, U> fmt::Debug for TypedSideOffsets2D<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default, U> Default for TypedSideOffsets2D<T, U> {
|
||||
fn default() -> Self {
|
||||
TypedSideOffsets2D {
|
||||
top: Default::default(),
|
||||
right: Default::default(),
|
||||
bottom: Default::default(),
|
||||
left: Default::default(),
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The default 2D side offset type with no unit.
|
||||
/// The default side offset type with no unit.
|
||||
pub type SideOffsets2D<T> = TypedSideOffsets2D<T, UnknownUnit>;
|
||||
|
||||
impl<T: Copy, U> TypedSideOffsets2D<T, U> {
|
||||
|
418
third_party/rust/euclid/src/size.rs
vendored
418
third_party/rust/euclid/src/size.rs
vendored
@ -13,7 +13,6 @@ use mint;
|
||||
use length::Length;
|
||||
use scale::TypedScale;
|
||||
use vector::{TypedVector2D, vec2, BoolVector2D};
|
||||
use vector::{TypedVector3D, vec3, BoolVector3D};
|
||||
use num::*;
|
||||
|
||||
use num_traits::{Float, NumCast, Signed};
|
||||
@ -48,12 +47,6 @@ impl<T: fmt::Display, U> fmt::Display for TypedSize2D<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default, U> Default for TypedSize2D<T, U> {
|
||||
fn default() -> Self {
|
||||
TypedSize2D::new(Default::default(), Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedSize2D<T, U> {
|
||||
/// Constructor taking scalar values.
|
||||
pub fn new(width: T, height: T) -> Self {
|
||||
@ -205,11 +198,6 @@ impl<T: Copy, U> TypedSize2D<T, U> {
|
||||
[self.width, self.height]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_tuple(&self) -> (T, T) {
|
||||
(self.width, self.height)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_vector(&self) -> TypedVector2D<T, U> {
|
||||
vec2(self.width, self.height)
|
||||
@ -392,29 +380,6 @@ impl<T, U> Into<mint::Vector2<T>> for TypedSize2D<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> Into<[T; 2]> for TypedSize2D<T, U> {
|
||||
fn into(self) -> [T; 2] {
|
||||
self.to_array()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> From<[T; 2]> for TypedSize2D<T, U> {
|
||||
fn from(array: [T; 2]) -> Self {
|
||||
size2(array[0], array[1])
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> Into<(T, T)> for TypedSize2D<T, U> {
|
||||
fn into(self) -> (T, T) {
|
||||
self.to_tuple()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> From<(T, T)> for TypedSize2D<T, U> {
|
||||
fn from(tuple: (T, T)) -> Self {
|
||||
size2(tuple.0, tuple.1)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod size2d {
|
||||
@ -476,386 +441,3 @@ mod size2d {
|
||||
assert_eq!(s1, s2);
|
||||
}
|
||||
}
|
||||
|
||||
/// A 3d size tagged with a unit.
|
||||
#[derive(EuclidMatrix)]
|
||||
#[repr(C)]
|
||||
pub struct TypedSize3D<T, U> {
|
||||
pub width: T,
|
||||
pub height: T,
|
||||
pub depth: T,
|
||||
#[doc(hidden)]
|
||||
pub _unit: PhantomData<U>,
|
||||
}
|
||||
|
||||
/// Default 3d size type with no unit.
|
||||
///
|
||||
/// `Size3D` provides the same methods as `TypedSize3D`.
|
||||
pub type Size3D<T> = TypedSize3D<T, UnknownUnit>;
|
||||
|
||||
impl<T: fmt::Debug, U> fmt::Debug for TypedSize3D<T, U> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{:?}×{:?}×{:?}", self.width, self.height, self.depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Display, U> fmt::Display for TypedSize3D<T, U> {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(formatter, "({}x{}x{})", self.width, self.height, self.depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default, U> Default for TypedSize3D<T, U> {
|
||||
fn default() -> Self {
|
||||
TypedSize3D::new(Default::default(), Default::default(), Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedSize3D<T, U> {
|
||||
/// Constructor taking scalar values.
|
||||
pub fn new(width: T, height: T, depth: T) -> Self {
|
||||
TypedSize3D {
|
||||
width,
|
||||
height,
|
||||
depth,
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone, U> TypedSize3D<T, U> {
|
||||
/// Constructor taking scalar strongly typed lengths.
|
||||
pub fn from_lengths(width: Length<T, U>, height: Length<T, U>, depth: Length<T, U>) -> Self {
|
||||
TypedSize3D::new(width.get(), height.get(), depth.get())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Round, U> TypedSize3D<T, U> {
|
||||
/// Rounds each component to the nearest integer value.
|
||||
///
|
||||
/// This behavior is preserved for negative values (unlike the basic cast).
|
||||
pub fn round(&self) -> Self {
|
||||
TypedSize3D::new(self.width.round(), self.height.round(), self.depth.round())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Ceil, U> TypedSize3D<T, U> {
|
||||
/// Rounds each component to the smallest integer equal or greater than the original value.
|
||||
///
|
||||
/// This behavior is preserved for negative values (unlike the basic cast).
|
||||
pub fn ceil(&self) -> Self {
|
||||
TypedSize3D::new(self.width.ceil(), self.height.ceil(), self.depth.ceil())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Floor, U> TypedSize3D<T, U> {
|
||||
/// Rounds each component to the biggest integer equal or lower than the original value.
|
||||
///
|
||||
/// This behavior is preserved for negative values (unlike the basic cast).
|
||||
pub fn floor(&self) -> Self {
|
||||
TypedSize3D::new(self.width.floor(), self.height.floor(), self.depth.floor())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Add<T, Output = T>, U> Add for TypedSize3D<T, U> {
|
||||
type Output = Self;
|
||||
fn add(self, other: Self) -> Self {
|
||||
TypedSize3D::new(self.width + other.width, self.height + other.height, self.depth + other.depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Sub<T, Output = T>, U> Sub for TypedSize3D<T, U> {
|
||||
type Output = Self;
|
||||
fn sub(self, other: Self) -> Self {
|
||||
TypedSize3D::new(self.width - other.width, self.height - other.height, self.depth - other.depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Clone + Mul<T, Output=T>, U> TypedSize3D<T, U> {
|
||||
pub fn volume(&self) -> T {
|
||||
self.width * self.height * self.depth
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedSize3D<T, U>
|
||||
where
|
||||
T: Copy + One + Add<Output = T> + Sub<Output = T> + Mul<Output = T>,
|
||||
{
|
||||
/// Linearly interpolate between this size and another size.
|
||||
///
|
||||
/// `t` is expected to be between zero and one.
|
||||
#[inline]
|
||||
pub fn lerp(&self, other: Self, t: T) -> Self {
|
||||
let one_t = T::one() - t;
|
||||
size3(
|
||||
one_t * self.width + t * other.width,
|
||||
one_t * self.height + t * other.height,
|
||||
one_t * self.depth + t * other.depth,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Zero + PartialOrd, U> TypedSize3D<T, U> {
|
||||
pub fn is_empty_or_negative(&self) -> bool {
|
||||
let zero = T::zero();
|
||||
self.width <= zero || self.height <= zero || self.depth <= zero
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Zero, U> TypedSize3D<T, U> {
|
||||
pub fn zero() -> Self {
|
||||
TypedSize3D::new(Zero::zero(), Zero::zero(), Zero::zero())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Zero, U> Zero for TypedSize3D<T, U> {
|
||||
fn zero() -> Self {
|
||||
TypedSize3D::new(Zero::zero(), Zero::zero(), Zero::zero())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Mul<T, Output = T>, U> Mul<T> for TypedSize3D<T, U> {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn mul(self, scale: T) -> Self {
|
||||
TypedSize3D::new(self.width * scale, self.height * scale, self.depth * scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Div<T, Output = T>, U> Div<T> for TypedSize3D<T, U> {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn div(self, scale: T) -> Self {
|
||||
TypedSize3D::new(self.width / scale, self.height / scale, self.depth / scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Mul<T, Output = T>, U1, U2> Mul<TypedScale<T, U1, U2>> for TypedSize3D<T, U1> {
|
||||
type Output = TypedSize3D<T, U2>;
|
||||
#[inline]
|
||||
fn mul(self, scale: TypedScale<T, U1, U2>) -> TypedSize3D<T, U2> {
|
||||
TypedSize3D::new(self.width * scale.get(), self.height * scale.get(), self.depth * scale.get())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Div<T, Output = T>, U1, U2> Div<TypedScale<T, U1, U2>> for TypedSize3D<T, U2> {
|
||||
type Output = TypedSize3D<T, U1>;
|
||||
#[inline]
|
||||
fn div(self, scale: TypedScale<T, U1, U2>) -> TypedSize3D<T, U1> {
|
||||
TypedSize3D::new(self.width / scale.get(), self.height / scale.get(), self.depth / scale.get())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> TypedSize3D<T, U> {
|
||||
/// Returns self.width as a Length carrying the unit.
|
||||
#[inline]
|
||||
pub fn width_typed(&self) -> Length<T, U> {
|
||||
Length::new(self.width)
|
||||
}
|
||||
|
||||
/// Returns self.height as a Length carrying the unit.
|
||||
#[inline]
|
||||
pub fn height_typed(&self) -> Length<T, U> {
|
||||
Length::new(self.height)
|
||||
}
|
||||
|
||||
/// Returns self.depth as a Length carrying the unit.
|
||||
#[inline]
|
||||
pub fn depth_typed(&self) -> Length<T, U> {
|
||||
Length::new(self.depth)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_array(&self) -> [T; 3] {
|
||||
[self.width, self.height, self.depth]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_vector(&self) -> TypedVector3D<T, U> {
|
||||
vec3(self.width, self.height, self.depth)
|
||||
}
|
||||
|
||||
/// Drop the units, preserving only the numeric value.
|
||||
pub fn to_untyped(&self) -> Size3D<T> {
|
||||
TypedSize3D::new(self.width, self.height, self.depth)
|
||||
}
|
||||
|
||||
/// Tag a unitless value with units.
|
||||
pub fn from_untyped(p: &Size3D<T>) -> Self {
|
||||
TypedSize3D::new(p.width, p.height, p.depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: NumCast + Copy, Unit> TypedSize3D<T, Unit> {
|
||||
/// Cast from one numeric representation to another, preserving the units.
|
||||
///
|
||||
/// When casting from floating point to integer coordinates, the decimals are truncated
|
||||
/// as one would expect from a simple cast, but this behavior does not always make sense
|
||||
/// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
|
||||
pub fn cast<NewT: NumCast + Copy>(&self) -> TypedSize3D<NewT, Unit> {
|
||||
self.try_cast().unwrap()
|
||||
}
|
||||
|
||||
/// Fallible cast from one numeric representation to another, preserving the units.
|
||||
///
|
||||
/// When casting from floating point to integer coordinates, the decimals are truncated
|
||||
/// as one would expect from a simple cast, but this behavior does not always make sense
|
||||
/// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
|
||||
pub fn try_cast<NewT: NumCast + Copy>(&self) -> Option<TypedSize3D<NewT, Unit>> {
|
||||
match (NumCast::from(self.width), NumCast::from(self.height), NumCast::from(self.depth)) {
|
||||
(Some(w), Some(h), Some(d)) => Some(TypedSize3D::new(w, h, d)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
// Convenience functions for common casts
|
||||
|
||||
/// Cast into an `f32` size.
|
||||
pub fn to_f32(&self) -> TypedSize3D<f32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `f64` size.
|
||||
pub fn to_f64(&self) -> TypedSize3D<f64, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `uint` size, truncating decimals if any.
|
||||
///
|
||||
/// When casting from floating point sizes, it is worth considering whether
|
||||
/// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
|
||||
/// the desired conversion behavior.
|
||||
pub fn to_usize(&self) -> TypedSize3D<usize, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `u32` size, truncating decimals if any.
|
||||
///
|
||||
/// When casting from floating point sizes, it is worth considering whether
|
||||
/// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
|
||||
/// the desired conversion behavior.
|
||||
pub fn to_u32(&self) -> TypedSize3D<u32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `i32` size, truncating decimals if any.
|
||||
///
|
||||
/// When casting from floating point sizes, it is worth considering whether
|
||||
/// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
|
||||
/// the desired conversion behavior.
|
||||
pub fn to_i32(&self) -> TypedSize3D<i32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `i64` size, truncating decimals if any.
|
||||
///
|
||||
/// When casting from floating point sizes, it is worth considering whether
|
||||
/// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
|
||||
/// the desired conversion behavior.
|
||||
pub fn to_i64(&self) -> TypedSize3D<i64, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedSize3D<T, U>
|
||||
where
|
||||
T: Signed,
|
||||
{
|
||||
pub fn abs(&self) -> Self {
|
||||
size3(self.width.abs(), self.height.abs(), self.depth.abs())
|
||||
}
|
||||
|
||||
pub fn is_positive(&self) -> bool {
|
||||
self.width.is_positive() && self.height.is_positive() && self.depth.is_positive()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PartialOrd, U> TypedSize3D<T, U> {
|
||||
pub fn greater_than(&self, other: &Self) -> BoolVector3D {
|
||||
BoolVector3D {
|
||||
x: self.width > other.width,
|
||||
y: self.height > other.height,
|
||||
z: self.depth > other.depth,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lower_than(&self, other: &Self) -> BoolVector3D {
|
||||
BoolVector3D {
|
||||
x: self.width < other.width,
|
||||
y: self.height < other.height,
|
||||
z: self.depth < other.depth,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<T: PartialEq, U> TypedSize3D<T, U> {
|
||||
pub fn equal(&self, other: &Self) -> BoolVector3D {
|
||||
BoolVector3D {
|
||||
x: self.width == other.width,
|
||||
y: self.height == other.height,
|
||||
z: self.depth == other.depth,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn not_equal(&self, other: &Self) -> BoolVector3D {
|
||||
BoolVector3D {
|
||||
x: self.width != other.width,
|
||||
y: self.height != other.height,
|
||||
z: self.depth != other.depth,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Float, U> TypedSize3D<T, U> {
|
||||
#[inline]
|
||||
pub fn min(self, other: Self) -> Self {
|
||||
size3(
|
||||
self.width.min(other.width),
|
||||
self.height.min(other.height),
|
||||
self.depth.min(other.depth),
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn max(self, other: Self) -> Self {
|
||||
size3(
|
||||
self.width.max(other.width),
|
||||
self.height.max(other.height),
|
||||
self.depth.max(other.depth),
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn clamp(&self, start: Self, end: Self) -> Self {
|
||||
self.max(start).min(end)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Shorthand for `TypedSize3D::new(w, h, d)`.
|
||||
pub fn size3<T, U>(w: T, h: T, d: T) -> TypedSize3D<T, U> {
|
||||
TypedSize3D::new(w, h, d)
|
||||
}
|
||||
|
||||
#[cfg(feature = "mint")]
|
||||
impl<T, U> From<mint::Vector3<T>> for TypedSize3D<T, U> {
|
||||
fn from(v: mint::Vector3<T>) -> Self {
|
||||
TypedSize3D {
|
||||
width: v.x,
|
||||
height: v.y,
|
||||
depth: v.z,
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "mint")]
|
||||
impl<T, U> Into<mint::Vector3<T>> for TypedSize3D<T, U> {
|
||||
fn into(self) -> mint::Vector3<T> {
|
||||
mint::Vector3 {
|
||||
x: self.width,
|
||||
y: self.height,
|
||||
z: self.depth,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
40
third_party/rust/euclid/src/transform2d.rs
vendored
40
third_party/rust/euclid/src/transform2d.rs
vendored
@ -35,10 +35,6 @@ use num_traits::NumCast;
|
||||
/// A pre-transformation corresponds to adding an operation that is applied before
|
||||
/// the rest of the transformation, while a post-transformation adds an operation
|
||||
/// that is applied after.
|
||||
///
|
||||
/// These transforms are for working with _row vectors_, so the matrix math for transforming
|
||||
/// a vector is `v * T`. If your library is using column vectors, use `row_major` functions when you
|
||||
/// are asked for `column_major` representations and vice versa.
|
||||
#[repr(C)]
|
||||
#[derive(EuclidMatrix)]
|
||||
pub struct TypedTransform2D<T, Src, Dst> {
|
||||
@ -54,10 +50,6 @@ pub type Transform2D<T> = TypedTransform2D<T, UnknownUnit, UnknownUnit>;
|
||||
|
||||
impl<T: Copy, Src, Dst> TypedTransform2D<T, Src, Dst> {
|
||||
/// Create a transform specifying its matrix elements in row-major order.
|
||||
///
|
||||
/// Beware: This library is written with the assumption that row vectors
|
||||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), then please use `column_major`
|
||||
pub fn row_major(m11: T, m12: T, m21: T, m22: T, m31: T, m32: T) -> Self {
|
||||
TypedTransform2D {
|
||||
m11, m12,
|
||||
@ -68,10 +60,6 @@ impl<T: Copy, Src, Dst> TypedTransform2D<T, Src, Dst> {
|
||||
}
|
||||
|
||||
/// Create a transform specifying its matrix elements in column-major order.
|
||||
///
|
||||
/// Beware: This library is written with the assumption that row vectors
|
||||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), then please use `row_major`
|
||||
pub fn column_major(m11: T, m21: T, m31: T, m12: T, m22: T, m32: T) -> Self {
|
||||
TypedTransform2D {
|
||||
m11, m12,
|
||||
@ -83,10 +71,6 @@ impl<T: Copy, Src, Dst> TypedTransform2D<T, Src, Dst> {
|
||||
|
||||
/// Returns an array containing this transform's terms in row-major order (the order
|
||||
/// in which the transform is actually laid out in memory).
|
||||
///
|
||||
/// Beware: This library is written with the assumption that row vectors
|
||||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), then please use `to_column_major_array`
|
||||
pub fn to_row_major_array(&self) -> [T; 6] {
|
||||
[
|
||||
self.m11, self.m12,
|
||||
@ -96,10 +80,6 @@ impl<T: Copy, Src, Dst> TypedTransform2D<T, Src, Dst> {
|
||||
}
|
||||
|
||||
/// Returns an array containing this transform's terms in column-major order.
|
||||
///
|
||||
/// Beware: This library is written with the assumption that row vectors
|
||||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), then please use `to_row_major_array`
|
||||
pub fn to_column_major_array(&self) -> [T; 6] {
|
||||
[
|
||||
self.m11, self.m21, self.m31,
|
||||
@ -111,10 +91,6 @@ impl<T: Copy, Src, Dst> TypedTransform2D<T, Src, Dst> {
|
||||
/// as arrays.
|
||||
///
|
||||
/// This is a convenience method to interface with other libraries like glium.
|
||||
///
|
||||
/// Beware: This library is written with the assumption that row vectors
|
||||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), this will return column major arrays.
|
||||
pub fn to_row_arrays(&self) -> [[T; 2]; 3] {
|
||||
[
|
||||
[self.m11, self.m12],
|
||||
@ -124,10 +100,6 @@ impl<T: Copy, Src, Dst> TypedTransform2D<T, Src, Dst> {
|
||||
}
|
||||
|
||||
/// Creates a transform from an array of 6 elements in row-major order.
|
||||
///
|
||||
/// Beware: This library is written with the assumption that row vectors
|
||||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), please provide a column major array.
|
||||
pub fn from_row_major_array(array: [T; 6]) -> Self {
|
||||
Self::row_major(
|
||||
array[0], array[1],
|
||||
@ -137,10 +109,6 @@ impl<T: Copy, Src, Dst> TypedTransform2D<T, Src, Dst> {
|
||||
}
|
||||
|
||||
/// Creates a transform from 3 rows of 2 elements (row-major order).
|
||||
///
|
||||
/// Beware: This library is written with the assumption that row vectors
|
||||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), please provide a column major array.
|
||||
pub fn from_row_arrays(array: [[T; 2]; 3]) -> Self {
|
||||
Self::row_major(
|
||||
array[0][0], array[0][1],
|
||||
@ -226,8 +194,6 @@ where T: Copy + Clone +
|
||||
|
||||
/// Returns the multiplication of the two matrices such that mat's transformation
|
||||
/// applies after self's transformation.
|
||||
///
|
||||
/// Assuming row vectors, this is equivalent to self * mat
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn post_mul<NewDst>(&self, mat: &TypedTransform2D<T, Dst, NewDst>) -> TypedTransform2D<T, Src, NewDst> {
|
||||
TypedTransform2D::row_major(
|
||||
@ -242,8 +208,6 @@ where T: Copy + Clone +
|
||||
|
||||
/// Returns the multiplication of the two matrices such that mat's transformation
|
||||
/// applies before self's transformation.
|
||||
///
|
||||
/// Assuming row vectors, this is equivalent to mat * self
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn pre_mul<NewSrc>(&self, mat: &TypedTransform2D<T, NewSrc, Src>) -> TypedTransform2D<T, NewSrc, Dst> {
|
||||
mat.post_mul(self)
|
||||
@ -322,8 +286,6 @@ where T: Copy + Clone +
|
||||
}
|
||||
|
||||
/// Returns the given point transformed by this transform.
|
||||
///
|
||||
/// Assuming row vectors, this is equivalent to `p * self`
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn transform_point(&self, point: &TypedPoint2D<T, Src>) -> TypedPoint2D<T, Dst> {
|
||||
@ -332,8 +294,6 @@ where T: Copy + Clone +
|
||||
}
|
||||
|
||||
/// Returns the given vector transformed by this matrix.
|
||||
///
|
||||
/// Assuming row vectors, this is equivalent to `v * self`
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn transform_vector(&self, vec: &TypedVector2D<T, Src>) -> TypedVector2D<T, Dst> {
|
||||
|
51
third_party/rust/euclid/src/transform3d.rs
vendored
51
third_party/rust/euclid/src/transform3d.rs
vendored
@ -37,10 +37,6 @@ use num_traits::NumCast;
|
||||
/// A pre-transformation corresponds to adding an operation that is applied before
|
||||
/// the rest of the transformation, while a post-transformation adds an operation
|
||||
/// that is applied after.
|
||||
///
|
||||
/// These transforms are for working with _row vectors_, so the matrix math for transforming
|
||||
/// a vector is `v * T`. If your library is using column vectors, use `row_major` functions when you
|
||||
/// are asked for `column_major` representations and vice versa.
|
||||
#[derive(EuclidMatrix)]
|
||||
#[repr(C)]
|
||||
pub struct TypedTransform3D<T, Src, Dst> {
|
||||
@ -60,10 +56,6 @@ impl<T, Src, Dst> TypedTransform3D<T, Src, Dst> {
|
||||
///
|
||||
/// For example, the translation terms m41, m42, m43 on the last row with the
|
||||
/// row-major convention) are the 13rd, 14th and 15th parameters.
|
||||
///
|
||||
/// Beware: This library is written with the assumption that row vectors
|
||||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), then please use `column_major`
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
|
||||
pub fn row_major(
|
||||
@ -85,10 +77,6 @@ impl<T, Src, Dst> TypedTransform3D<T, Src, Dst> {
|
||||
///
|
||||
/// For example, the translation terms m41, m42, m43 on the last column with the
|
||||
/// column-major convention) are the 4th, 8th and 12nd parameters.
|
||||
///
|
||||
/// Beware: This library is written with the assumption that row vectors
|
||||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), then please use `row_major`
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
|
||||
pub fn column_major(
|
||||
@ -268,8 +256,6 @@ where T: Copy + Clone +
|
||||
|
||||
/// Returns the multiplication of the two matrices such that mat's transformation
|
||||
/// applies after self's transformation.
|
||||
///
|
||||
/// Assuming row vectors, this is equivalent to self * mat
|
||||
pub fn post_mul<NewDst>(&self, mat: &TypedTransform3D<T, Dst, NewDst>) -> TypedTransform3D<T, Src, NewDst> {
|
||||
TypedTransform3D::row_major(
|
||||
self.m11 * mat.m11 + self.m12 * mat.m21 + self.m13 * mat.m31 + self.m14 * mat.m41,
|
||||
@ -293,8 +279,6 @@ where T: Copy + Clone +
|
||||
|
||||
/// Returns the multiplication of the two matrices such that mat's transformation
|
||||
/// applies before self's transformation.
|
||||
///
|
||||
/// Assuming row vectors, this is equivalent to mat * self
|
||||
pub fn pre_mul<NewSrc>(&self, mat: &TypedTransform3D<T, NewSrc, Src>) -> TypedTransform3D<T, NewSrc, Dst> {
|
||||
mat.post_mul(self)
|
||||
}
|
||||
@ -426,8 +410,6 @@ where T: Copy + Clone +
|
||||
/// Returns the homogeneous vector corresponding to the transformed 2d point.
|
||||
///
|
||||
/// The input point must be use the unit Src, and the returned point has the unit Dst.
|
||||
///
|
||||
/// Assuming row vectors, this is equivalent to `p * self`
|
||||
#[inline]
|
||||
pub fn transform_point2d_homogeneous(
|
||||
&self, p: &TypedPoint2D<T, Src>
|
||||
@ -445,7 +427,6 @@ where T: Copy + Clone +
|
||||
///
|
||||
/// The input point must be use the unit Src, and the returned point has the unit Dst.
|
||||
///
|
||||
/// Assuming row vectors, this is equivalent to `p * self`
|
||||
#[inline]
|
||||
pub fn transform_point2d(&self, p: &TypedPoint2D<T, Src>) -> Option<TypedPoint2D<T, Dst>> {
|
||||
//Note: could use `transform_point2d_homogeneous()` but it would waste the calculus of `z`
|
||||
@ -463,8 +444,6 @@ where T: Copy + Clone +
|
||||
/// Returns the given 2d vector transformed by this matrix.
|
||||
///
|
||||
/// The input point must be use the unit Src, and the returned point has the unit Dst.
|
||||
///
|
||||
/// Assuming row vectors, this is equivalent to `v * self`
|
||||
#[inline]
|
||||
pub fn transform_vector2d(&self, v: &TypedVector2D<T, Src>) -> TypedVector2D<T, Dst> {
|
||||
vec2(
|
||||
@ -476,8 +455,6 @@ where T: Copy + Clone +
|
||||
/// Returns the homogeneous vector corresponding to the transformed 3d point.
|
||||
///
|
||||
/// The input point must be use the unit Src, and the returned point has the unit Dst.
|
||||
///
|
||||
/// Assuming row vectors, this is equivalent to `p * self`
|
||||
#[inline]
|
||||
pub fn transform_point3d_homogeneous(
|
||||
&self, p: &TypedPoint3D<T, Src>
|
||||
@ -494,8 +471,6 @@ where T: Copy + Clone +
|
||||
/// or `None` otherwise.
|
||||
///
|
||||
/// The input point must be use the unit Src, and the returned point has the unit Dst.
|
||||
///
|
||||
/// Assuming row vectors, this is equivalent to `p * self`
|
||||
#[inline]
|
||||
pub fn transform_point3d(&self, p: &TypedPoint3D<T, Src>) -> Option<TypedPoint3D<T, Dst>> {
|
||||
self.transform_point3d_homogeneous(p).to_point3d()
|
||||
@ -504,8 +479,6 @@ where T: Copy + Clone +
|
||||
/// Returns the given 3d vector transformed by this matrix.
|
||||
///
|
||||
/// The input point must be use the unit Src, and the returned point has the unit Dst.
|
||||
///
|
||||
/// Assuming row vectors, this is equivalent to `v * self`
|
||||
#[inline]
|
||||
pub fn transform_vector3d(&self, v: &TypedVector3D<T, Src>) -> TypedVector3D<T, Dst> {
|
||||
vec3(
|
||||
@ -691,10 +664,6 @@ where T: Copy + Clone +
|
||||
impl<T: Copy, Src, Dst> TypedTransform3D<T, Src, Dst> {
|
||||
/// Returns an array containing this transform's terms in row-major order (the order
|
||||
/// in which the transform is actually laid out in memory).
|
||||
///
|
||||
/// Beware: This library is written with the assumption that row vectors
|
||||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), then please use `to_column_major_array`
|
||||
pub fn to_row_major_array(&self) -> [T; 16] {
|
||||
[
|
||||
self.m11, self.m12, self.m13, self.m14,
|
||||
@ -705,10 +674,6 @@ impl<T: Copy, Src, Dst> TypedTransform3D<T, Src, Dst> {
|
||||
}
|
||||
|
||||
/// Returns an array containing this transform's terms in column-major order.
|
||||
///
|
||||
/// Beware: This library is written with the assumption that row vectors
|
||||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), then please use `to_row_major_array`
|
||||
pub fn to_column_major_array(&self) -> [T; 16] {
|
||||
[
|
||||
self.m11, self.m21, self.m31, self.m41,
|
||||
@ -722,10 +687,6 @@ impl<T: Copy, Src, Dst> TypedTransform3D<T, Src, Dst> {
|
||||
/// as arrays.
|
||||
///
|
||||
/// This is a convenience method to interface with other libraries like glium.
|
||||
///
|
||||
/// Beware: This library is written with the assumption that row vectors
|
||||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), then please use `to_column_arrays`
|
||||
pub fn to_row_arrays(&self) -> [[T; 4]; 4] {
|
||||
[
|
||||
[self.m11, self.m12, self.m13, self.m14],
|
||||
@ -739,10 +700,6 @@ impl<T: Copy, Src, Dst> TypedTransform3D<T, Src, Dst> {
|
||||
/// or 4 rows in column-major order) as arrays.
|
||||
///
|
||||
/// This is a convenience method to interface with other libraries like glium.
|
||||
///
|
||||
/// Beware: This library is written with the assumption that row vectors
|
||||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), then please use `to_row_arrays`
|
||||
pub fn to_column_arrays(&self) -> [[T; 4]; 4] {
|
||||
[
|
||||
[self.m11, self.m21, self.m31, self.m41],
|
||||
@ -753,10 +710,6 @@ impl<T: Copy, Src, Dst> TypedTransform3D<T, Src, Dst> {
|
||||
}
|
||||
|
||||
/// Creates a transform from an array of 16 elements in row-major order.
|
||||
///
|
||||
/// Beware: This library is written with the assumption that row vectors
|
||||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), please provide column-major data to this function.
|
||||
pub fn from_array(array: [T; 16]) -> Self {
|
||||
Self::row_major(
|
||||
array[0], array[1], array[2], array[3],
|
||||
@ -767,10 +720,6 @@ impl<T: Copy, Src, Dst> TypedTransform3D<T, Src, Dst> {
|
||||
}
|
||||
|
||||
/// Creates a transform from 4 rows of 4 elements (row-major order).
|
||||
///
|
||||
/// Beware: This library is written with the assumption that row vectors
|
||||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), please provide column-major data to tis function.
|
||||
pub fn from_row_arrays(array: [[T; 4]; 4]) -> Self {
|
||||
Self::row_major(
|
||||
array[0][0], array[0][1], array[0][2], array[0][3],
|
||||
|
10
third_party/rust/euclid/src/translation.rs
vendored
10
third_party/rust/euclid/src/translation.rs
vendored
@ -63,11 +63,6 @@ where
|
||||
pub fn to_array(&self) -> [T; 2] {
|
||||
[self.x, self.y]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_tuple(&self) -> (T, T) {
|
||||
(self.x, self.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> TypedTranslation2D<T, Src, Dst>
|
||||
@ -269,11 +264,6 @@ where
|
||||
pub fn to_array(&self) -> [T; 3] {
|
||||
[self.x, self.y, self.z]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_tuple(&self) -> (T, T, T) {
|
||||
(self.x, self.y, self.z)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> TypedTranslation3D<T, Src, Dst>
|
||||
|
96
third_party/rust/euclid/src/vector.rs
vendored
96
third_party/rust/euclid/src/vector.rs
vendored
@ -15,8 +15,6 @@ use mint;
|
||||
use point::{TypedPoint2D, TypedPoint3D, point2, point3};
|
||||
use size::{TypedSize2D, size2};
|
||||
use scale::TypedScale;
|
||||
use transform2d::TypedTransform2D;
|
||||
use transform3d::TypedTransform3D;
|
||||
use trig::Trig;
|
||||
use Angle;
|
||||
use num::*;
|
||||
@ -68,12 +66,6 @@ impl<T: fmt::Display, U> fmt::Display for TypedVector2D<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default, U> Default for TypedVector2D<T, U> {
|
||||
fn default() -> Self {
|
||||
TypedVector2D::new(Default::default(), Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedVector2D<T, U> {
|
||||
/// Constructor taking scalar values directly.
|
||||
#[inline]
|
||||
@ -143,39 +135,10 @@ impl<T: Copy, U> TypedVector2D<T, U> {
|
||||
vec2(p.x, p.y)
|
||||
}
|
||||
|
||||
/// Cast the unit
|
||||
#[inline]
|
||||
pub fn cast_unit<V>(&self) -> TypedVector2D<T, V> {
|
||||
vec2(self.x, self.y)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_array(&self) -> [T; 2] {
|
||||
[self.x, self.y]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_tuple(&self) -> (T, T) {
|
||||
(self.x, self.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedVector2D<T, U>
|
||||
where
|
||||
T: Copy
|
||||
+ Clone
|
||||
+ Add<T, Output = T>
|
||||
+ Mul<T, Output = T>
|
||||
+ Div<T, Output = T>
|
||||
+ Sub<T, Output = T>
|
||||
+ Trig
|
||||
+ PartialOrd
|
||||
+ One
|
||||
+ Zero {
|
||||
#[inline]
|
||||
pub fn to_transform(&self) -> TypedTransform2D<T, U, U> {
|
||||
TypedTransform2D::create_translation(self.x, self.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedVector2D<T, U>
|
||||
@ -499,18 +462,6 @@ impl<T: Copy, U> From<[T; 2]> for TypedVector2D<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> Into<(T, T)> for TypedVector2D<T, U> {
|
||||
fn into(self) -> (T, T) {
|
||||
self.to_tuple()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> From<(T, T)> for TypedVector2D<T, U> {
|
||||
fn from(tuple: (T, T)) -> Self {
|
||||
vec2(tuple.0, tuple.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedVector2D<T, U>
|
||||
where
|
||||
T: Signed,
|
||||
@ -549,11 +500,6 @@ impl<T: Copy + Zero, U> TypedVector3D<T, U> {
|
||||
pub fn to_array_4d(&self) -> [T; 4] {
|
||||
[self.x, self.y, self.z, Zero::zero()]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_tuple_4d(&self) -> (T, T, T, T) {
|
||||
(self.x, self.y, self.z, Zero::zero())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Debug, U> fmt::Debug for TypedVector3D<T, U> {
|
||||
@ -568,12 +514,6 @@ impl<T: fmt::Display, U> fmt::Display for TypedVector3D<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default, U> Default for TypedVector3D<T, U> {
|
||||
fn default() -> Self {
|
||||
TypedVector3D::new(Default::default(), Default::default(), Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedVector3D<T, U> {
|
||||
/// Constructor taking scalar values directly.
|
||||
#[inline]
|
||||
@ -643,11 +583,6 @@ impl<T: Copy, U> TypedVector3D<T, U> {
|
||||
[self.x, self.y, self.z]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_tuple(&self) -> (T, T, T) {
|
||||
(self.x, self.y, self.z)
|
||||
}
|
||||
|
||||
/// Drop the units, preserving only the numeric value.
|
||||
#[inline]
|
||||
pub fn to_untyped(&self) -> Vector3D<T> {
|
||||
@ -667,25 +602,6 @@ impl<T: Copy, U> TypedVector3D<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedVector3D<T, U>
|
||||
where
|
||||
T: Copy
|
||||
+ Clone
|
||||
+ Add<T, Output = T>
|
||||
+ Mul<T, Output = T>
|
||||
+ Div<T, Output = T>
|
||||
+ Sub<T, Output = T>
|
||||
+ Trig
|
||||
+ PartialOrd
|
||||
+ One
|
||||
+ Zero
|
||||
+ Neg<Output = T> {
|
||||
#[inline]
|
||||
pub fn to_transform(&self) -> TypedTransform3D<T, U, U> {
|
||||
TypedTransform3D::create_translation(self.x, self.y, self.z)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Mul<T, Output = T> + Add<T, Output = T> + Sub<T, Output = T> + Copy, U>
|
||||
TypedVector3D<T, U> {
|
||||
// Dot product.
|
||||
@ -1014,18 +930,6 @@ impl<T: Copy, U> From<[T; 3]> for TypedVector3D<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> Into<(T, T, T)> for TypedVector3D<T, U> {
|
||||
fn into(self) -> (T, T, T) {
|
||||
self.to_tuple()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> From<(T, T, T)> for TypedVector3D<T, U> {
|
||||
fn from(tuple: (T, T, T)) -> Self {
|
||||
vec3(tuple.0, tuple.1, tuple.2)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedVector3D<T, U>
|
||||
where
|
||||
T: Signed,
|
||||
|
@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"e32cf0f1999d39d32e222b28b26ccc431533204f6ae4f96afc55f0231900126b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"11f6eec1a694070311f8ff191c53e67b90bf1d5064f32d684a1b73b1c3264ac1","crates-io.md":"131dee2d4beaf83485aed22942b98815ef65af9bcfb65f02b5b90c59b8bc7b8b","src/bound.rs":"346f20898b86432bad7ea86207b0b395d52fe804cb4b0f9805ba6f3ff58f9cd0","src/de.rs":"c7fba9a1206b11a17bd6445a9d6945f5171c7e81587f90aaf26732f50126dad7","src/dummy.rs":"413f639118681cecff6188e790c88636e34dd8e1b247bbbaa7b6a121b5cf6921","src/fragment.rs":"5819ac5b16f5945c05ce47c3370745f2e73deb415367ae6afbd8208867f611d2","src/internals/ast.rs":"b0a791275ea3d6f0e7b698e0758757dc6a4a5ce25ae45a9adfe70c1ac878fb34","src/internals/attr.rs":"f95eb8481822f4b5eca5e28483469c020d73335d60980cb20e1c28a073b90f52","src/internals/case.rs":"b2024f414f5d832bafa53b9ae7924b2d43a29175b19bb3da36f15c9071666558","src/internals/check.rs":"5beb3d32fcdf689dfce60eb4d5cf8f0167dcde3286e8075f8e40cb4aa714b8ad","src/internals/ctxt.rs":"ceb74c96802f89de896a30b774b49d4954d6c3344596cbbc1ff8fad2ac754fe1","src/internals/mod.rs":"8e363739bbfcd43bcaedd1746b2d17cebd5964167c145bd0db473f0ff4521edc","src/lib.rs":"fd6883d899ea98448aee074374388fdfd8792363928cc1ddd3812737c5921a76","src/pretend.rs":"24c7c4168cf176e77e718627ab81c1055481187d1551282f20416c01af895891","src/ser.rs":"1ee1499c317f5c8fadc21cb60ee9f114a748a17da4a52219ed03ec7eb3f894a8","src/try.rs":"b9a10c8690d442a57fc7097d42c9a4f13034c7b4a30b7eb02d538fdbf8ae0a8d"},"package":"beed18e6f5175aef3ba670e57c60ef3b1b74d250d962a26604bff4c80e970dd4"}
|
||||
{"files":{"Cargo.toml":"071ea0d1ef1e899f01b0e90383b7dfefdf1b23c733444c59815ce345e7833054","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"11f6eec1a694070311f8ff191c53e67b90bf1d5064f32d684a1b73b1c3264ac1","crates-io.md":"131dee2d4beaf83485aed22942b98815ef65af9bcfb65f02b5b90c59b8bc7b8b","src/bound.rs":"47b4018d54220862c2546589fe3cbccdd72c5d90438c265c258c1a2ee98e9210","src/de.rs":"09ba5a4cab60dfc713ea66f69d1989786a913e060f1ec6f9b701e83f37448931","src/dummy.rs":"413f639118681cecff6188e790c88636e34dd8e1b247bbbaa7b6a121b5cf6921","src/fragment.rs":"5819ac5b16f5945c05ce47c3370745f2e73deb415367ae6afbd8208867f611d2","src/internals/ast.rs":"64cd449a627a3489053407735f0d1de669272d879a75afc66051e323a1c1ebd4","src/internals/attr.rs":"f95eb8481822f4b5eca5e28483469c020d73335d60980cb20e1c28a073b90f52","src/internals/case.rs":"b2024f414f5d832bafa53b9ae7924b2d43a29175b19bb3da36f15c9071666558","src/internals/check.rs":"d101f08b2bd007602c4a7b3f6ae2d4cb9fbe0c179cde55809a666ed4a7043a12","src/internals/ctxt.rs":"ceb74c96802f89de896a30b774b49d4954d6c3344596cbbc1ff8fad2ac754fe1","src/internals/mod.rs":"8e363739bbfcd43bcaedd1746b2d17cebd5964167c145bd0db473f0ff4521edc","src/lib.rs":"fd6883d899ea98448aee074374388fdfd8792363928cc1ddd3812737c5921a76","src/pretend.rs":"ea5aa1b338038ce1791cef34fd20091abb062cd61c0384ac931d0069413a5302","src/ser.rs":"843b2a66a17511640c4e5ebd08e16b8f58f9772c7a8283e1bb2f043b302f21be","src/try.rs":"b9a10c8690d442a57fc7097d42c9a4f13034c7b4a30b7eb02d538fdbf8ae0a8d"},"package":null}
|
56
third_party/rust/serde_derive/Cargo.toml
vendored
56
third_party/rust/serde_derive/Cargo.toml
vendored
@ -1,48 +1,32 @@
|
||||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g. crates.io) dependencies
|
||||
#
|
||||
# If you believe there's an error in this file please file an
|
||||
# issue against the rust-lang/cargo repository. If you're
|
||||
# editing this file be aware that the upstream Cargo.toml
|
||||
# will likely look very different (and much more reasonable)
|
||||
|
||||
[package]
|
||||
name = "serde_derive"
|
||||
version = "1.0.88"
|
||||
version = "1.0.88" # remember to update html_root_url
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
include = ["Cargo.toml", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
|
||||
license = "MIT/Apache-2.0"
|
||||
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
||||
homepage = "https://serde.rs"
|
||||
documentation = "https://serde.rs/derive.html"
|
||||
readme = "crates-io.md"
|
||||
keywords = ["serde", "serialization", "no_std"]
|
||||
license = "MIT/Apache-2.0"
|
||||
repository = "https://github.com/serde-rs/serde"
|
||||
documentation = "https://serde.rs/derive.html"
|
||||
keywords = ["serde", "serialization", "no_std"]
|
||||
readme = "crates-io.md"
|
||||
include = ["Cargo.toml", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APACHE", "LICENSE-MIT"]
|
||||
|
||||
[lib]
|
||||
name = "serde_derive"
|
||||
proc-macro = true
|
||||
[dependencies.proc-macro2]
|
||||
version = "0.4"
|
||||
|
||||
[dependencies.quote]
|
||||
version = "0.6.3"
|
||||
|
||||
[dependencies.syn]
|
||||
version = "0.15.22"
|
||||
features = ["visit"]
|
||||
[dev-dependencies.serde]
|
||||
version = "1.0"
|
||||
[badges]
|
||||
travis-ci = { repository = "serde-rs/serde" }
|
||||
appveyor = { repository = "serde-rs/serde" }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
deserialize_in_place = []
|
||||
[badges.appveyor]
|
||||
repository = "serde-rs/serde"
|
||||
|
||||
[badges.travis-ci]
|
||||
repository = "serde-rs/serde"
|
||||
[lib]
|
||||
name = "serde_derive"
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = "0.4"
|
||||
quote = "0.6.3"
|
||||
syn = { version = "0.15.22", features = ["visit", "extra-traits"] }
|
||||
|
||||
[dev-dependencies]
|
||||
serde = { version = "1.0", path = "../serde" }
|
||||
|
4
third_party/rust/serde_derive/src/bound.rs
vendored
4
third_party/rust/serde_derive/src/bound.rs
vendored
@ -64,7 +64,7 @@ pub fn with_where_predicates_from_variants(
|
||||
from_variant: fn(&attr::Variant) -> Option<&[syn::WherePredicate]>,
|
||||
) -> syn::Generics {
|
||||
let variants = match cont.data {
|
||||
Data::Enum(ref variants) => variants,
|
||||
Data::Enum(_, ref variants) => variants,
|
||||
Data::Struct(_, _) => {
|
||||
return generics.clone();
|
||||
}
|
||||
@ -161,7 +161,7 @@ pub fn with_bound(
|
||||
associated_type_usage: Vec::new(),
|
||||
};
|
||||
match cont.data {
|
||||
Data::Enum(ref variants) => {
|
||||
Data::Enum(_, ref variants) => {
|
||||
for variant in variants.iter() {
|
||||
let relevant_fields = variant
|
||||
.fields
|
||||
|
394
third_party/rust/serde_derive/src/de.rs
vendored
394
third_party/rust/serde_derive/src/de.rs
vendored
@ -11,6 +11,10 @@ use internals::ast::{Container, Data, Field, Style, Variant};
|
||||
use internals::{attr, Ctxt, Derive};
|
||||
use pretend;
|
||||
|
||||
#[cfg(feature = "deserialize_in_place")]
|
||||
use internals::ast::Repr;
|
||||
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result<TokenStream, Vec<syn::Error>> {
|
||||
@ -95,6 +99,7 @@ fn precondition_no_de_lifetime(cx: &Ctxt, cont: &Container) {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Parameters {
|
||||
/// Name of the type the `derive` is on.
|
||||
local: syn::Ident,
|
||||
@ -209,6 +214,7 @@ fn requires_default(field: &attr::Field, _variant: Option<&attr::Variant>) -> bo
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
enum BorrowedLifetimes {
|
||||
Borrowed(BTreeSet<syn::Lifetime>),
|
||||
Static,
|
||||
@ -265,7 +271,7 @@ fn deserialize_body(cont: &Container, params: &Parameters) -> Fragment {
|
||||
deserialize_from(type_from)
|
||||
} else if let attr::Identifier::No = cont.attrs.identifier() {
|
||||
match cont.data {
|
||||
Data::Enum(ref variants) => deserialize_enum(params, variants, &cont.attrs),
|
||||
Data::Enum(_, ref variants) => deserialize_enum(params, variants, &cont.attrs),
|
||||
Data::Struct(Style::Struct, ref fields) => {
|
||||
deserialize_struct(None, params, fields, &cont.attrs, None, &Untagged::No)
|
||||
}
|
||||
@ -276,7 +282,7 @@ fn deserialize_body(cont: &Container, params: &Parameters) -> Fragment {
|
||||
}
|
||||
} else {
|
||||
match cont.data {
|
||||
Data::Enum(ref variants) => {
|
||||
Data::Enum(_, ref variants) => {
|
||||
deserialize_custom_identifier(params, variants, &cont.attrs)
|
||||
}
|
||||
Data::Struct(_, _) => unreachable!("checked in serde_derive_internals"),
|
||||
@ -313,7 +319,14 @@ fn deserialize_in_place_body(cont: &Container, params: &Parameters) -> Option<St
|
||||
Data::Struct(Style::Tuple, ref fields) | Data::Struct(Style::Newtype, ref fields) => {
|
||||
deserialize_tuple_in_place(None, params, fields, &cont.attrs, None)
|
||||
}
|
||||
Data::Enum(_) | Data::Struct(Style::Unit, _) => {
|
||||
Data::Enum(ref repr, ref variants) => {
|
||||
if let Some(x) = deserialize_enum_in_place(params, repr, variants, &cont.attrs) {
|
||||
x
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
Data::Struct(Style::Unit, _) => {
|
||||
return None;
|
||||
}
|
||||
};
|
||||
@ -341,7 +354,7 @@ fn deserialize_in_place_body(_cont: &Container, _params: &Parameters) -> Option<
|
||||
fn deserialize_transparent(cont: &Container, params: &Parameters) -> Fragment {
|
||||
let fields = match cont.data {
|
||||
Data::Struct(_, ref fields) => fields,
|
||||
Data::Enum(_) => unreachable!(),
|
||||
Data::Enum(_, _) => unreachable!(),
|
||||
};
|
||||
|
||||
let this = ¶ms.this;
|
||||
@ -541,19 +554,28 @@ fn deserialize_tuple_in_place(
|
||||
None
|
||||
};
|
||||
|
||||
let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, &expecting));
|
||||
let visit_seq = Stmts(deserialize_seq_in_place(params, fields, is_enum, cattrs, &expecting));
|
||||
|
||||
let visitor_expr = quote! {
|
||||
__Visitor {
|
||||
place: __place,
|
||||
lifetime: _serde::export::PhantomData,
|
||||
let visitor_expr = if is_enum {
|
||||
quote! {
|
||||
__Visitor {
|
||||
place: this,
|
||||
lifetime: _serde::export::PhantomData,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
__Visitor {
|
||||
place: __place,
|
||||
lifetime: _serde::export::PhantomData,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let dispatch = if let Some(deserializer) = deserializer {
|
||||
quote!(_serde::Deserializer::deserialize_tuple(#deserializer, #nfields, #visitor_expr))
|
||||
} else if is_enum {
|
||||
quote!(_serde::de::VariantAccess::tuple_variant(__variant, #nfields, #visitor_expr))
|
||||
quote!(try!(_serde::de::VariantAccess::tuple_variant(__variant, #nfields, #visitor_expr)))
|
||||
} else if nfields == 1 {
|
||||
let type_name = cattrs.name().deserialize_name();
|
||||
quote!(_serde::Deserializer::deserialize_newtype_struct(__deserializer, #type_name, #visitor_expr))
|
||||
@ -710,9 +732,11 @@ fn deserialize_seq(
|
||||
fn deserialize_seq_in_place(
|
||||
params: &Parameters,
|
||||
fields: &[Field],
|
||||
_increment_fields: bool, // FIXME: Not needed anymore?
|
||||
cattrs: &attr::Container,
|
||||
expecting: &str,
|
||||
) -> Fragment {
|
||||
// For enums there's a secret `tag` field at the start which we shouldn't touch,
|
||||
let deserialized_count = fields
|
||||
.iter()
|
||||
.filter(|field| !field.attrs.skip_deserializing())
|
||||
@ -1039,7 +1063,7 @@ fn deserialize_struct_in_place(
|
||||
None => format!("struct {}", params.type_name()),
|
||||
};
|
||||
|
||||
let visit_seq = Stmts(deserialize_seq_in_place(params, fields, cattrs, &expecting));
|
||||
let visit_seq = Stmts(deserialize_seq_in_place(params, fields, false, cattrs, &expecting));
|
||||
|
||||
let (field_visitor, fields_stmt, visit_map) =
|
||||
deserialize_struct_as_struct_in_place_visitor(params, fields, cattrs);
|
||||
@ -1140,6 +1164,19 @@ fn deserialize_enum(
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "deserialize_in_place")]
|
||||
fn deserialize_enum_in_place(
|
||||
params: &Parameters,
|
||||
repr: &Repr,
|
||||
variants: &[Variant],
|
||||
cattrs: &attr::Container,
|
||||
) -> Option<Fragment> {
|
||||
match *cattrs.tag() {
|
||||
attr::TagType::External => deserialize_externally_tagged_enum_in_place(params, repr, variants, cattrs),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn prepare_enum_variant_enum(
|
||||
variants: &[Variant],
|
||||
cattrs: &attr::Container,
|
||||
@ -1269,6 +1306,259 @@ fn deserialize_externally_tagged_enum(
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "deserialize_in_place")]
|
||||
fn deserialize_externally_tagged_enum_in_place(
|
||||
params: &Parameters,
|
||||
repr: &Repr,
|
||||
variants: &[Variant],
|
||||
cattrs: &attr::Container,
|
||||
) -> Option<Fragment> {
|
||||
let int_repr = repr.get_stable_rust_enum_layout().map(|int_repr| {
|
||||
let int_repr = Ident::new(int_repr, Span::call_site());
|
||||
quote!(#[repr(#int_repr)])
|
||||
});
|
||||
|
||||
let unit_variant = variants.iter().position(|variant| is_unit(variant));
|
||||
let non_unit_variant = variants.iter().enumerate().find(|&(_, variant)| !is_unit(variant));
|
||||
|
||||
// We need an int_repr, unit variant, and a non-unit variant to proceed
|
||||
if int_repr.is_none() || unit_variant.is_none() || non_unit_variant.is_none() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let unit_index = unit_variant.unwrap();
|
||||
let (non_unit_index, non_unit_variant) = non_unit_variant.unwrap();
|
||||
let int_repr = int_repr.unwrap();
|
||||
|
||||
let this = ¶ms.this;
|
||||
let (de_impl_generics, de_ty_generics, ty_generics, where_clause) = split_with_de_lifetime(params,);
|
||||
let delife = params.borrowed.de_lifetime();
|
||||
|
||||
let type_name = cattrs.name().deserialize_name();
|
||||
|
||||
let expecting = format!("enum {}", params.type_name());
|
||||
|
||||
let variant_names_idents: Vec<_> = variants
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|&(_, variant)| !variant.attrs.skip_deserializing())
|
||||
.map(|(i, variant)| {
|
||||
(
|
||||
variant.attrs.name().deserialize_name(),
|
||||
field_i(i),
|
||||
variant.attrs.aliases(),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let variants_stmt = {
|
||||
let variant_names = variant_names_idents.iter().map(|&(ref name, _, _)| name);
|
||||
quote! {
|
||||
const VARIANTS: &'static [&'static str] = &[ #(#variant_names),* ];
|
||||
}
|
||||
};
|
||||
|
||||
let variant_visitor = Stmts(deserialize_generated_identifier(&variant_names_idents, cattrs, true, None),);
|
||||
|
||||
let non_unit_field = field_i(non_unit_index);
|
||||
let tag_access = match non_unit_variant.style {
|
||||
Style::Struct => {
|
||||
quote!(repr.#non_unit_field.tag)
|
||||
}
|
||||
Style::Tuple | Style::Newtype => {
|
||||
quote!(repr.#non_unit_field.0)
|
||||
}
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
let mut sub_params = params.clone();
|
||||
let variant_arms_from = variants
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|&(_, variant)| !variant.attrs.skip_deserializing())
|
||||
.map(
|
||||
|(i, variant)| {
|
||||
let variant_name = field_i(i);
|
||||
sub_params.this = syn::Path::from(variant_name.clone());
|
||||
|
||||
let this_decl = if is_unit(variant) {
|
||||
None
|
||||
} else {
|
||||
Some(quote!(let this = &mut repr.#variant_name;))
|
||||
};
|
||||
let block = Stmts(deserialize_externally_tagged_variant_in_place(&sub_params, variant, cattrs));
|
||||
quote! {
|
||||
(__Field::#variant_name, __variant) => {
|
||||
{
|
||||
#this_decl
|
||||
#block;
|
||||
}
|
||||
#tag_access = __Tag::#variant_name;
|
||||
_serde::export::Result::Ok(())
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
let all_skipped = variants
|
||||
.iter()
|
||||
.all(|variant| variant.attrs.skip_deserializing());
|
||||
|
||||
let match_variant_from = if all_skipped {
|
||||
// This is an empty enum like `enum Impossible {}` or an enum in which
|
||||
// all variants have `#[serde(skip_deserializing)]`.
|
||||
quote! {
|
||||
// FIXME: Once we drop support for Rust 1.15:
|
||||
// let _serde::export::Err(__err) = _serde::de::EnumAccess::variant::<__Field>(__data);
|
||||
// _serde::export::Err(__err)
|
||||
_serde::export::Result::map(
|
||||
_serde::de::EnumAccess::variant::<__Field>(__data),
|
||||
|(__impossible, _)| match __impossible {})
|
||||
}
|
||||
} else {
|
||||
let unit_field = field_i(unit_index);
|
||||
|
||||
quote! {
|
||||
unsafe {
|
||||
let repr = ::std::mem::transmute::<&mut #this #ty_generics, &mut __EnumRepr>(self.place);
|
||||
#tag_access = __Tag::#unit_field;
|
||||
match try!(_serde::de::EnumAccess::variant(__data)) {
|
||||
#(#variant_arms_from)*
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let repr_cases = variants
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(
|
||||
|(i, variant)| {
|
||||
if is_unit(&variant) {
|
||||
None
|
||||
} else {
|
||||
let variant_name = field_i(i);
|
||||
Some(quote!(#variant_name: #variant_name))
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
let tag_cases = variants
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(
|
||||
|(i, _variant)| {
|
||||
let variant_name = field_i(i);
|
||||
|
||||
quote!(#variant_name)
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
let repr_payloads = variants
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(
|
||||
|(i, variant)| {
|
||||
let variant_name = field_i(i);
|
||||
match variant.style {
|
||||
Style::Struct => {
|
||||
let fields = variant.fields.iter().enumerate().map(|(j, field)| {
|
||||
let field_name = field_i(j);
|
||||
let field_ty = field.ty;
|
||||
quote!(#field_name: #field_ty)
|
||||
});
|
||||
|
||||
let payload = quote! {
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[allow(non_camel_case_types)]
|
||||
struct #variant_name #ty_generics {
|
||||
tag: __Tag,
|
||||
#(#fields),*
|
||||
}
|
||||
};
|
||||
Some(payload)
|
||||
}
|
||||
Style::Tuple | Style::Newtype => {
|
||||
let fields = variant.fields.iter().map(|field| {
|
||||
let field_ty = field.ty;
|
||||
quote!(#field_ty)
|
||||
});
|
||||
|
||||
let payload = quote! {
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[allow(non_camel_case_types)]
|
||||
struct #variant_name #ty_generics (
|
||||
__Tag,
|
||||
#(#fields),*
|
||||
|
||||
);
|
||||
};
|
||||
Some(payload)
|
||||
}
|
||||
Style::Unit => None,
|
||||
}
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
let raw_repr = quote! {
|
||||
#[repr(C)]
|
||||
#[allow(non_camel_case_types)]
|
||||
union __EnumRepr #ty_generics {
|
||||
#(#repr_cases),*
|
||||
}
|
||||
|
||||
#int_repr
|
||||
#[derive(Copy, Clone)]
|
||||
#[allow(non_camel_case_types)]
|
||||
enum __Tag {
|
||||
#(#tag_cases),*
|
||||
}
|
||||
|
||||
#(#repr_payloads)*
|
||||
};
|
||||
|
||||
let de_from_impl_generics = de_impl_generics.in_place();
|
||||
let de_from_ty_generics = de_ty_generics.in_place();
|
||||
let dest_life = place_lifetime();
|
||||
|
||||
Some(quote_block! {
|
||||
#variant_visitor
|
||||
|
||||
struct __Visitor #de_from_impl_generics #where_clause {
|
||||
place: &#dest_life mut #this #ty_generics,
|
||||
lifetime: _serde::export::PhantomData<&#delife ()>,
|
||||
}
|
||||
|
||||
impl #de_from_impl_generics _serde::de::Visitor<#delife> for __Visitor #de_from_ty_generics #where_clause {
|
||||
type Value = ();
|
||||
|
||||
fn expecting(&self, formatter: &mut _serde::export::Formatter) -> _serde::export::fmt::Result {
|
||||
_serde::export::Formatter::write_str(formatter, #expecting)
|
||||
}
|
||||
|
||||
fn visit_enum<__A>(self, __data: __A) -> _serde::export::Result<Self::Value, __A::Error>
|
||||
where __A: _serde::de::EnumAccess<#delife>
|
||||
{
|
||||
#raw_repr
|
||||
|
||||
#match_variant_from
|
||||
}
|
||||
}
|
||||
|
||||
#variants_stmt
|
||||
|
||||
_serde::Deserializer::deserialize_enum(__deserializer, #type_name, VARIANTS,
|
||||
__Visitor {
|
||||
place: __place,
|
||||
lifetime: _serde::export::PhantomData,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn deserialize_internally_tagged_enum(
|
||||
params: &Parameters,
|
||||
variants: &[Variant],
|
||||
@ -1367,13 +1657,6 @@ fn deserialize_adjacently_tagged_enum(
|
||||
}
|
||||
};
|
||||
|
||||
fn is_unit(variant: &Variant) -> bool {
|
||||
match variant.style {
|
||||
Style::Unit => true,
|
||||
Style::Struct | Style::Tuple | Style::Newtype => false,
|
||||
}
|
||||
}
|
||||
|
||||
let mut missing_content = quote! {
|
||||
_serde::export::Err(<__A::Error as _serde::de::Error>::missing_field(#content))
|
||||
};
|
||||
@ -1688,6 +1971,46 @@ fn deserialize_externally_tagged_variant(
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "deserialize_in_place")]
|
||||
fn deserialize_externally_tagged_variant_in_place(
|
||||
params: &Parameters,
|
||||
variant: &Variant,
|
||||
cattrs: &attr::Container,
|
||||
) -> Fragment {
|
||||
if let Some(_path) = variant.attrs.deserialize_with() {
|
||||
unimplemented!()
|
||||
/*
|
||||
let (wrapper, wrapper_ty, unwrap_fn) =
|
||||
wrap_deserialize_variant_with(params, &variant, path);
|
||||
return quote_block! {
|
||||
#wrapper
|
||||
_serde::export::Result::map(
|
||||
_serde::de::VariantAccess::newtype_variant::<#wrapper_ty>(__variant), #unwrap_fn)
|
||||
};
|
||||
*/
|
||||
}
|
||||
|
||||
let variant_ident = &variant.ident;
|
||||
|
||||
match variant.style {
|
||||
Style::Unit => {
|
||||
quote_block! {
|
||||
try!(_serde::de::VariantAccess::unit_variant(__variant));
|
||||
}
|
||||
}
|
||||
Style::Newtype => {
|
||||
deserialize_externally_tagged_newtype_variant_in_place(variant_ident, params, &variant.fields[0])
|
||||
}
|
||||
Style::Tuple => {
|
||||
deserialize_tuple_in_place(Some(variant_ident.clone()), params, &variant.fields, cattrs, None)
|
||||
}
|
||||
Style::Struct => {
|
||||
unimplemented!()
|
||||
// deserialize_struct(None, params, &variant.fields, cattrs, None, Untagged::No).0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_internally_tagged_variant(
|
||||
params: &Parameters,
|
||||
variant: &Variant,
|
||||
@ -1812,6 +2135,34 @@ fn deserialize_externally_tagged_newtype_variant(
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "deserialize_in_place")]
|
||||
fn deserialize_externally_tagged_newtype_variant_in_place(
|
||||
_variant_ident: &syn::Ident,
|
||||
params: &Parameters,
|
||||
field: &Field,
|
||||
) -> Fragment {
|
||||
let _this = ¶ms.this;
|
||||
match field.attrs.deserialize_with() {
|
||||
None => {
|
||||
quote_expr! {
|
||||
try!(_serde::de::VariantAccess::newtype_variant_seed(__variant, _serde::private::de::InPlaceSeed(&mut this.1)));
|
||||
}
|
||||
}
|
||||
Some(_path) => {
|
||||
unimplemented!();
|
||||
/*
|
||||
let (wrapper, wrapper_ty) = wrap_deserialize_field_with(params, field.ty, path);
|
||||
quote_block! {
|
||||
#wrapper
|
||||
_serde::export::Result::map(
|
||||
_serde::de::VariantAccess::newtype_variant::<#wrapper_ty>(__variant),
|
||||
|__wrapper| #this::#variant_ident(__wrapper.value))
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_untagged_newtype_variant(
|
||||
variant_ident: &syn::Ident,
|
||||
params: &Parameters,
|
||||
@ -3001,3 +3352,10 @@ fn split_with_de_lifetime(
|
||||
let (_, ty_generics, where_clause) = params.generics.split_for_impl();
|
||||
(de_impl_generics, de_ty_generics, ty_generics, where_clause)
|
||||
}
|
||||
|
||||
fn is_unit(variant: &Variant) -> bool {
|
||||
match variant.style {
|
||||
Style::Unit => true,
|
||||
Style::Struct | Style::Tuple | Style::Newtype => false,
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ pub struct Container<'a> {
|
||||
///
|
||||
/// Analagous to `syn::Data`.
|
||||
pub enum Data<'a> {
|
||||
Enum(Vec<Variant<'a>>),
|
||||
Enum(Repr, Vec<Variant<'a>>),
|
||||
Struct(Style, Vec<Field<'a>>),
|
||||
}
|
||||
|
||||
@ -46,6 +46,12 @@ pub struct Field<'a> {
|
||||
pub original: &'a syn::Field,
|
||||
}
|
||||
|
||||
pub struct Repr {
|
||||
pub int_repr: Option<&'static str>,
|
||||
pub c_repr: bool,
|
||||
pub other_repr: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Style {
|
||||
/// Named fields.
|
||||
@ -69,7 +75,8 @@ impl<'a> Container<'a> {
|
||||
|
||||
let mut data = match item.data {
|
||||
syn::Data::Enum(ref data) => {
|
||||
Data::Enum(enum_from_ast(cx, &data.variants, attrs.default()))
|
||||
let (repr, variants) = enum_from_ast(cx, item, &data.variants, attrs.default());
|
||||
Data::Enum(repr, variants)
|
||||
}
|
||||
syn::Data::Struct(ref data) => {
|
||||
let (style, fields) = struct_from_ast(cx, &data.fields, None, attrs.default());
|
||||
@ -83,7 +90,7 @@ impl<'a> Container<'a> {
|
||||
|
||||
let mut has_flatten = false;
|
||||
match data {
|
||||
Data::Enum(ref mut variants) => {
|
||||
Data::Enum(_, ref mut variants) => {
|
||||
for variant in variants {
|
||||
variant.attrs.rename_by_rules(attrs.rename_all_rules());
|
||||
for field in &mut variant.fields {
|
||||
@ -125,7 +132,7 @@ impl<'a> Container<'a> {
|
||||
impl<'a> Data<'a> {
|
||||
pub fn all_fields(&'a self) -> Box<Iterator<Item = &'a Field<'a>> + 'a> {
|
||||
match *self {
|
||||
Data::Enum(ref variants) => {
|
||||
Data::Enum(_, ref variants) => {
|
||||
Box::new(variants.iter().flat_map(|variant| variant.fields.iter()))
|
||||
}
|
||||
Data::Struct(_, ref fields) => Box::new(fields.iter()),
|
||||
@ -137,16 +144,37 @@ impl<'a> Data<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Repr {
|
||||
/// Gives the int type to use for the `repr(int)` enum layout
|
||||
pub fn get_stable_rust_enum_layout(&self) -> Option<&'static str> {
|
||||
if self.c_repr || self.other_repr {
|
||||
None
|
||||
} else {
|
||||
self.int_repr
|
||||
}
|
||||
}
|
||||
|
||||
/// Gives the int type to use for the `repr(C, int)` enum layout
|
||||
pub fn get_stable_c_enum_layout(&self) -> Option<&'static str> {
|
||||
if !self.c_repr && self.other_repr {
|
||||
None
|
||||
} else {
|
||||
self.int_repr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn enum_from_ast<'a>(
|
||||
cx: &Ctxt,
|
||||
item: &'a syn::DeriveInput,
|
||||
variants: &'a Punctuated<syn::Variant, Token![,]>,
|
||||
container_default: &attr::Default,
|
||||
) -> Vec<Variant<'a>> {
|
||||
variants
|
||||
container_default: &attr::Default
|
||||
) -> (Repr, Vec<Variant<'a>>) {
|
||||
let variants = variants
|
||||
.iter()
|
||||
.map(|variant| {
|
||||
let attrs = attr::Variant::from_ast(cx, variant);
|
||||
let (style, fields) =
|
||||
let (style, fields) =
|
||||
struct_from_ast(cx, &variant.fields, Some(&attrs), container_default);
|
||||
Variant {
|
||||
ident: variant.ident.clone(),
|
||||
@ -156,7 +184,48 @@ fn enum_from_ast<'a>(
|
||||
original: variant,
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
.collect();
|
||||
|
||||
// Compute repr info for enum optimizations
|
||||
static INT_TYPES: [&'static str; 12] = [
|
||||
"u8", "u16", "u32", "u64", "u128", "usize",
|
||||
"i8", "i16", "i32", "i64", "i128", "isize",
|
||||
];
|
||||
|
||||
let mut int_repr = None;
|
||||
let mut c_repr = false;
|
||||
let mut other_repr = false;
|
||||
|
||||
for attr in &item.attrs {
|
||||
if let Some(syn::Meta::List(ref list)) = attr.interpret_meta() {
|
||||
if list.ident == "repr" {
|
||||
// has_repr = true;
|
||||
for repr in &list.nested {
|
||||
if let syn::NestedMeta::Meta(syn::Meta::Word(ref repr)) = *repr {
|
||||
if repr == "C" {
|
||||
c_repr = true;
|
||||
} else if let Some(int_type) = INT_TYPES.iter().cloned().find(|int_type| repr == int_type) {
|
||||
if int_repr.is_some() {
|
||||
// This shouldn't happen, but we shouldn't crash if we see it.
|
||||
// So just treat the enum as having a mysterious other repr,
|
||||
// which makes us discard any attempt to optimize based on layout.
|
||||
other_repr = true;
|
||||
}
|
||||
int_repr = Some(int_type);
|
||||
} else {
|
||||
other_repr = true;
|
||||
}
|
||||
} else {
|
||||
panic!("impossible repr? {:?}", repr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let repr = Repr { int_repr, c_repr, other_repr };
|
||||
|
||||
(repr, variants)
|
||||
}
|
||||
|
||||
fn struct_from_ast<'a>(
|
||||
|
@ -19,7 +19,7 @@ pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) {
|
||||
/// attribute.
|
||||
fn check_getter(cx: &Ctxt, cont: &Container) {
|
||||
match cont.data {
|
||||
Data::Enum(_) => {
|
||||
Data::Enum(_, _) => {
|
||||
if cont.data.has_getter() {
|
||||
cx.error_spanned_by(
|
||||
cont.original,
|
||||
@ -42,7 +42,7 @@ fn check_getter(cx: &Ctxt, cont: &Container) {
|
||||
/// Flattening has some restrictions we can test.
|
||||
fn check_flatten(cx: &Ctxt, cont: &Container) {
|
||||
match cont.data {
|
||||
Data::Enum(ref variants) => {
|
||||
Data::Enum(_, ref variants) => {
|
||||
for variant in variants {
|
||||
for field in &variant.fields {
|
||||
check_flatten_field(cx, variant.style, field);
|
||||
@ -86,7 +86,7 @@ fn check_flatten_field(cx: &Ctxt, style: Style, field: &Field) {
|
||||
/// last variant may be a newtype variant which is an implicit "other" case.
|
||||
fn check_identifier(cx: &Ctxt, cont: &Container) {
|
||||
let variants = match cont.data {
|
||||
Data::Enum(ref variants) => variants,
|
||||
Data::Enum(_, ref variants) => variants,
|
||||
Data::Struct(_, _) => {
|
||||
return;
|
||||
}
|
||||
@ -170,7 +170,7 @@ fn check_identifier(cx: &Ctxt, cont: &Container) {
|
||||
/// (de)serialize_with.
|
||||
fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
|
||||
let variants = match cont.data {
|
||||
Data::Enum(ref variants) => variants,
|
||||
Data::Enum(_, ref variants) => variants,
|
||||
Data::Struct(_, _) => {
|
||||
return;
|
||||
}
|
||||
@ -252,7 +252,7 @@ fn check_variant_skip_attrs(cx: &Ctxt, cont: &Container) {
|
||||
/// the to-be-deserialized input.
|
||||
fn check_internal_tag_field_name_conflict(cx: &Ctxt, cont: &Container) {
|
||||
let variants = match cont.data {
|
||||
Data::Enum(ref variants) => variants,
|
||||
Data::Enum(_, ref variants) => variants,
|
||||
Data::Struct(_, _) => return,
|
||||
};
|
||||
|
||||
@ -338,7 +338,7 @@ fn check_transparent(cx: &Ctxt, cont: &mut Container, derive: Derive) {
|
||||
}
|
||||
|
||||
let fields = match cont.data {
|
||||
Data::Enum(_) => {
|
||||
Data::Enum(_, _) => {
|
||||
cx.error_spanned_by(
|
||||
cont.original,
|
||||
"#[serde(transparent)] is not allowed on an enum",
|
||||
|
4
third_party/rust/serde_derive/src/pretend.rs
vendored
4
third_party/rust/serde_derive/src/pretend.rs
vendored
@ -53,7 +53,7 @@ fn pretend_fields_used(cont: &Container) -> TokenStream {
|
||||
let (_, ty_generics, _) = cont.generics.split_for_impl();
|
||||
|
||||
let patterns = match cont.data {
|
||||
Data::Enum(ref variants) => variants
|
||||
Data::Enum(_, ref variants) => variants
|
||||
.iter()
|
||||
.filter_map(|variant| match variant.style {
|
||||
Style::Struct => {
|
||||
@ -94,7 +94,7 @@ fn pretend_fields_used(cont: &Container) -> TokenStream {
|
||||
//
|
||||
fn pretend_variants_used(cont: &Container) -> TokenStream {
|
||||
let variants = match cont.data {
|
||||
Data::Enum(ref variants) => variants,
|
||||
Data::Enum(_, ref variants) => variants,
|
||||
Data::Struct(_, _) => {
|
||||
return quote!();
|
||||
}
|
||||
|
4
third_party/rust/serde_derive/src/ser.rs
vendored
4
third_party/rust/serde_derive/src/ser.rs
vendored
@ -159,7 +159,7 @@ fn serialize_body(cont: &Container, params: &Parameters) -> Fragment {
|
||||
serialize_into(params, type_into)
|
||||
} else {
|
||||
match cont.data {
|
||||
Data::Enum(ref variants) => serialize_enum(params, variants, &cont.attrs),
|
||||
Data::Enum(_, ref variants) => serialize_enum(params, variants, &cont.attrs),
|
||||
Data::Struct(Style::Struct, ref fields) => {
|
||||
serialize_struct(params, fields, &cont.attrs)
|
||||
}
|
||||
@ -177,7 +177,7 @@ fn serialize_body(cont: &Container, params: &Parameters) -> Fragment {
|
||||
fn serialize_transparent(cont: &Container, params: &Parameters) -> Fragment {
|
||||
let fields = match cont.data {
|
||||
Data::Struct(_, ref fields) => fields,
|
||||
Data::Enum(_) => unreachable!(),
|
||||
Data::Enum(_, _) => unreachable!(),
|
||||
};
|
||||
|
||||
let self_var = ¶ms.self_var;
|
||||
|
Loading…
Reference in New Issue
Block a user