summaryrefslogtreecommitdiffstats
path: root/gfx/wr/peek-poke
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /gfx/wr/peek-poke
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'gfx/wr/peek-poke')
-rw-r--r--gfx/wr/peek-poke/Cargo.toml17
-rw-r--r--gfx/wr/peek-poke/LICENSE-APACHE201
-rw-r--r--gfx/wr/peek-poke/LICENSE-MIT44
-rw-r--r--gfx/wr/peek-poke/README.md54
-rw-r--r--gfx/wr/peek-poke/peek-poke-derive/Cargo.toml19
-rw-r--r--gfx/wr/peek-poke/peek-poke-derive/LICENSE-APACHE201
-rw-r--r--gfx/wr/peek-poke/peek-poke-derive/LICENSE-MIT44
-rw-r--r--gfx/wr/peek-poke/peek-poke-derive/README.md54
-rw-r--r--gfx/wr/peek-poke/peek-poke-derive/src/lib.rs263
-rw-r--r--gfx/wr/peek-poke/src/euclid.rs191
-rw-r--r--gfx/wr/peek-poke/src/lib.rs440
-rw-r--r--gfx/wr/peek-poke/src/slice_ext.rs19
-rw-r--r--gfx/wr/peek-poke/src/vec_ext.rs26
-rw-r--r--gfx/wr/peek-poke/tests/max_size.rs117
-rw-r--r--gfx/wr/peek-poke/tests/round_trip.rs275
15 files changed, 1965 insertions, 0 deletions
diff --git a/gfx/wr/peek-poke/Cargo.toml b/gfx/wr/peek-poke/Cargo.toml
new file mode 100644
index 0000000000..a2dc99065b
--- /dev/null
+++ b/gfx/wr/peek-poke/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+name = "peek-poke"
+version = "0.3.0"
+authors = ["Dan Glastonbury <dan.glastonbury@gmail.com>"]
+repository = "https://github.com/servo/webrender"
+description = "A mechanism for serializing and deserializing data into/from byte buffers, for use in WebRender."
+license = "MIT/Apache-2.0"
+edition = "2018"
+
+[dependencies]
+euclid = { version = "0.22.0", optional = true }
+peek-poke-derive = { version = "0.3", path = "./peek-poke-derive", optional = true }
+
+[features]
+default = ["derive"]
+derive = ["peek-poke-derive"]
+extras = ["derive", "euclid"]
diff --git a/gfx/wr/peek-poke/LICENSE-APACHE b/gfx/wr/peek-poke/LICENSE-APACHE
new file mode 100644
index 0000000000..16fe87b06e
--- /dev/null
+++ b/gfx/wr/peek-poke/LICENSE-APACHE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/gfx/wr/peek-poke/LICENSE-MIT b/gfx/wr/peek-poke/LICENSE-MIT
new file mode 100644
index 0000000000..110bb34712
--- /dev/null
+++ b/gfx/wr/peek-poke/LICENSE-MIT
@@ -0,0 +1,44 @@
+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.
diff --git a/gfx/wr/peek-poke/README.md b/gfx/wr/peek-poke/README.md
new file mode 100644
index 0000000000..1c379aa121
--- /dev/null
+++ b/gfx/wr/peek-poke/README.md
@@ -0,0 +1,54 @@
+# 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.
diff --git a/gfx/wr/peek-poke/peek-poke-derive/Cargo.toml b/gfx/wr/peek-poke/peek-poke-derive/Cargo.toml
new file mode 100644
index 0000000000..491e0d95ae
--- /dev/null
+++ b/gfx/wr/peek-poke/peek-poke-derive/Cargo.toml
@@ -0,0 +1,19 @@
+[package]
+name = "peek-poke-derive"
+version = "0.3.0"
+authors = ["Dan Glastonbury <dan.glastonbury@gmail.com>"]
+repository = "https://github.com/servo/webrender"
+description = "Derive macro for peek-poke."
+license = "MIT/Apache-2.0"
+edition = "2018"
+
+[lib]
+doctest = false
+proc-macro = true
+
+[dependencies]
+proc-macro2 = "1"
+quote = "1"
+syn = "1"
+synstructure = "0.12"
+unicode-xid = "0.2"
diff --git a/gfx/wr/peek-poke/peek-poke-derive/LICENSE-APACHE b/gfx/wr/peek-poke/peek-poke-derive/LICENSE-APACHE
new file mode 100644
index 0000000000..16fe87b06e
--- /dev/null
+++ b/gfx/wr/peek-poke/peek-poke-derive/LICENSE-APACHE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/gfx/wr/peek-poke/peek-poke-derive/LICENSE-MIT b/gfx/wr/peek-poke/peek-poke-derive/LICENSE-MIT
new file mode 100644
index 0000000000..110bb34712
--- /dev/null
+++ b/gfx/wr/peek-poke/peek-poke-derive/LICENSE-MIT
@@ -0,0 +1,44 @@
+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.
diff --git a/gfx/wr/peek-poke/peek-poke-derive/README.md b/gfx/wr/peek-poke/peek-poke-derive/README.md
new file mode 100644
index 0000000000..1c379aa121
--- /dev/null
+++ b/gfx/wr/peek-poke/peek-poke-derive/README.md
@@ -0,0 +1,54 @@
+# 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.
diff --git a/gfx/wr/peek-poke/peek-poke-derive/src/lib.rs b/gfx/wr/peek-poke/peek-poke-derive/src/lib.rs
new file mode 100644
index 0000000000..ac20b2b922
--- /dev/null
+++ b/gfx/wr/peek-poke/peek-poke-derive/src/lib.rs
@@ -0,0 +1,263 @@
+// 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'
+ matches!(&s.variants()[..], [v] if v.prefix.is_none())
+}
+
+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 num_variants = s.variants().len();
+ let discriminant_size_type = get_discriminant_size_type(num_variants);
+ 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
+ }
+ }
+ });
+
+ let type_name = s.ast().ident.to_string();
+ let max_tag_value = num_variants - 1;
+
+ 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
+ out_of_range_tag => {
+ panic!("WRDL: memory corruption detected while parsing {} - enum tag should be <= {}, but was {}",
+ #type_name, #max_tag_value, out_of_range_tag);
+ }
+ }
+ }
+ }
+}
+
+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);
diff --git a/gfx/wr/peek-poke/src/euclid.rs b/gfx/wr/peek-poke/src/euclid.rs
new file mode 100644
index 0000000000..dc4dd7774b
--- /dev/null
+++ b/gfx/wr/peek-poke/src/euclid.rs
@@ -0,0 +1,191 @@
+// 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::{Point2D, Rect, Box2D, SideOffsets2D, Size2D, Transform3D, Vector2D};
+
+unsafe impl<T: Poke, U> Poke for Point2D<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 Point2D<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 Rect<T, U> {
+ #[inline(always)]
+ fn max_size() -> usize {
+ Point2D::<T, U>::max_size() + Size2D::<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 Rect<T, U> {
+ #[inline(always)]
+ unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
+ let bytes = Point2D::<T, U>::peek_from(bytes, &mut (*output).origin);
+ let bytes = Size2D::<T, U>::peek_from(bytes, &mut (*output).size);
+ bytes
+ }
+}
+
+unsafe impl<T: Poke, U> Poke for Box2D<T, U> {
+ #[inline(always)]
+ fn max_size() -> usize {
+ Point2D::<T, U>::max_size() * 2
+ }
+ #[inline(always)]
+ unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
+ let bytes = self.min.poke_into(bytes);
+ let bytes = self.max.poke_into(bytes);
+ bytes
+ }
+}
+impl<T: Peek, U> Peek for Box2D<T, U> {
+ #[inline(always)]
+ unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
+ let bytes = Point2D::<T, U>::peek_from(bytes, &mut (*output).min);
+ let bytes = Point2D::<T, U>::peek_from(bytes, &mut (*output).max);
+ bytes
+ }
+}
+
+unsafe impl<T: Poke, U> Poke for SideOffsets2D<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 SideOffsets2D<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 Size2D<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 Size2D<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 Transform3D<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 Transform3D<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 Vector2D<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 Vector2D<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
+ }
+}
diff --git a/gfx/wr/peek-poke/src/lib.rs b/gfx/wr/peek-poke/src/lib.rs
new file mode 100644
index 0000000000..18f6a9acd8
--- /dev/null
+++ b/gfx/wr/peek-poke/src/lib.rs
@@ -0,0 +1,440 @@
+// 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(), "WRDL: unexpected end of display list");
+ 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(), "WRDL: Peek::max_size was wrong");
+ 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(), "WRDL: buffer too small to write into");
+ 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()));
+ }
+}
+
+/// Remove the "red zone" (padding of zeroes) from the end of the vec of `bytes`.
+/// This is effectively the inverse of `ensure_red_zone`, with the caveat that
+/// space reserved for the red zone is not un-reserved. Callers are repsonsible
+/// for making sure the vec actually has a red zone, otherwise data bytes can
+/// get stripped instead.
+pub fn strip_red_zone<T: Poke>(bytes: &mut Vec<u8>) {
+ assert!(bytes.len() >= T::max_size());
+ unsafe {
+ let end_ptr = bytes.as_end_mut_ptr();
+ bytes.set_end_ptr(end_ptr.sub(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);
diff --git a/gfx/wr/peek-poke/src/slice_ext.rs b/gfx/wr/peek-poke/src/slice_ext.rs
new file mode 100644
index 0000000000..f309d2f741
--- /dev/null
+++ b/gfx/wr/peek-poke/src/slice_ext.rs
@@ -0,0 +1,19 @@
+// 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()) }
+ }
+}
diff --git a/gfx/wr/peek-poke/src/vec_ext.rs b/gfx/wr/peek-poke/src/vec_ext.rs
new file mode 100644
index 0000000000..42e26032e5
--- /dev/null
+++ b/gfx/wr/peek-poke/src/vec_ext.rs
@@ -0,0 +1,26 @@
+// 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);
+ }
+}
diff --git a/gfx/wr/peek-poke/tests/max_size.rs b/gfx/wr/peek-poke/tests/max_size.rs
new file mode 100644
index 0000000000..67cd1ca4a6
--- /dev/null
+++ b/gfx/wr/peek-poke/tests/max_size.rs
@@ -0,0 +1,117 @@
+// 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>())
+}
diff --git a/gfx/wr/peek-poke/tests/round_trip.rs b/gfx/wr/peek-poke/tests/round_trip.rs
new file mode 100644
index 0000000000..3134c207ec
--- /dev/null
+++ b/gfx/wr/peek-poke/tests/round_trip.rs
@@ -0,0 +1,275 @@
+// 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, Default, 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)));
+ }
+}