summaryrefslogtreecommitdiffstats
path: root/third_party/rust/plain
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /third_party/rust/plain
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/plain')
-rw-r--r--third_party/rust/plain/.cargo-checksum.json1
-rw-r--r--third_party/rust/plain/Cargo.toml24
-rw-r--r--third_party/rust/plain/LICENSE-APACHE201
-rw-r--r--third_party/rust/plain/LICENSE-MIT25
-rw-r--r--third_party/rust/plain/README.md146
-rw-r--r--third_party/rust/plain/src/error.rs6
-rw-r--r--third_party/rust/plain/src/lib.rs158
-rw-r--r--third_party/rust/plain/src/methods.rs198
-rw-r--r--third_party/rust/plain/src/plain.rs96
-rw-r--r--third_party/rust/plain/src/tests.rs123
10 files changed, 978 insertions, 0 deletions
diff --git a/third_party/rust/plain/.cargo-checksum.json b/third_party/rust/plain/.cargo-checksum.json
new file mode 100644
index 0000000000..154d244037
--- /dev/null
+++ b/third_party/rust/plain/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"7ca9f28917559a3066a55570c2af18d3d76656537d6826aeaea03b9b53703f03","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"bc12b75fd81829814d843a03fa52aad0e53355b1f13665e309ff7fa33c66e5b5","README.md":"016afabc736fc574d980b31ef5fec1b695c458b5ee5b53be7e6490772cdbf59d","src/error.rs":"febf6f4536848406692a7e81769934c629ce66d147b119bb33cba214598cf314","src/lib.rs":"2e66f345463c909a04cdc438b02a0bded92891eda64e4796ab02ec8bd66220ea","src/methods.rs":"cd78e4505a1e3aeb8ed08abcc2000d0b46b9c572becbc6fc90358332377a8081","src/plain.rs":"15d2f5ce4c1239b36871e1f5e1da0fc0fb8e3d73b52185cb77d3139f6c3be223","src/tests.rs":"cef8f21e98efd7dab3508843a375fb6dbb2b04e879779336ca70ac9f5eeb2c89"},"package":"b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"} \ No newline at end of file
diff --git a/third_party/rust/plain/Cargo.toml b/third_party/rust/plain/Cargo.toml
new file mode 100644
index 0000000000..e08b586a6c
--- /dev/null
+++ b/third_party/rust/plain/Cargo.toml
@@ -0,0 +1,24 @@
+# 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 = "plain"
+version = "0.2.3"
+authors = ["jzr"]
+description = "A small Rust library that allows users to reinterpret data of certain types safely."
+homepage = "https://github.com/randomites/plain"
+documentation = "https://docs.rs/plain"
+readme = "README.md"
+keywords = ["plain", "pod", "ffi", "memory"]
+categories = ["no-std", "data-structures", "parsing"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/randomites/plain"
diff --git a/third_party/rust/plain/LICENSE-APACHE b/third_party/rust/plain/LICENSE-APACHE
new file mode 100644
index 0000000000..16fe87b06e
--- /dev/null
+++ b/third_party/rust/plain/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/third_party/rust/plain/LICENSE-MIT b/third_party/rust/plain/LICENSE-MIT
new file mode 100644
index 0000000000..fcb6e2f85a
--- /dev/null
+++ b/third_party/rust/plain/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) 2017 Plain contributors
+
+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/third_party/rust/plain/README.md b/third_party/rust/plain/README.md
new file mode 100644
index 0000000000..fec0ccd062
--- /dev/null
+++ b/third_party/rust/plain/README.md
@@ -0,0 +1,146 @@
+# libplain
+
+[![Build Status](https://travis-ci.org/randomites/plain.svg?branch=master)](https://travis-ci.org/randomites/plain)
+[![Current Crates.io Version](https://img.shields.io/crates/v/plain.svg)](https://crates.io/crates/plain)
+[![Current Documentation](https://docs.rs/plain/badge.svg)](https://docs.rs/plain)
+
+A small Rust library that allows users to interpret arrays of bytes
+as certain kinds of structures safely.
+
+This crate provides an unsafe trait [`Plain`](https://docs.rs/plain/0.2.0/plain/trait.Plain.html), which the user
+of the crate uses to mark types for which operations of this library are safe.
+See [`Plain`](https://docs.rs/plain/0.2.0/plain/trait.Plain.html) for the contractual obligation.
+
+Other than that, everything else in this crate is perfectly safe to use as long
+as the `Plain` trait is not implemented on inadmissible types (similar to how
+`Send` and `Sync` in the standard library work).
+
+# Purpose
+
+In low level systems development, it is sometimes necessary to
+interpret locations in memory as data structures. Functions of
+this crate serve to avoid pitfalls associated with that, without
+having to resort to big, full-featured (de)serialization libraries.
+
+On the other hand, this crate contains no provisions when it comes
+to handling differences in encoding and byte ordering between
+platforms. As such, it is entirely unsuitable for processing
+external data such as file contents or network packets.
+
+# Examples
+
+To start using the crate, simply do `extern crate plain;`.
+
+If you want your plain types to have methods from this crate, also include `use plain.Plain;`.
+
+Then it's just a matter of marking the right types and using them.
+
+```
+
+extern crate plain;
+use plain::Plain;
+use std::mem;
+
+
+#[repr(C)]
+#[derive(Default)]
+struct ELF64Header {
+ pub e_ident: [u8; 16],
+ pub e_type: u16,
+ pub e_machine: u16,
+ pub e_version: u32,
+ pub e_entry: u64,
+ pub e_phoff: u64,
+ pub e_shoff: u64,
+ pub e_flags: u32,
+ pub e_ehsize: u16,
+ pub e_phentsize: u16,
+ pub e_phnum: u16,
+ pub e_shentsize: u16,
+ pub e_shnum: u16,
+ pub e_shstrndx: u16,
+}
+
+// SAFE: ELF64Header satisfies all the requirements of `Plain`.
+unsafe impl Plain for ELF64Header {}
+
+impl ELF64Header {
+ fn from_bytes(buf: &[u8]) -> &ELF64Header {
+ plain::from_bytes(buf).expect("The buffer is either too short or not aligned!")
+ }
+
+ fn from_mut_bytes(buf: &mut [u8]) -> &mut ELF64Header {
+ plain::from_mut_bytes(buf).expect("The buffer is either too short or not aligned!")
+ }
+
+ fn copy_from_bytes(buf: &[u8]) -> ELF64Header {
+ let mut h = ELF64Header::default();
+ h.copy_from_bytes(buf).expect("The buffer is too short!");
+ h
+ }
+}
+
+# fn process_elf(elf: &ELF64Header) {}
+
+// Conditional copying for ultimate hackery.
+fn opportunistic_elf_processing(buf: &[u8]) {
+ if plain::is_aligned::<ELF64Header>(buf) {
+ // No copy necessary.
+ let elf_ref = ELF64Header::from_bytes(buf);
+ process_elf(elf_ref);
+ } else {
+ // Not aligned properly, copy to stack first.
+ let elf = ELF64Header::copy_from_bytes(buf);
+ process_elf(&elf);
+ }
+}
+
+#[repr(C)]
+#[derive(Default, Copy, Clone)]
+struct ArrayEntry {
+ pub name: [u8; 32],
+ pub tag: u32,
+ pub score: u32,
+}
+
+// SAFE: ArrayEntry satisfies all the requirements of `Plain`.
+unsafe impl Plain for ArrayEntry {}
+
+fn array_from_bytes(buf: &[u8]) -> &[ArrayEntry] {
+ // NOTE: length is not a concern here,
+ // since slice_from_bytes() can return empty slice.
+
+ match plain::slice_from_bytes(buf) {
+ Err(_) => panic!("The buffer is not aligned!"),
+ Ok(arr) => arr,
+ }
+}
+
+fn array_from_unaligned_bytes(buf: &[u8]) -> Vec<ArrayEntry> {
+ let length = buf.len() / mem::size_of::<ArrayEntry>();
+ let mut result = vec![ArrayEntry::default(); length];
+ (&mut result).copy_from_bytes(buf).expect("Cannot fail here.");
+ result
+}
+
+# fn main() {}
+
+```
+
+# Comparison to [`pod`](https://crates.io/crates/pod)
+
+[`pod`](https://crates.io/crates/pod) is another crate created to help working with plain data.
+The major difference between `pod` and `plain` is scope.
+
+`plain` currently provides only a few functions (+method wrappers) and its implementation
+involves very few lines of unsafe code. It can be used in `no_std` code. Also, it doesn't
+deal with [endianness](https://en.wikipedia.org/wiki/Endianness) in any way,
+so it is only suitable for certain kinds of low-level work.
+
+`pod`, on the other hand, provides a wide arsenal
+of various methods, most of which may be unnecessary for a given use case.
+It has dependencies on `std` as well as other crates, but among other things
+it provides tools to handle endianness properly.
+
+In short, `plain` is much, much _plainer_...
+
diff --git a/third_party/rust/plain/src/error.rs b/third_party/rust/plain/src/error.rs
new file mode 100644
index 0000000000..0012eba9bc
--- /dev/null
+++ b/third_party/rust/plain/src/error.rs
@@ -0,0 +1,6 @@
+
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub enum Error {
+ TooShort,
+ BadAlignment,
+}
diff --git a/third_party/rust/plain/src/lib.rs b/third_party/rust/plain/src/lib.rs
new file mode 100644
index 0000000000..f4eb4badf1
--- /dev/null
+++ b/third_party/rust/plain/src/lib.rs
@@ -0,0 +1,158 @@
+//! A small Rust library that allows users to interpret arrays of bytes
+//! as certain kinds of structures safely.
+//!
+//! This crate provides an unsafe trait [`Plain`](trait.Plain.html), which the user
+//! of the crate uses to mark types for which operations of this library are safe.
+//! See [`Plain`](trait.Plain.html) for the contractual obligation.
+//!
+//! Other than that, everything else in this crate is perfectly safe to use as long
+//! as the `Plain` trait is not implemented on inadmissible types (similar to how
+//! `Send` and `Sync` in the standard library work).
+//!
+//! # Purpose
+//!
+//! In low level systems development, it is sometimes necessary to
+//! interpret locations in memory as data structures. Functions of
+//! this crate serve to avoid pitfalls associated with that, without
+//! having to resort to big, full-featured (de)serialization libraries.
+//!
+//! On the other hand, this crate contains no provisions when it comes
+//! to handling differences in encoding and byte ordering between
+//! platforms. As such, it is entirely unsuitable for processing
+//! external data such as file contents or network packets.
+//!
+//! # Examples
+//!
+//! To start using the crate, simply do `extern crate plain;`.
+//!
+//! If you want your plain types to have methods from this crate, also include `use plain.Plain;`.
+//!
+//! Then it's just a matter of marking the right types and using them.
+//!
+//! ```
+//!
+//! extern crate plain;
+//! use plain::Plain;
+//! use std::mem;
+//!
+//!
+//! #[repr(C)]
+//! #[derive(Default)]
+//! struct ELF64Header {
+//! pub e_ident: [u8; 16],
+//! pub e_type: u16,
+//! pub e_machine: u16,
+//! pub e_version: u32,
+//! pub e_entry: u64,
+//! pub e_phoff: u64,
+//! pub e_shoff: u64,
+//! pub e_flags: u32,
+//! pub e_ehsize: u16,
+//! pub e_phentsize: u16,
+//! pub e_phnum: u16,
+//! pub e_shentsize: u16,
+//! pub e_shnum: u16,
+//! pub e_shstrndx: u16,
+//! }
+//!
+//! // SAFE: ELF64Header satisfies all the requirements of `Plain`.
+//! unsafe impl Plain for ELF64Header {}
+//!
+//! impl ELF64Header {
+//! fn from_bytes(buf: &[u8]) -> &ELF64Header {
+//! plain::from_bytes(buf).expect("The buffer is either too short or not aligned!")
+//! }
+//!
+//! fn from_mut_bytes(buf: &mut [u8]) -> &mut ELF64Header {
+//! plain::from_mut_bytes(buf).expect("The buffer is either too short or not aligned!")
+//! }
+//!
+//! fn copy_from_bytes(buf: &[u8]) -> ELF64Header {
+//! let mut h = ELF64Header::default();
+//! h.copy_from_bytes(buf).expect("The buffer is too short!");
+//! h
+//! }
+//! }
+//!
+//! # fn process_elf(elf: &ELF64Header) {}
+//!
+//! // Conditional copying for ultimate hackery.
+//! fn opportunistic_elf_processing(buf: &[u8]) {
+//! if plain::is_aligned::<ELF64Header>(buf) {
+//! // No copy necessary.
+//! let elf_ref = ELF64Header::from_bytes(buf);
+//! process_elf(elf_ref);
+//! } else {
+//! // Not aligned properly, copy to stack first.
+//! let elf = ELF64Header::copy_from_bytes(buf);
+//! process_elf(&elf);
+//! }
+//! }
+//!
+//! #[repr(C)]
+//! #[derive(Default, Copy, Clone)]
+//! struct ArrayEntry {
+//! pub name: [u8; 32],
+//! pub tag: u32,
+//! pub score: u32,
+//! }
+//!
+//! // SAFE: ArrayEntry satisfies all the requirements of `Plain`.
+//! unsafe impl Plain for ArrayEntry {}
+//!
+//! fn array_from_bytes(buf: &[u8]) -> &[ArrayEntry] {
+//! // NOTE: length is not a concern here,
+//! // since slice_from_bytes() can return empty slice.
+//!
+//! match plain::slice_from_bytes(buf) {
+//! Err(_) => panic!("The buffer is not aligned!"),
+//! Ok(arr) => arr,
+//! }
+//! }
+//!
+//! fn array_from_unaligned_bytes(buf: &[u8]) -> Vec<ArrayEntry> {
+//! let length = buf.len() / mem::size_of::<ArrayEntry>();
+//! let mut result = vec![ArrayEntry::default(); length];
+//! (&mut result).copy_from_bytes(buf).expect("Cannot fail here.");
+//! result
+//! }
+//!
+//! # fn main() {}
+//!
+//! ```
+//!
+//! # Comparison to [`pod`](https://crates.io/crates/pod)
+//!
+//! [`pod`](https://crates.io/crates/pod) is another crate created to help working with plain data.
+//! The major difference between `pod` and `plain` is scope.
+//!
+//! `plain` currently provides only a few functions (+method wrappers) and its implementation
+//! involves very few lines of unsafe code. It can be used in `no_std` code. Also, it doesn't
+//! deal with [endianness](https://en.wikipedia.org/wiki/Endianness) in any way,
+//! so it is only suitable for certain kinds of low-level work.
+//!
+//! `pod`, on the other hand, provides a wide arsenal
+//! of various methods, most of which may be unnecessary for a given use case.
+//! It has dependencies on `std` as well as other crates, but among other things
+//! it provides tools to handle endianness properly.
+//!
+//! In short, `plain` is much, much _plainer_...
+#![no_std]
+
+mod error;
+pub use error::Error;
+
+mod plain;
+pub use plain::Plain;
+
+mod methods;
+pub use methods::{as_bytes, as_mut_bytes, copy_from_bytes, from_bytes, from_mut_bytes, is_aligned,
+ slice_from_bytes, slice_from_bytes_len, slice_from_mut_bytes,
+ slice_from_mut_bytes_len};
+
+#[cfg(test)]
+#[macro_use]
+extern crate std;
+
+#[cfg(test)]
+mod tests;
diff --git a/third_party/rust/plain/src/methods.rs b/third_party/rust/plain/src/methods.rs
new file mode 100644
index 0000000000..58be4a2500
--- /dev/null
+++ b/third_party/rust/plain/src/methods.rs
@@ -0,0 +1,198 @@
+
+use core::{mem, slice};
+
+use {Error, Plain};
+
+/// Check if a byte slice is aligned suitably for type T.
+#[inline]
+pub fn is_aligned<T>(bytes: &[u8]) -> bool {
+ ((bytes.as_ptr() as usize) % mem::align_of::<T>()) == 0
+}
+
+#[inline(always)]
+fn check_alignment<T>(bytes: &[u8]) -> Result<(), Error> {
+ if is_aligned::<T>(bytes) {
+ Ok(())
+ } else {
+ Err(Error::BadAlignment)
+ }
+}
+
+#[inline(always)]
+fn check_length<T>(bytes: &[u8], len: usize) -> Result<(), Error> {
+ if mem::size_of::<T>() > 0 && (bytes.len() / mem::size_of::<T>()) < len {
+ Err(Error::TooShort)
+ } else {
+ Ok(())
+ }
+}
+
+/// Interpret data as bytes. Not safe for data with padding.
+#[inline(always)]
+pub unsafe fn as_bytes<S>(s: &S) -> &[u8]
+where
+ S: ?Sized,
+{
+ let bptr = s as *const S as *const u8;
+ let bsize = mem::size_of_val(s);
+ slice::from_raw_parts(bptr, bsize)
+}
+
+/// Interpret data as mutable bytes.
+/// Reading is not safe for data with padding. Writing is ok.
+#[inline(always)]
+pub unsafe fn as_mut_bytes<S>(s: &mut S) -> &mut [u8]
+where
+ S: Plain + ?Sized,
+{
+ let bptr = s as *mut S as *mut u8;
+ let bsize = mem::size_of_val(s);
+ slice::from_raw_parts_mut(bptr, bsize)
+}
+
+/// Safely converts a byte slice to a reference.
+///
+/// However, if the byte slice is not long enough
+/// to contain target type, or if it doesn't
+/// satisfy the type's alignment requirements,
+/// the function returns an error.
+///
+/// The function will not fail when the
+/// byte slice is longer than necessary, since it is
+/// a common practice to interpret the beginning of
+/// a slice as a fixed-size header.
+///
+/// In many cases it is preferrable to allocate
+/// a value/slice of the target type and use
+/// [`copy_from_bytes()`](fn.copy_from_bytes.html) to copy
+/// data instead. That way, any issues with alignment
+/// are implicitly avoided.
+///
+#[inline]
+pub fn from_bytes<T>(bytes: &[u8]) -> Result<&T, Error>
+where
+ T: Plain,
+{
+ try!(check_alignment::<T>(bytes));
+ try!(check_length::<T>(bytes, 1));
+ Ok(unsafe { &*(bytes.as_ptr() as *const T) })
+}
+
+/// Similar to [`from_bytes()`](fn.from_bytes.html),
+/// except that the output is a slice of T, instead
+/// of a reference to a single T. All concerns about
+/// alignment also apply here, but size is handled
+/// differently.
+///
+/// The result slice's length is set to be
+/// `bytes.len() / size_of::<T>()`, and there
+/// are no requirements for input size. I.e.
+/// the result may be empty slice, and the input
+/// slice doesn't necessarily have to end on `T`'s
+/// boundary. The latter has pragmatic reasons: If the
+/// length of the array is not known in advance,
+/// e.g. if it's terminated by a special element,
+/// it's perfectly legal to turn the whole rest
+/// of data into `&[T]` and set the proper length
+/// after inspecting the array.
+///
+/// In many cases it is preferrable to allocate
+/// a value/slice of the target type and use
+/// [`copy_from_bytes()`](fn.copy_from_bytes.html) to copy
+/// data instead. That way, any issues with alignment
+/// are implicitly avoided.
+///
+#[inline]
+pub fn slice_from_bytes<T>(bytes: &[u8]) -> Result<&[T], Error>
+where
+ T: Plain,
+{
+ let len = bytes.len() / mem::size_of::<T>();
+ slice_from_bytes_len(bytes, len)
+}
+
+
+/// Same as [`slice_from_bytes()`](fn.slice_from_bytes.html),
+/// except that it takes explicit length of the result slice.
+///
+/// If the input slice cannot satisfy the length, returns error.
+/// The input slice is allowed to be longer than necessary.
+///
+#[inline]
+pub fn slice_from_bytes_len<T>(bytes: &[u8], len: usize) -> Result<&[T], Error>
+where
+ T: Plain,
+{
+ try!(check_alignment::<T>(bytes));
+ try!(check_length::<T>(bytes, len));
+ Ok(unsafe {
+ slice::from_raw_parts(bytes.as_ptr() as *const T, len)
+ })
+}
+
+/// See [`from_bytes()`](fn.from_bytes.html).
+///
+/// Does the same, except with mutable references.
+///
+#[inline]
+pub fn from_mut_bytes<T>(bytes: &mut [u8]) -> Result<&mut T, Error>
+where
+ T: Plain,
+{
+ try!(check_alignment::<T>(bytes));
+ try!(check_length::<T>(bytes, 1));
+ Ok(unsafe { &mut *(bytes.as_mut_ptr() as *mut T) })
+}
+
+/// See [`slice_from_bytes()`](fn.slice_from_bytes.html).
+///
+/// Does the same, except with mutable references.
+///
+#[inline]
+pub fn slice_from_mut_bytes<T>(bytes: &mut [u8]) -> Result<&mut [T], Error>
+where
+ T: Plain,
+{
+ let len = bytes.len() / mem::size_of::<T>();
+ slice_from_mut_bytes_len(bytes, len)
+}
+
+/// See [`slice_from_bytes_len()`](fn.slice_from_bytes_len.html).
+///
+/// Does the same, except with mutable references.
+///
+#[inline]
+pub fn slice_from_mut_bytes_len<T>(bytes: &mut [u8], len: usize) -> Result<&mut [T], Error>
+where
+ T: Plain,
+{
+ try!(check_alignment::<T>(bytes));
+ try!(check_length::<T>(bytes, len));
+ Ok(unsafe {
+ slice::from_raw_parts_mut(bytes.as_ptr() as *mut T, len)
+ })
+}
+
+/// Copies data from a byte slice into existing memory.
+/// Suitable when [`from_bytes()`](fn.from_bytes.html) would normally
+/// be used, but the data is not aligned properly in memory.
+///
+/// For an example how to use it, see crate-level documentation.
+///
+#[inline]
+pub fn copy_from_bytes<T>(into: &mut T, bytes: &[u8]) -> Result<(), Error>
+where
+ T: Plain + ?Sized,
+{
+ let sz = mem::size_of_val(into);
+
+ if bytes.len() < sz {
+ return Err(Error::TooShort);
+ }
+
+ unsafe {
+ as_mut_bytes(into).copy_from_slice(&bytes[..sz]);
+ }
+
+ Ok(())
+}
diff --git a/third_party/rust/plain/src/plain.rs b/third_party/rust/plain/src/plain.rs
new file mode 100644
index 0000000000..35522006de
--- /dev/null
+++ b/third_party/rust/plain/src/plain.rs
@@ -0,0 +1,96 @@
+use Error;
+
+/// A trait for plain data types that can be safely read from a byte slice.
+///
+/// A type can be [`Plain`](trait.Plain.html) if it is `#repr(C)` and only contains
+/// data with no possible invalid values. Types that _can't_ be `Plain`
+/// include, but are not limited to, `bool`, `char`, `enum`s, tuples,
+/// pointers and references.
+///
+/// At this moment, `Drop` types are also not legal, because
+/// compiler adds a special "drop flag" into the type. This is slated
+/// to change in the future.
+///
+/// On the other hand, arrays of a `Plain` type, and
+/// structures where all members are plain (and not `Drop`), are okay.
+///
+/// Structures that are not `#repr(C)`, while not necessarily illegal
+/// in principle, are largely useless because they don't have a stable
+/// layout. For example, the compiler is allowed to reorder fields
+/// arbitrarily.
+///
+/// All methods of this trait are implemented automatically as wrappers
+/// for crate-level funtions.
+///
+pub unsafe trait Plain {
+ #[inline(always)]
+ fn from_bytes(bytes: &[u8]) -> Result<&Self, Error>
+ where
+ Self: Sized,
+ {
+ ::from_bytes(bytes)
+ }
+
+ #[inline(always)]
+ fn slice_from_bytes(bytes: &[u8]) -> Result<&[Self], Error>
+ where
+ Self: Sized,
+ {
+ ::slice_from_bytes(bytes)
+ }
+
+ #[inline(always)]
+ fn slice_from_bytes_len(bytes: &[u8], len: usize) -> Result<&[Self], Error>
+ where
+ Self: Sized,
+ {
+ ::slice_from_bytes_len(bytes, len)
+ }
+
+ #[inline(always)]
+ fn from_mut_bytes(bytes: &mut [u8]) -> Result<&mut Self, Error>
+ where
+ Self: Sized,
+ {
+ ::from_mut_bytes(bytes)
+ }
+
+ #[inline(always)]
+ fn slice_from_mut_bytes(bytes: &mut [u8]) -> Result<&mut [Self], Error>
+ where
+ Self: Sized,
+ {
+ ::slice_from_mut_bytes(bytes)
+ }
+
+ #[inline(always)]
+ fn slice_from_mut_bytes_len(bytes: &mut [u8], len: usize) -> Result<&mut [Self], Error>
+ where
+ Self: Sized,
+ {
+ ::slice_from_mut_bytes_len(bytes, len)
+ }
+
+ #[inline(always)]
+ fn copy_from_bytes(&mut self, bytes: &[u8]) -> Result<(), Error> {
+ ::copy_from_bytes(self, bytes)
+ }
+}
+
+unsafe impl Plain for u8 {}
+unsafe impl Plain for u16 {}
+unsafe impl Plain for u32 {}
+unsafe impl Plain for u64 {}
+unsafe impl Plain for usize {}
+
+unsafe impl Plain for i8 {}
+unsafe impl Plain for i16 {}
+unsafe impl Plain for i32 {}
+unsafe impl Plain for i64 {}
+unsafe impl Plain for isize {}
+
+unsafe impl<S> Plain for [S]
+where
+ S: Plain,
+{
+}
diff --git a/third_party/rust/plain/src/tests.rs b/third_party/rust/plain/src/tests.rs
new file mode 100644
index 0000000000..7ab1c3753e
--- /dev/null
+++ b/third_party/rust/plain/src/tests.rs
@@ -0,0 +1,123 @@
+
+
+#![allow(dead_code)]
+
+use ::*;
+use core::mem;
+
+#[repr(C)]
+#[derive(Debug, Default, Copy, Eq, Clone, PartialEq)]
+struct Dummy1 {
+ field1: u64,
+ field2: u32,
+ field3: u16,
+ field4: u8,
+ field5: u8,
+}
+
+unsafe impl Plain for Dummy1 {}
+
+#[repr(C)]
+#[derive(Debug, Default, Copy, Eq, Clone, PartialEq)]
+struct Dummy2 {
+ field1: u8,
+ field2: u8,
+ field3: u16,
+ field4: u32,
+ field5: u64,
+}
+
+unsafe impl Plain for Dummy2 {}
+
+fn as_bytes<T: ?Sized>(r: &T) -> &[u8] {
+ unsafe { methods::as_bytes(r) }
+}
+
+fn as_mut_bytes<T: Plain + ?Sized>(r: &mut T) -> &mut [u8] {
+ unsafe { methods::as_mut_bytes(r) }
+}
+
+#[test]
+fn one_too_short() {
+ let b = vec![0u8; mem::size_of::<Dummy1>() - 1];
+
+ let r = Dummy1::from_bytes(&b);
+ assert!(r == Err(Error::TooShort));
+}
+
+#[test]
+fn unaligned() {
+ let b = vec![0u8; mem::size_of::<Dummy1>() + 1];
+ let b = &b[1..];
+
+ let r = Dummy1::from_bytes(&b);
+ assert!(r == Err(Error::BadAlignment));
+}
+
+#[test]
+fn copy_test() {
+ let t1 = Dummy1 {
+ field1: 0xaaaaaaaaaaaaaaaau64,
+ field2: 0xbbbbbbbbu32,
+ field3: 0xccccu16,
+ field4: 0xddu8,
+ field5: 0xeeu8,
+ };
+
+ let mut t2 = Dummy2::default();
+
+ assert!(t2.copy_from_bytes(as_bytes(&t1)) == Ok(()));
+
+ assert!(t2.field1 == 0xaau8);
+ assert!(t2.field2 == 0xaau8);
+ assert!(t2.field3 == 0xaaaau16);
+ assert!(t2.field4 == 0xaaaaaaaau32);
+ assert!(t2.field5 == 0xbbbbbbbbccccddeeu64 || t2.field5 == 0xeeddccccbbbbbbbbu64);
+
+ let sz = mem::size_of::<Dummy2>();
+ assert!(t2.copy_from_bytes(&as_bytes(&t1)[..sz - 1]) == Err(Error::TooShort));
+}
+
+#[test]
+fn basic_function() {
+ let t1 = Dummy1 {
+ field1: 0xaaaaaaaaaaaaaaaau64,
+ field2: 0xbbbbbbbbu32,
+ field3: 0xccccu16,
+ field4: 0xddu8,
+ field5: 0xeeu8,
+ };
+
+ let r1: &Dummy2 = from_bytes(as_bytes(&t1)).unwrap();
+
+ assert!(r1.field1 == 0xaau8);
+ assert!(r1.field2 == 0xaau8);
+ assert!(r1.field3 == 0xaaaau16);
+ assert!(r1.field4 == 0xaaaaaaaau32);
+ assert!(r1.field5 == 0xbbbbbbbbccccddeeu64 || r1.field5 == 0xeeddccccbbbbbbbbu64);
+
+ let r2 = as_bytes(r1);
+ assert!(r2.len() == mem::size_of::<Dummy1>());
+ assert!(r2[5] == 0xaa);
+
+ let size = r2.len();
+ let r3 = as_bytes(r2);
+ assert!(r3.len() == size);
+
+ let r4 = Dummy1::from_bytes(r3).unwrap();
+
+ let r5 = from_bytes::<Dummy2>(as_bytes(r4)).unwrap();
+
+ {
+ let r6 = slice_from_bytes::<Dummy1>(as_bytes(r5)).unwrap();
+
+ assert!(r6.len() == 1);
+ assert!(t1 == r6[0]);
+ }
+
+ let r7 = slice_from_bytes::<u64>(as_bytes(r5)).unwrap();
+ assert!(r7.len() == 2);
+
+ assert!(r7[0] == 0xaaaaaaaaaaaaaaaau64);
+ assert!(r7[1] == 0xbbbbbbbbccccddeeu64 || r7[1] == 0xeeddccccbbbbbbbbu64);
+}