diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:47:55 +0000 |
commit | 2aadc03ef15cb5ca5cc2af8a7c08e070742f0ac4 (patch) | |
tree | 033cc839730fda84ff08db877037977be94e5e3a /vendor/arrayvec | |
parent | Initial commit. (diff) | |
download | cargo-2aadc03ef15cb5ca5cc2af8a7c08e070742f0ac4.tar.xz cargo-2aadc03ef15cb5ca5cc2af8a7c08e070742f0ac4.zip |
Adding upstream version 0.70.1+ds1.upstream/0.70.1+ds1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/arrayvec')
-rw-r--r-- | vendor/arrayvec/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | vendor/arrayvec/CHANGELOG.md | 234 | ||||
-rw-r--r-- | vendor/arrayvec/Cargo.toml | 63 | ||||
-rw-r--r-- | vendor/arrayvec/LICENSE-APACHE | 201 | ||||
-rw-r--r-- | vendor/arrayvec/LICENSE-MIT | 25 | ||||
-rw-r--r-- | vendor/arrayvec/README.md | 24 | ||||
-rw-r--r-- | vendor/arrayvec/benches/arraystring.rs | 90 | ||||
-rw-r--r-- | vendor/arrayvec/benches/extend.rs | 78 | ||||
-rw-r--r-- | vendor/arrayvec/ci/miri.sh | 15 | ||||
-rw-r--r-- | vendor/arrayvec/custom.css | 25 | ||||
-rw-r--r-- | vendor/arrayvec/src/array.rs | 151 | ||||
-rw-r--r-- | vendor/arrayvec/src/array_string.rs | 582 | ||||
-rw-r--r-- | vendor/arrayvec/src/char.rs | 99 | ||||
-rw-r--r-- | vendor/arrayvec/src/errors.rs | 49 | ||||
-rw-r--r-- | vendor/arrayvec/src/lib.rs | 1213 | ||||
-rw-r--r-- | vendor/arrayvec/src/maybe_uninit.rs | 44 | ||||
-rw-r--r-- | vendor/arrayvec/tests/serde.rs | 79 | ||||
-rw-r--r-- | vendor/arrayvec/tests/tests.rs | 688 |
18 files changed, 3661 insertions, 0 deletions
diff --git a/vendor/arrayvec/.cargo-checksum.json b/vendor/arrayvec/.cargo-checksum.json new file mode 100644 index 0000000..dac86de --- /dev/null +++ b/vendor/arrayvec/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{},"package":"23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"}
\ No newline at end of file diff --git a/vendor/arrayvec/CHANGELOG.md b/vendor/arrayvec/CHANGELOG.md new file mode 100644 index 0000000..9ee813c --- /dev/null +++ b/vendor/arrayvec/CHANGELOG.md @@ -0,0 +1,234 @@ +Recent Changes (arrayvec) +------------------------- + +- 0.5.2 + + - Add `is_empty` methods for ArrayVec and ArrayString by @nicbn + - Implement `TryFrom<Slice>` for ArrayVec by @paulkernfeld + - Add `unstable-const-fn` to make `new` methods const by @m-ou-se + - Run miri in CI and a few related fixes by @RalfJung + - Fix outdated comment by @Phlosioneer + - Move changelog to a separate file by @Luro02 + - Remove deprecated `Error::description` by @AnderEnder + - Use pointer method `add` by @hbina + +- 0.5.1 + + - Add `as_ptr`, `as_mut_ptr` accessors directly on the `ArrayVec` by @tbu- + (matches the same addition to `Vec` which happened in Rust 1.37). + - Add method `ArrayString::len` (now available directly, not just through deref to str). + - Use raw pointers instead of `&mut [u8]` for encoding chars into `ArrayString` + (uninit best practice fix). + - Use raw pointers instead of `get_unchecked_mut` where the target may be + uninitialized everywhere relevant in the ArrayVec implementation + (uninit best practice fix). + - Changed inline hints on many methods, mainly removing inline hints + - `ArrayVec::dispose` is now deprecated (it has no purpose anymore) + +- 0.4.12 + + - Use raw pointers instead of `get_unchecked_mut` where the target may be + uninitialized everywhere relevant in the ArrayVec implementation. + +- 0.5.0 + + - Use `MaybeUninit` (now unconditionally) in the implementation of + `ArrayVec` + - Use `MaybeUninit` (now unconditionally) in the implementation of + `ArrayString` + - The crate feature for serde serialization is now named `serde`. + - Updated the `Array` trait interface, and it is now easier to use for + users outside the crate. + - Add `FromStr` impl for `ArrayString` by @despawnerer + - Add method `try_extend_from_slice` to `ArrayVec`, which is always + effecient by @Thomasdezeeuw. + - Add method `remaining_capacity` by @Thomasdezeeuw + - Improve performance of the `extend` method. + - The index type of zero capacity vectors is now itself zero size, by + @clarfon + - Use `drop_in_place` for truncate and clear methods. This affects drop order + and resume from panic during drop. + - Use Rust 2018 edition for the implementation + - Require Rust 1.36 or later, for the unconditional `MaybeUninit` + improvements. + +- 0.4.11 + + - In Rust 1.36 or later, use newly stable `MaybeUninit`. This extends the + soundness work introduced in 0.4.9, we are finally able to use this in + stable. We use feature detection (build script) to enable this at build + time. + +- 0.4.10 + + - Use `repr(C)` in the `union` version that was introduced in 0.4.9, to + allay some soundness concerns. + +- 0.4.9 + + - Use `union` in the implementation on when this is detected to be supported + (nightly only for now). This is a better solution for treating uninitialized + regions correctly, and we'll use it in stable Rust as soon as we are able. + When this is enabled, the `ArrayVec` has no space overhead in its memory + layout, although the size of the vec should not be relied upon. (See [#114](https://github.com/bluss/arrayvec/pull/114)) + - `ArrayString` updated to not use uninitialized memory, it instead zeros its + backing array. This will be refined in the next version, since we + need to make changes to the user visible API. + - The `use_union` feature now does nothing (like its documentation foretold). + + +- 0.4.8 + + - Implement Clone and Debug for `IntoIter` by @clarcharr + - Add more array sizes under crate features. These cover all in the range + up to 128 and 129 to 255 respectively (we have a few of those by default): + + - `array-size-33-128` + - `array-size-129-255` + +- 0.4.7 + + - Fix future compat warning about raw pointer casts + - Use `drop_in_place` when dropping the arrayvec by-value iterator + - Decrease mininum Rust version (see docs) by @jeehoonkang + +- 0.3.25 + + - Fix future compat warning about raw pointer casts + +- 0.4.6 + + - Fix compilation on 16-bit targets. This means, the 65536 array size is not + included on these targets. + +- 0.3.24 + + - Fix compilation on 16-bit targets. This means, the 65536 array size is not + included on these targets. + - Fix license files so that they are both included (was fixed in 0.4 before) + +- 0.4.5 + + - Add methods to `ArrayString` by @DenialAdams: + + - `.pop() -> Option<char>` + - `.truncate(new_len)` + - `.remove(index) -> char` + + - Remove dependency on crate odds + - Document debug assertions in unsafe methods better + +- 0.4.4 + + - Add method `ArrayVec::truncate()` by @niklasf + +- 0.4.3 + + - Improve performance for `ArrayVec::extend` with a lower level + implementation (#74) + - Small cleanup in dependencies (use no std for crates where we don't need more) + +- 0.4.2 + + - Add constructor method `new` to `CapacityError`. + +- 0.4.1 + + - Add `Default` impl to `ArrayString` by @tbu- + +- 0.4.0 + + - Reformed signatures and error handling by @bluss and @tbu-: + + - `ArrayVec`'s `push, insert, remove, swap_remove` now match `Vec`'s + corresponding signature and panic on capacity errors where applicable. + - Add fallible methods `try_push, insert` and checked methods + `pop_at, swap_pop`. + - Similar changes to `ArrayString`'s push methods. + + - Use a local version of the `RangeArgument` trait + - Add array sizes 50, 150, 200 by @daboross + - Support serde 1.0 by @daboross + - New method `.push_unchecked()` by @niklasf + - `ArrayString` implements `PartialOrd, Ord` by @tbu- + - Require Rust 1.14 + - crate feature `use_generic_array` was dropped. + +- 0.3.23 + + - Implement `PartialOrd, Ord` as well as `PartialOrd<str>` for + `ArrayString`. + +- 0.3.22 + + - Implement `Array` for the 65536 size + +- 0.3.21 + + - Use `encode_utf8` from crate odds + - Add constructor `ArrayString::from_byte_string` + +- 0.3.20 + + - Simplify and speed up `ArrayString`’s `.push(char)`- + +- 0.3.19 + + - Add new crate feature `use_generic_array` which allows using their + `GenericArray` just like a regular fixed size array for the storage + of an `ArrayVec`. + +- 0.3.18 + + - Fix bounds check in `ArrayVec::insert`! + It would be buggy if `self.len() < index < self.capacity()`. Take note of + the push out behavior specified in the docs. + +- 0.3.17 + + - Added crate feature `use_union` which forwards to the nodrop crate feature + - Added methods `.is_full()` to `ArrayVec` and `ArrayString`. + +- 0.3.16 + + - Added method `.retain()` to `ArrayVec`. + - Added methods `.as_slice(), .as_mut_slice()` to `ArrayVec` and `.as_str()` + to `ArrayString`. + +- 0.3.15 + + - Add feature std, which you can opt out of to use `no_std` (requires Rust 1.6 + to opt out). + - Implement `Clone::clone_from` for ArrayVec and ArrayString + +- 0.3.14 + + - Add `ArrayString::from(&str)` + +- 0.3.13 + + - Added `DerefMut` impl for `ArrayString`. + - Added method `.simplify()` to drop the element for `CapacityError`. + - Added method `.dispose()` to `ArrayVec` + +- 0.3.12 + + - Added ArrayString, a fixed capacity analogy of String + +- 0.3.11 + + - Added trait impls Default, PartialOrd, Ord, Write for ArrayVec + +- 0.3.10 + + - Go back to using external NoDrop, fixing a panic safety bug (issue #3) + +- 0.3.8 + + - Inline the non-dropping logic to remove one drop flag in the + ArrayVec representation. + +- 0.3.7 + + - Added method .into_inner() + - Added unsafe method .set_len() diff --git a/vendor/arrayvec/Cargo.toml b/vendor/arrayvec/Cargo.toml new file mode 100644 index 0000000..4fb37c1 --- /dev/null +++ b/vendor/arrayvec/Cargo.toml @@ -0,0 +1,63 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +edition = "2018" +name = "arrayvec" +version = "0.5.2" +authors = ["bluss"] +description = "A vector with fixed capacity, backed by an array (it can be stored on the stack too). Implements fixed capacity ArrayVec and ArrayString." +documentation = "https://docs.rs/arrayvec/" +keywords = ["stack", "vector", "array", "data-structure", "no_std"] +categories = ["data-structures", "no-std"] +license = "MIT/Apache-2.0" +repository = "https://github.com/bluss/arrayvec" +[package.metadata.docs.rs] +features = ["serde"] + +[package.metadata.release] +no-dev-version = true +tag-name = "{{version}}" +[profile.bench] +debug = true + +[profile.release] +debug = true + +[[bench]] +name = "extend" +harness = false + +[[bench]] +name = "arraystring" +harness = false +[dependencies.serde] +version = "1.0" +optional = true +default-features = false +[dev-dependencies.bencher] +version = "0.1.4" + +[dev-dependencies.matches] +version = "0.1" + +[dev-dependencies.serde_test] +version = "1.0" + +[build-dependencies] + +[features] +array-sizes-129-255 = [] +array-sizes-33-128 = [] +default = ["std"] +std = [] +unstable-const-fn = [] diff --git a/vendor/arrayvec/LICENSE-APACHE b/vendor/arrayvec/LICENSE-APACHE new file mode 100644 index 0000000..16fe87b --- /dev/null +++ b/vendor/arrayvec/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/vendor/arrayvec/LICENSE-MIT b/vendor/arrayvec/LICENSE-MIT new file mode 100644 index 0000000..2c8f27d --- /dev/null +++ b/vendor/arrayvec/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) Ulrik Sverdrup "bluss" 2015-2017 + +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/vendor/arrayvec/README.md b/vendor/arrayvec/README.md new file mode 100644 index 0000000..bfac3b3 --- /dev/null +++ b/vendor/arrayvec/README.md @@ -0,0 +1,24 @@ + +arrayvec +======== +[![Crates.io: arrayvec](https://img.shields.io/crates/v/arrayvec.svg)](https://crates.io/crates/arrayvec) +[![Crates.io: nodrop](https://img.shields.io/crates/v/nodrop.svg)](https://crates.io/crates/nodrop) +[![Documentation](https://docs.rs/arrayvec/badge.svg)](https://docs.rs/arrayvec) +[![Build Status](https://travis-ci.org/bluss/arrayvec.svg?branch=master)](https://travis-ci.org/bluss/arrayvec) +[![License: Apache](https://img.shields.io/badge/License-Apache%202.0-red.svg)](LICENSE-APACHE) +OR +[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) + +A vector with fixed capacity. + +Please read the [`API documentation here`](https://docs.rs/arrayvec) + +# License + +Dual-licensed to be compatible with the Rust project. + +Licensed under the Apache License, Version 2.0 +http://www.apache.org/licenses/LICENSE-2.0 or the MIT license +http://opensource.org/licenses/MIT, at your +option. This file may not be copied, modified, or distributed +except according to those terms. diff --git a/vendor/arrayvec/benches/arraystring.rs b/vendor/arrayvec/benches/arraystring.rs new file mode 100644 index 0000000..9cff587 --- /dev/null +++ b/vendor/arrayvec/benches/arraystring.rs @@ -0,0 +1,90 @@ + +extern crate arrayvec; +#[macro_use] extern crate bencher; + +use arrayvec::ArrayString; + +use bencher::Bencher; + +fn try_push_c(b: &mut Bencher) { + let mut v = ArrayString::<[u8; 512]>::new(); + b.iter(|| { + v.clear(); + while v.try_push('c').is_ok() { + } + v.len() + }); + b.bytes = v.capacity() as u64; +} + +fn try_push_alpha(b: &mut Bencher) { + let mut v = ArrayString::<[u8; 512]>::new(); + b.iter(|| { + v.clear(); + while v.try_push('α').is_ok() { + } + v.len() + }); + b.bytes = v.capacity() as u64; +} + +// Yes, pushing a string char-by-char is slow. Use .push_str. +fn try_push_string(b: &mut Bencher) { + let mut v = ArrayString::<[u8; 512]>::new(); + let input = "abcαβγ“”"; + b.iter(|| { + v.clear(); + for ch in input.chars().cycle() { + if !v.try_push(ch).is_ok() { + break; + } + } + v.len() + }); + b.bytes = v.capacity() as u64; +} + +fn push_c(b: &mut Bencher) { + let mut v = ArrayString::<[u8; 512]>::new(); + b.iter(|| { + v.clear(); + while !v.is_full() { + v.push('c'); + } + v.len() + }); + b.bytes = v.capacity() as u64; +} + +fn push_alpha(b: &mut Bencher) { + let mut v = ArrayString::<[u8; 512]>::new(); + b.iter(|| { + v.clear(); + while !v.is_full() { + v.push('α'); + } + v.len() + }); + b.bytes = v.capacity() as u64; +} + +fn push_string(b: &mut Bencher) { + let mut v = ArrayString::<[u8; 512]>::new(); + let input = "abcαβγ“”"; + b.iter(|| { + v.clear(); + for ch in input.chars().cycle() { + if !v.is_full() { + v.push(ch); + } else { + break; + } + } + v.len() + }); + b.bytes = v.capacity() as u64; +} + +benchmark_group!(benches, try_push_c, try_push_alpha, try_push_string, push_c, + push_alpha, push_string); +benchmark_main!(benches); diff --git a/vendor/arrayvec/benches/extend.rs b/vendor/arrayvec/benches/extend.rs new file mode 100644 index 0000000..0579717 --- /dev/null +++ b/vendor/arrayvec/benches/extend.rs @@ -0,0 +1,78 @@ + +extern crate arrayvec; +#[macro_use] extern crate bencher; + +use std::io::Write; + +use arrayvec::ArrayVec; + +use bencher::Bencher; +use bencher::black_box; + +fn extend_with_constant(b: &mut Bencher) { + let mut v = ArrayVec::<[u8; 512]>::new(); + let cap = v.capacity(); + b.iter(|| { + v.clear(); + let constant = black_box(1); + v.extend((0..cap).map(move |_| constant)); + v[511] + }); + b.bytes = v.capacity() as u64; +} + +fn extend_with_range(b: &mut Bencher) { + let mut v = ArrayVec::<[u8; 512]>::new(); + let cap = v.capacity(); + b.iter(|| { + v.clear(); + let range = 0..cap; + v.extend(range.map(|x| black_box(x as _))); + v[511] + }); + b.bytes = v.capacity() as u64; +} + +fn extend_with_slice(b: &mut Bencher) { + let mut v = ArrayVec::<[u8; 512]>::new(); + let data = [1; 512]; + b.iter(|| { + v.clear(); + let iter = data.iter().map(|&x| x); + v.extend(iter); + v[511] + }); + b.bytes = v.capacity() as u64; +} + +fn extend_with_write(b: &mut Bencher) { + let mut v = ArrayVec::<[u8; 512]>::new(); + let data = [1; 512]; + b.iter(|| { + v.clear(); + v.write(&data[..]).ok(); + v[511] + }); + b.bytes = v.capacity() as u64; +} + +fn extend_from_slice(b: &mut Bencher) { + let mut v = ArrayVec::<[u8; 512]>::new(); + let data = [1; 512]; + b.iter(|| { + v.clear(); + v.try_extend_from_slice(&data).ok(); + v[511] + }); + b.bytes = v.capacity() as u64; +} + +benchmark_group!(benches, + extend_with_constant, + extend_with_range, + extend_with_slice, + extend_with_write, + extend_from_slice +); + +benchmark_main!(benches); diff --git a/vendor/arrayvec/ci/miri.sh b/vendor/arrayvec/ci/miri.sh new file mode 100644 index 0000000..6b95c2d --- /dev/null +++ b/vendor/arrayvec/ci/miri.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env sh + +set -ex + +export CARGO_NET_RETRY=5 +export CARGO_NET_TIMEOUT=10 + +MIRI_NIGHTLY=nightly-$(curl -s https://rust-lang.github.io/rustup-components-history/x86_64-unknown-linux-gnu/miri) +echo "Installing latest nightly with Miri: $MIRI_NIGHTLY" +rustup default "$MIRI_NIGHTLY" + +rustup component add miri +cargo miri setup + +cargo miri test diff --git a/vendor/arrayvec/custom.css b/vendor/arrayvec/custom.css new file mode 100644 index 0000000..8e0b705 --- /dev/null +++ b/vendor/arrayvec/custom.css @@ -0,0 +1,25 @@ + +.docblock pre.rust { background: #eeeeff; } +pre.trait, pre.fn, pre.struct, pre.enum, pre.typedef { background: #fcfefc; } + +/* Small “example” label for doc examples */ +.docblock pre.rust::before { + content: "example"; + float: right; + font-style: italic; + font-size: 0.8em; + margin-top: -10px; + margin-right: -5px; +} + + +/* Fixup where display in trait listing */ +pre.trait .where::before { +content: '\a '; +} + +.docblock code { + background-color: inherit; + font-weight: bold; + padding: 0 0.1em; +} diff --git a/vendor/arrayvec/src/array.rs b/vendor/arrayvec/src/array.rs new file mode 100644 index 0000000..2de5e77 --- /dev/null +++ b/vendor/arrayvec/src/array.rs @@ -0,0 +1,151 @@ + +/// Trait for fixed size arrays. +/// +/// This trait is implemented for some specific array sizes, see +/// the implementor list below. At the current state of Rust we can't +/// make this fully general for every array size. +/// +/// The following crate features add more array sizes (and they are not +/// enabled by default due to their impact on compliation speed). +/// +/// - `array-sizes-33-128`: All sizes 33 to 128 are implemented +/// (a few in this range are included by default). +/// - `array-sizes-129-255`: All sizes 129 to 255 are implemented +/// (a few in this range are included by default). +/// +/// ## Safety +/// +/// This trait can *only* be implemented by fixed-size arrays or types with +/// *exactly* the representation of a fixed size array (of the right element +/// type and capacity). +/// +/// Normally this trait is an implementation detail of arrayvec and doesn’t +/// need implementing. +pub unsafe trait Array { + /// The array’s element type + type Item; + /// The smallest type that can index and tell the length of the array. + #[doc(hidden)] + type Index: Index; + /// The array's element capacity + const CAPACITY: usize; + fn as_slice(&self) -> &[Self::Item]; + fn as_mut_slice(&mut self) -> &mut [Self::Item]; +} + +pub trait Index : PartialEq + Copy { + const ZERO: Self; + fn to_usize(self) -> usize; + fn from(_: usize) -> Self; +} + +impl Index for () { + const ZERO: Self = (); + #[inline(always)] + fn to_usize(self) -> usize { 0 } + #[inline(always)] + fn from(_ix: usize) -> Self { () } +} + +impl Index for bool { + const ZERO: Self = false; + #[inline(always)] + fn to_usize(self) -> usize { self as usize } + #[inline(always)] + fn from(ix: usize) -> Self { ix != 0 } +} + +impl Index for u8 { + const ZERO: Self = 0; + #[inline(always)] + fn to_usize(self) -> usize { self as usize } + #[inline(always)] + fn from(ix: usize) -> Self { ix as u8 } +} + +impl Index for u16 { + const ZERO: Self = 0; + #[inline(always)] + fn to_usize(self) -> usize { self as usize } + #[inline(always)] + fn from(ix: usize) -> Self { ix as u16 } +} + +impl Index for u32 { + const ZERO: Self = 0; + #[inline(always)] + fn to_usize(self) -> usize { self as usize } + #[inline(always)] + fn from(ix: usize) -> Self { ix as u32 } +} + +impl Index for usize { + const ZERO: Self = 0; + #[inline(always)] + fn to_usize(self) -> usize { self } + #[inline(always)] + fn from(ix: usize) -> Self { ix } +} + +macro_rules! fix_array_impl { + ($index_type:ty, $len:expr ) => ( + unsafe impl<T> Array for [T; $len] { + type Item = T; + type Index = $index_type; + const CAPACITY: usize = $len; + #[doc(hidden)] + fn as_slice(&self) -> &[Self::Item] { self } + #[doc(hidden)] + fn as_mut_slice(&mut self) -> &mut [Self::Item] { self } + } + ) +} + +macro_rules! fix_array_impl_recursive { + ($index_type:ty, ) => (); + ($index_type:ty, $($len:expr,)*) => ( + $(fix_array_impl!($index_type, $len);)* + ); +} + + +fix_array_impl_recursive!((), 0,); +fix_array_impl_recursive!(bool, 1,); +fix_array_impl_recursive!(u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, ); + +#[cfg(not(feature="array-sizes-33-128"))] +fix_array_impl_recursive!(u8, 32, 40, 48, 50, 56, 64, 72, 96, 100, 128, ); + +#[cfg(feature="array-sizes-33-128")] +fix_array_impl_recursive!(u8, +32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, +52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, +72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, +92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, +109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, +125, 126, 127, 128, +); + +#[cfg(not(feature="array-sizes-129-255"))] +fix_array_impl_recursive!(u8, 160, 192, 200, 224,); + +#[cfg(feature="array-sizes-129-255")] +fix_array_impl_recursive!(u8, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, +141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, +157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, +173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, +189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, +205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, +221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, +237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, +253, 254, 255, +); + +fix_array_impl_recursive!(u16, 256, 384, 512, 768, 1024, 2048, 4096, 8192, 16384, 32768,); +// This array size doesn't exist on 16-bit +#[cfg(any(target_pointer_width="32", target_pointer_width="64"))] +fix_array_impl_recursive!(u32, 1 << 16,); + diff --git a/vendor/arrayvec/src/array_string.rs b/vendor/arrayvec/src/array_string.rs new file mode 100644 index 0000000..1aae59e --- /dev/null +++ b/vendor/arrayvec/src/array_string.rs @@ -0,0 +1,582 @@ +use std::borrow::Borrow; +use std::cmp; +use std::fmt; +use std::hash::{Hash, Hasher}; +use std::ptr; +use std::ops::{Deref, DerefMut}; +use std::str; +use std::str::FromStr; +use std::str::Utf8Error; +use std::slice; + +use crate::array::Array; +use crate::array::Index; +use crate::CapacityError; +use crate::char::encode_utf8; + +#[cfg(feature="serde")] +use serde::{Serialize, Deserialize, Serializer, Deserializer}; + +use super::MaybeUninit as MaybeUninitCopy; + +/// A string with a fixed capacity. +/// +/// The `ArrayString` is a string backed by a fixed size array. It keeps track +/// of its length. +/// +/// The string is a contiguous value that you can store directly on the stack +/// if needed. +#[derive(Copy)] +pub struct ArrayString<A> + where A: Array<Item=u8> + Copy +{ + xs: MaybeUninitCopy<A>, + len: A::Index, +} + +impl<A> Default for ArrayString<A> + where A: Array<Item=u8> + Copy +{ + /// Return an empty `ArrayString` + fn default() -> ArrayString<A> { + ArrayString::new() + } +} + +impl<A> ArrayString<A> + where A: Array<Item=u8> + Copy +{ + /// Create a new empty `ArrayString`. + /// + /// Capacity is inferred from the type parameter. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// let mut string = ArrayString::<[_; 16]>::new(); + /// string.push_str("foo"); + /// assert_eq!(&string[..], "foo"); + /// assert_eq!(string.capacity(), 16); + /// ``` + #[cfg(not(feature="unstable-const-fn"))] + pub fn new() -> ArrayString<A> { + unsafe { + ArrayString { + xs: MaybeUninitCopy::uninitialized(), + len: Index::ZERO, + } + } + } + + #[cfg(feature="unstable-const-fn")] + pub const fn new() -> ArrayString<A> { + unsafe { + ArrayString { + xs: MaybeUninitCopy::uninitialized(), + len: Index::ZERO, + } + } + } + + /// Return the length of the string. + #[inline] + pub fn len(&self) -> usize { self.len.to_usize() } + + /// Returns whether the string is empty. + #[inline] + pub fn is_empty(&self) -> bool { self.len() == 0 } + + /// Create a new `ArrayString` from a `str`. + /// + /// Capacity is inferred from the type parameter. + /// + /// **Errors** if the backing array is not large enough to fit the string. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// let mut string = ArrayString::<[_; 3]>::from("foo").unwrap(); + /// assert_eq!(&string[..], "foo"); + /// assert_eq!(string.len(), 3); + /// assert_eq!(string.capacity(), 3); + /// ``` + pub fn from(s: &str) -> Result<Self, CapacityError<&str>> { + let mut arraystr = Self::new(); + arraystr.try_push_str(s)?; + Ok(arraystr) + } + + /// Create a new `ArrayString` from a byte string literal. + /// + /// **Errors** if the byte string literal is not valid UTF-8. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// let string = ArrayString::from_byte_string(b"hello world").unwrap(); + /// ``` + pub fn from_byte_string(b: &A) -> Result<Self, Utf8Error> { + let len = str::from_utf8(b.as_slice())?.len(); + debug_assert_eq!(len, A::CAPACITY); + Ok(ArrayString { + xs: MaybeUninitCopy::from(*b), + len: Index::from(A::CAPACITY), + }) + } + + /// Return the capacity of the `ArrayString`. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// let string = ArrayString::<[_; 3]>::new(); + /// assert_eq!(string.capacity(), 3); + /// ``` + #[inline(always)] + pub fn capacity(&self) -> usize { A::CAPACITY } + + /// Return if the `ArrayString` is completely filled. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// let mut string = ArrayString::<[_; 1]>::new(); + /// assert!(!string.is_full()); + /// string.push_str("A"); + /// assert!(string.is_full()); + /// ``` + pub fn is_full(&self) -> bool { self.len() == self.capacity() } + + /// Adds the given char to the end of the string. + /// + /// ***Panics*** if the backing array is not large enough to fit the additional char. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// let mut string = ArrayString::<[_; 2]>::new(); + /// + /// string.push('a'); + /// string.push('b'); + /// + /// assert_eq!(&string[..], "ab"); + /// ``` + pub fn push(&mut self, c: char) { + self.try_push(c).unwrap(); + } + + /// Adds the given char to the end of the string. + /// + /// Returns `Ok` if the push succeeds. + /// + /// **Errors** if the backing array is not large enough to fit the additional char. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// let mut string = ArrayString::<[_; 2]>::new(); + /// + /// string.try_push('a').unwrap(); + /// string.try_push('b').unwrap(); + /// let overflow = string.try_push('c'); + /// + /// assert_eq!(&string[..], "ab"); + /// assert_eq!(overflow.unwrap_err().element(), 'c'); + /// ``` + pub fn try_push(&mut self, c: char) -> Result<(), CapacityError<char>> { + let len = self.len(); + unsafe { + let ptr = self.xs.ptr_mut().add(len); + let remaining_cap = self.capacity() - len; + match encode_utf8(c, ptr, remaining_cap) { + Ok(n) => { + self.set_len(len + n); + Ok(()) + } + Err(_) => Err(CapacityError::new(c)), + } + } + } + + /// Adds the given string slice to the end of the string. + /// + /// ***Panics*** if the backing array is not large enough to fit the string. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// let mut string = ArrayString::<[_; 2]>::new(); + /// + /// string.push_str("a"); + /// string.push_str("d"); + /// + /// assert_eq!(&string[..], "ad"); + /// ``` + pub fn push_str(&mut self, s: &str) { + self.try_push_str(s).unwrap() + } + + /// Adds the given string slice to the end of the string. + /// + /// Returns `Ok` if the push succeeds. + /// + /// **Errors** if the backing array is not large enough to fit the string. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// let mut string = ArrayString::<[_; 2]>::new(); + /// + /// string.try_push_str("a").unwrap(); + /// let overflow1 = string.try_push_str("bc"); + /// string.try_push_str("d").unwrap(); + /// let overflow2 = string.try_push_str("ef"); + /// + /// assert_eq!(&string[..], "ad"); + /// assert_eq!(overflow1.unwrap_err().element(), "bc"); + /// assert_eq!(overflow2.unwrap_err().element(), "ef"); + /// ``` + pub fn try_push_str<'a>(&mut self, s: &'a str) -> Result<(), CapacityError<&'a str>> { + if s.len() > self.capacity() - self.len() { + return Err(CapacityError::new(s)); + } + unsafe { + let dst = self.xs.ptr_mut().add(self.len()); + let src = s.as_ptr(); + ptr::copy_nonoverlapping(src, dst, s.len()); + let newl = self.len() + s.len(); + self.set_len(newl); + } + Ok(()) + } + + /// Removes the last character from the string and returns it. + /// + /// Returns `None` if this `ArrayString` is empty. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// let mut s = ArrayString::<[_; 3]>::from("foo").unwrap(); + /// + /// assert_eq!(s.pop(), Some('o')); + /// assert_eq!(s.pop(), Some('o')); + /// assert_eq!(s.pop(), Some('f')); + /// + /// assert_eq!(s.pop(), None); + /// ``` + pub fn pop(&mut self) -> Option<char> { + let ch = match self.chars().rev().next() { + Some(ch) => ch, + None => return None, + }; + let new_len = self.len() - ch.len_utf8(); + unsafe { + self.set_len(new_len); + } + Some(ch) + } + + /// Shortens this `ArrayString` to the specified length. + /// + /// If `new_len` is greater than the string’s current length, this has no + /// effect. + /// + /// ***Panics*** if `new_len` does not lie on a `char` boundary. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// let mut string = ArrayString::<[_; 6]>::from("foobar").unwrap(); + /// string.truncate(3); + /// assert_eq!(&string[..], "foo"); + /// string.truncate(4); + /// assert_eq!(&string[..], "foo"); + /// ``` + pub fn truncate(&mut self, new_len: usize) { + if new_len <= self.len() { + assert!(self.is_char_boundary(new_len)); + unsafe { + // In libstd truncate is called on the underlying vector, + // which in turns drops each element. + // As we know we don't have to worry about Drop, + // we can just set the length (a la clear.) + self.set_len(new_len); + } + } + } + + /// Removes a `char` from this `ArrayString` at a byte position and returns it. + /// + /// This is an `O(n)` operation, as it requires copying every element in the + /// array. + /// + /// ***Panics*** if `idx` is larger than or equal to the `ArrayString`’s length, + /// or if it does not lie on a `char` boundary. + /// + /// ``` + /// use arrayvec::ArrayString; + /// + /// let mut s = ArrayString::<[_; 3]>::from("foo").unwrap(); + /// + /// assert_eq!(s.remove(0), 'f'); + /// assert_eq!(s.remove(1), 'o'); + /// assert_eq!(s.remove(0), 'o'); + /// ``` + pub fn remove(&mut self, idx: usize) -> char { + let ch = match self[idx..].chars().next() { + Some(ch) => ch, + None => panic!("cannot remove a char from the end of a string"), + }; + + let next = idx + ch.len_utf8(); + let len = self.len(); + unsafe { + ptr::copy(self.xs.ptr().add(next), + self.xs.ptr_mut().add(idx), + len - next); + self.set_len(len - (next - idx)); + } + ch + } + + /// Make the string empty. + pub fn clear(&mut self) { + unsafe { + self.set_len(0); + } + } + + /// Set the strings’s length. + /// + /// This function is `unsafe` because it changes the notion of the + /// number of “valid” bytes in the string. Use with care. + /// + /// This method uses *debug assertions* to check the validity of `length` + /// and may use other debug assertions. + pub unsafe fn set_len(&mut self, length: usize) { + debug_assert!(length <= self.capacity()); + self.len = Index::from(length); + } + + /// Return a string slice of the whole `ArrayString`. + pub fn as_str(&self) -> &str { + self + } +} + +impl<A> Deref for ArrayString<A> + where A: Array<Item=u8> + Copy +{ + type Target = str; + #[inline] + fn deref(&self) -> &str { + unsafe { + let sl = slice::from_raw_parts(self.xs.ptr(), self.len.to_usize()); + str::from_utf8_unchecked(sl) + } + } +} + +impl<A> DerefMut for ArrayString<A> + where A: Array<Item=u8> + Copy +{ + #[inline] + fn deref_mut(&mut self) -> &mut str { + unsafe { + let sl = slice::from_raw_parts_mut(self.xs.ptr_mut(), self.len.to_usize()); + str::from_utf8_unchecked_mut(sl) + } + } +} + +impl<A> PartialEq for ArrayString<A> + where A: Array<Item=u8> + Copy +{ + fn eq(&self, rhs: &Self) -> bool { + **self == **rhs + } +} + +impl<A> PartialEq<str> for ArrayString<A> + where A: Array<Item=u8> + Copy +{ + fn eq(&self, rhs: &str) -> bool { + &**self == rhs + } +} + +impl<A> PartialEq<ArrayString<A>> for str + where A: Array<Item=u8> + Copy +{ + fn eq(&self, rhs: &ArrayString<A>) -> bool { + self == &**rhs + } +} + +impl<A> Eq for ArrayString<A> + where A: Array<Item=u8> + Copy +{ } + +impl<A> Hash for ArrayString<A> + where A: Array<Item=u8> + Copy +{ + fn hash<H: Hasher>(&self, h: &mut H) { + (**self).hash(h) + } +} + +impl<A> Borrow<str> for ArrayString<A> + where A: Array<Item=u8> + Copy +{ + fn borrow(&self) -> &str { self } +} + +impl<A> AsRef<str> for ArrayString<A> + where A: Array<Item=u8> + Copy +{ + fn as_ref(&self) -> &str { self } +} + +impl<A> fmt::Debug for ArrayString<A> + where A: Array<Item=u8> + Copy +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } +} + +impl<A> fmt::Display for ArrayString<A> + where A: Array<Item=u8> + Copy +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } +} + +/// `Write` appends written data to the end of the string. +impl<A> fmt::Write for ArrayString<A> + where A: Array<Item=u8> + Copy +{ + fn write_char(&mut self, c: char) -> fmt::Result { + self.try_push(c).map_err(|_| fmt::Error) + } + + fn write_str(&mut self, s: &str) -> fmt::Result { + self.try_push_str(s).map_err(|_| fmt::Error) + } +} + +impl<A> Clone for ArrayString<A> + where A: Array<Item=u8> + Copy +{ + fn clone(&self) -> ArrayString<A> { + *self + } + fn clone_from(&mut self, rhs: &Self) { + // guaranteed to fit due to types matching. + self.clear(); + self.try_push_str(rhs).ok(); + } +} + +impl<A> PartialOrd for ArrayString<A> + where A: Array<Item=u8> + Copy +{ + fn partial_cmp(&self, rhs: &Self) -> Option<cmp::Ordering> { + (**self).partial_cmp(&**rhs) + } + fn lt(&self, rhs: &Self) -> bool { **self < **rhs } + fn le(&self, rhs: &Self) -> bool { **self <= **rhs } + fn gt(&self, rhs: &Self) -> bool { **self > **rhs } + fn ge(&self, rhs: &Self) -> bool { **self >= **rhs } +} + +impl<A> PartialOrd<str> for ArrayString<A> + where A: Array<Item=u8> + Copy +{ + fn partial_cmp(&self, rhs: &str) -> Option<cmp::Ordering> { + (**self).partial_cmp(rhs) + } + fn lt(&self, rhs: &str) -> bool { &**self < rhs } + fn le(&self, rhs: &str) -> bool { &**self <= rhs } + fn gt(&self, rhs: &str) -> bool { &**self > rhs } + fn ge(&self, rhs: &str) -> bool { &**self >= rhs } +} + +impl<A> PartialOrd<ArrayString<A>> for str + where A: Array<Item=u8> + Copy +{ + fn partial_cmp(&self, rhs: &ArrayString<A>) -> Option<cmp::Ordering> { + self.partial_cmp(&**rhs) + } + fn lt(&self, rhs: &ArrayString<A>) -> bool { self < &**rhs } + fn le(&self, rhs: &ArrayString<A>) -> bool { self <= &**rhs } + fn gt(&self, rhs: &ArrayString<A>) -> bool { self > &**rhs } + fn ge(&self, rhs: &ArrayString<A>) -> bool { self >= &**rhs } +} + +impl<A> Ord for ArrayString<A> + where A: Array<Item=u8> + Copy +{ + fn cmp(&self, rhs: &Self) -> cmp::Ordering { + (**self).cmp(&**rhs) + } +} + +impl<A> FromStr for ArrayString<A> + where A: Array<Item=u8> + Copy +{ + type Err = CapacityError; + + fn from_str(s: &str) -> Result<Self, Self::Err> { + Self::from(s).map_err(CapacityError::simplify) + } +} + +#[cfg(feature="serde")] +/// Requires crate feature `"serde"` +impl<A> Serialize for ArrayString<A> + where A: Array<Item=u8> + Copy +{ + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where S: Serializer + { + serializer.serialize_str(&*self) + } +} + +#[cfg(feature="serde")] +/// Requires crate feature `"serde"` +impl<'de, A> Deserialize<'de> for ArrayString<A> + where A: Array<Item=u8> + Copy +{ + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where D: Deserializer<'de> + { + use serde::de::{self, Visitor}; + use std::marker::PhantomData; + + struct ArrayStringVisitor<A: Array<Item=u8>>(PhantomData<A>); + + impl<'de, A: Copy + Array<Item=u8>> Visitor<'de> for ArrayStringVisitor<A> { + type Value = ArrayString<A>; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "a string no more than {} bytes long", A::CAPACITY) + } + + fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> + where E: de::Error, + { + ArrayString::from(v).map_err(|_| E::invalid_length(v.len(), &self)) + } + + fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E> + where E: de::Error, + { + let s = str::from_utf8(v).map_err(|_| E::invalid_value(de::Unexpected::Bytes(v), &self))?; + + ArrayString::from(s).map_err(|_| E::invalid_length(s.len(), &self)) + } + } + + deserializer.deserialize_str(ArrayStringVisitor::<A>(PhantomData)) + } +} diff --git a/vendor/arrayvec/src/char.rs b/vendor/arrayvec/src/char.rs new file mode 100644 index 0000000..03d64fc --- /dev/null +++ b/vendor/arrayvec/src/char.rs @@ -0,0 +1,99 @@ +// Copyright 2012-2016 The Rust 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. +// +// Original authors: alexchrichton, bluss + +use std::ptr; + +// UTF-8 ranges and tags for encoding characters +const TAG_CONT: u8 = 0b1000_0000; +const TAG_TWO_B: u8 = 0b1100_0000; +const TAG_THREE_B: u8 = 0b1110_0000; +const TAG_FOUR_B: u8 = 0b1111_0000; +const MAX_ONE_B: u32 = 0x80; +const MAX_TWO_B: u32 = 0x800; +const MAX_THREE_B: u32 = 0x10000; + +/// Placeholder +pub struct EncodeUtf8Error; + +#[inline] +unsafe fn write(ptr: *mut u8, index: usize, byte: u8) { + ptr::write(ptr.add(index), byte) +} + +/// Encode a char into buf using UTF-8. +/// +/// On success, return the byte length of the encoding (1, 2, 3 or 4).<br> +/// On error, return `EncodeUtf8Error` if the buffer was too short for the char. +/// +/// Safety: `ptr` must be writable for `len` bytes. +#[inline] +pub unsafe fn encode_utf8(ch: char, ptr: *mut u8, len: usize) -> Result<usize, EncodeUtf8Error> +{ + let code = ch as u32; + if code < MAX_ONE_B && len >= 1 { + write(ptr, 0, code as u8); + return Ok(1); + } else if code < MAX_TWO_B && len >= 2 { + write(ptr, 0, (code >> 6 & 0x1F) as u8 | TAG_TWO_B); + write(ptr, 1, (code & 0x3F) as u8 | TAG_CONT); + return Ok(2); + } else if code < MAX_THREE_B && len >= 3 { + write(ptr, 0, (code >> 12 & 0x0F) as u8 | TAG_THREE_B); + write(ptr, 1, (code >> 6 & 0x3F) as u8 | TAG_CONT); + write(ptr, 2, (code & 0x3F) as u8 | TAG_CONT); + return Ok(3); + } else if len >= 4 { + write(ptr, 0, (code >> 18 & 0x07) as u8 | TAG_FOUR_B); + write(ptr, 1, (code >> 12 & 0x3F) as u8 | TAG_CONT); + write(ptr, 2, (code >> 6 & 0x3F) as u8 | TAG_CONT); + write(ptr, 3, (code & 0x3F) as u8 | TAG_CONT); + return Ok(4); + }; + Err(EncodeUtf8Error) +} + + +#[test] +#[cfg_attr(miri, ignore)] // Miri is too slow +fn test_encode_utf8() { + // Test that all codepoints are encoded correctly + let mut data = [0u8; 16]; + for codepoint in 0..=(std::char::MAX as u32) { + if let Some(ch) = std::char::from_u32(codepoint) { + for elt in &mut data { *elt = 0; } + let ptr = data.as_mut_ptr(); + let len = data.len(); + unsafe { + let res = encode_utf8(ch, ptr, len).ok().unwrap(); + assert_eq!(res, ch.len_utf8()); + } + let string = std::str::from_utf8(&data).unwrap(); + assert_eq!(string.chars().next(), Some(ch)); + } + } +} + +#[test] +fn test_encode_utf8_oob() { + // test that we report oob if the buffer is too short + let mut data = [0u8; 16]; + let chars = ['a', 'α', '�', '𐍈']; + for (len, &ch) in (1..=4).zip(&chars) { + assert_eq!(len, ch.len_utf8(), "Len of ch={}", ch); + let ptr = data.as_mut_ptr(); + unsafe { + assert!(matches::matches!(encode_utf8(ch, ptr, len - 1), Err(_))); + assert!(matches::matches!(encode_utf8(ch, ptr, len), Ok(_))); + } + } +} + diff --git a/vendor/arrayvec/src/errors.rs b/vendor/arrayvec/src/errors.rs new file mode 100644 index 0000000..380742a --- /dev/null +++ b/vendor/arrayvec/src/errors.rs @@ -0,0 +1,49 @@ +use std::fmt; +#[cfg(feature="std")] +use std::any::Any; +#[cfg(feature="std")] +use std::error::Error; + +/// Error value indicating insufficient capacity +#[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)] +pub struct CapacityError<T = ()> { + element: T, +} + +impl<T> CapacityError<T> { + /// Create a new `CapacityError` from `element`. + pub fn new(element: T) -> CapacityError<T> { + CapacityError { + element: element, + } + } + + /// Extract the overflowing element + pub fn element(self) -> T { + self.element + } + + /// Convert into a `CapacityError` that does not carry an element. + pub fn simplify(self) -> CapacityError { + CapacityError { element: () } + } +} + +const CAPERROR: &'static str = "insufficient capacity"; + +#[cfg(feature="std")] +/// Requires `features="std"`. +impl<T: Any> Error for CapacityError<T> {} + +impl<T> fmt::Display for CapacityError<T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", CAPERROR) + } +} + +impl<T> fmt::Debug for CapacityError<T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}: {}", "CapacityError", CAPERROR) + } +} + diff --git a/vendor/arrayvec/src/lib.rs b/vendor/arrayvec/src/lib.rs new file mode 100644 index 0000000..a5d6c06 --- /dev/null +++ b/vendor/arrayvec/src/lib.rs @@ -0,0 +1,1213 @@ +//! **arrayvec** provides the types `ArrayVec` and `ArrayString`: +//! array-backed vector and string types, which store their contents inline. +//! +//! The arrayvec package has the following cargo features: +//! +//! - `std` +//! - Optional, enabled by default +//! - Use libstd; disable to use `no_std` instead. +//! +//! - `serde` +//! - Optional +//! - Enable serialization for ArrayVec and ArrayString using serde 1.x +//! - `array-sizes-33-128`, `array-sizes-129-255` +//! - Optional +//! - Enable more array sizes (see [Array] for more information) +//! +//! - `unstable-const-fn` +//! - Optional +//! - Makes [`ArrayVec::new`] and [`ArrayString::new`] `const fn`s, +//! using the nightly `const_fn` feature. +//! - Unstable and requires nightly. +//! +//! ## Rust Version +//! +//! This version of arrayvec requires Rust 1.36 or later. +//! +#![doc(html_root_url="https://docs.rs/arrayvec/0.4/")] +#![cfg_attr(not(feature="std"), no_std)] +#![cfg_attr(feature="unstable-const-fn", feature(const_fn))] + +#[cfg(feature="serde")] +extern crate serde; + +#[cfg(not(feature="std"))] +extern crate core as std; + +use std::cmp; +use std::iter; +use std::mem; +use std::ops::{Bound, Deref, DerefMut, RangeBounds}; +use std::ptr; +use std::slice; + +// extra traits +use std::borrow::{Borrow, BorrowMut}; +use std::hash::{Hash, Hasher}; +use std::fmt; + +#[cfg(feature="std")] +use std::io; + + +mod maybe_uninit; +use crate::maybe_uninit::MaybeUninit; + +#[cfg(feature="serde")] +use serde::{Serialize, Deserialize, Serializer, Deserializer}; + +mod array; +mod array_string; +mod char; +mod errors; + +pub use crate::array::Array; +use crate::array::Index; +pub use crate::array_string::ArrayString; +pub use crate::errors::CapacityError; + + +/// A vector with a fixed capacity. +/// +/// The `ArrayVec` is a vector backed by a fixed size array. It keeps track of +/// the number of initialized elements. +/// +/// The vector is a contiguous value that you can store directly on the stack +/// if needed. +/// +/// It offers a simple API but also dereferences to a slice, so +/// that the full slice API is available. +/// +/// ArrayVec can be converted into a by value iterator. +pub struct ArrayVec<A: Array> { + xs: MaybeUninit<A>, + len: A::Index, +} + +impl<A: Array> Drop for ArrayVec<A> { + fn drop(&mut self) { + self.clear(); + + // MaybeUninit inhibits array's drop + } +} + +macro_rules! panic_oob { + ($method_name:expr, $index:expr, $len:expr) => { + panic!(concat!("ArrayVec::", $method_name, ": index {} is out of bounds in vector of length {}"), + $index, $len) + } +} + +impl<A: Array> ArrayVec<A> { + /// Create a new empty `ArrayVec`. + /// + /// Capacity is inferred from the type parameter. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::<[_; 16]>::new(); + /// array.push(1); + /// array.push(2); + /// assert_eq!(&array[..], &[1, 2]); + /// assert_eq!(array.capacity(), 16); + /// ``` + #[cfg(not(feature="unstable-const-fn"))] + pub fn new() -> ArrayVec<A> { + unsafe { + ArrayVec { xs: MaybeUninit::uninitialized(), len: Index::ZERO } + } + } + + #[cfg(feature="unstable-const-fn")] + pub const fn new() -> ArrayVec<A> { + unsafe { + ArrayVec { xs: MaybeUninit::uninitialized(), len: Index::ZERO } + } + } + + /// Return the number of elements in the `ArrayVec`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1, 2, 3]); + /// array.pop(); + /// assert_eq!(array.len(), 2); + /// ``` + #[inline] + pub fn len(&self) -> usize { self.len.to_usize() } + + /// Returns whether the `ArrayVec` is empty. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1]); + /// array.pop(); + /// assert_eq!(array.is_empty(), true); + /// ``` + #[inline] + pub fn is_empty(&self) -> bool { self.len() == 0 } + + /// Return the capacity of the `ArrayVec`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let array = ArrayVec::from([1, 2, 3]); + /// assert_eq!(array.capacity(), 3); + /// ``` + #[inline(always)] + pub fn capacity(&self) -> usize { A::CAPACITY } + + /// Return if the `ArrayVec` is completely filled. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::<[_; 1]>::new(); + /// assert!(!array.is_full()); + /// array.push(1); + /// assert!(array.is_full()); + /// ``` + pub fn is_full(&self) -> bool { self.len() == self.capacity() } + + /// Returns the capacity left in the `ArrayVec`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1, 2, 3]); + /// array.pop(); + /// assert_eq!(array.remaining_capacity(), 1); + /// ``` + pub fn remaining_capacity(&self) -> usize { + self.capacity() - self.len() + } + + /// Push `element` to the end of the vector. + /// + /// ***Panics*** if the vector is already full. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::<[_; 2]>::new(); + /// + /// array.push(1); + /// array.push(2); + /// + /// assert_eq!(&array[..], &[1, 2]); + /// ``` + pub fn push(&mut self, element: A::Item) { + self.try_push(element).unwrap() + } + + /// Push `element` to the end of the vector. + /// + /// Return `Ok` if the push succeeds, or return an error if the vector + /// is already full. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::<[_; 2]>::new(); + /// + /// let push1 = array.try_push(1); + /// let push2 = array.try_push(2); + /// + /// assert!(push1.is_ok()); + /// assert!(push2.is_ok()); + /// + /// assert_eq!(&array[..], &[1, 2]); + /// + /// let overflow = array.try_push(3); + /// + /// assert!(overflow.is_err()); + /// ``` + pub fn try_push(&mut self, element: A::Item) -> Result<(), CapacityError<A::Item>> { + if self.len() < A::CAPACITY { + unsafe { + self.push_unchecked(element); + } + Ok(()) + } else { + Err(CapacityError::new(element)) + } + } + + + /// Push `element` to the end of the vector without checking the capacity. + /// + /// It is up to the caller to ensure the capacity of the vector is + /// sufficiently large. + /// + /// This method uses *debug assertions* to check that the arrayvec is not full. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::<[_; 2]>::new(); + /// + /// if array.len() + 2 <= array.capacity() { + /// unsafe { + /// array.push_unchecked(1); + /// array.push_unchecked(2); + /// } + /// } + /// + /// assert_eq!(&array[..], &[1, 2]); + /// ``` + pub unsafe fn push_unchecked(&mut self, element: A::Item) { + let len = self.len(); + debug_assert!(len < A::CAPACITY); + ptr::write(self.get_unchecked_ptr(len), element); + self.set_len(len + 1); + } + + /// Get pointer to where element at `index` would be + unsafe fn get_unchecked_ptr(&mut self, index: usize) -> *mut A::Item { + self.xs.ptr_mut().add(index) + } + + /// Insert `element` at position `index`. + /// + /// Shift up all elements after `index`. + /// + /// It is an error if the index is greater than the length or if the + /// arrayvec is full. + /// + /// ***Panics*** if the array is full or the `index` is out of bounds. See + /// `try_insert` for fallible version. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::<[_; 2]>::new(); + /// + /// array.insert(0, "x"); + /// array.insert(0, "y"); + /// assert_eq!(&array[..], &["y", "x"]); + /// + /// ``` + pub fn insert(&mut self, index: usize, element: A::Item) { + self.try_insert(index, element).unwrap() + } + + /// Insert `element` at position `index`. + /// + /// Shift up all elements after `index`; the `index` must be less than + /// or equal to the length. + /// + /// Returns an error if vector is already at full capacity. + /// + /// ***Panics*** `index` is out of bounds. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::<[_; 2]>::new(); + /// + /// assert!(array.try_insert(0, "x").is_ok()); + /// assert!(array.try_insert(0, "y").is_ok()); + /// assert!(array.try_insert(0, "z").is_err()); + /// assert_eq!(&array[..], &["y", "x"]); + /// + /// ``` + pub fn try_insert(&mut self, index: usize, element: A::Item) -> Result<(), CapacityError<A::Item>> { + if index > self.len() { + panic_oob!("try_insert", index, self.len()) + } + if self.len() == self.capacity() { + return Err(CapacityError::new(element)); + } + let len = self.len(); + + // follows is just like Vec<T> + unsafe { // infallible + // The spot to put the new value + { + let p: *mut _ = self.get_unchecked_ptr(index); + // Shift everything over to make space. (Duplicating the + // `index`th element into two consecutive places.) + ptr::copy(p, p.offset(1), len - index); + // Write it in, overwriting the first copy of the `index`th + // element. + ptr::write(p, element); + } + self.set_len(len + 1); + } + Ok(()) + } + + /// Remove the last element in the vector and return it. + /// + /// Return `Some(` *element* `)` if the vector is non-empty, else `None`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::<[_; 2]>::new(); + /// + /// array.push(1); + /// + /// assert_eq!(array.pop(), Some(1)); + /// assert_eq!(array.pop(), None); + /// ``` + pub fn pop(&mut self) -> Option<A::Item> { + if self.len() == 0 { + return None; + } + unsafe { + let new_len = self.len() - 1; + self.set_len(new_len); + Some(ptr::read(self.get_unchecked_ptr(new_len))) + } + } + + /// Remove the element at `index` and swap the last element into its place. + /// + /// This operation is O(1). + /// + /// Return the *element* if the index is in bounds, else panic. + /// + /// ***Panics*** if the `index` is out of bounds. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1, 2, 3]); + /// + /// assert_eq!(array.swap_remove(0), 1); + /// assert_eq!(&array[..], &[3, 2]); + /// + /// assert_eq!(array.swap_remove(1), 2); + /// assert_eq!(&array[..], &[3]); + /// ``` + pub fn swap_remove(&mut self, index: usize) -> A::Item { + self.swap_pop(index) + .unwrap_or_else(|| { + panic_oob!("swap_remove", index, self.len()) + }) + } + + /// Remove the element at `index` and swap the last element into its place. + /// + /// This is a checked version of `.swap_remove`. + /// This operation is O(1). + /// + /// Return `Some(` *element* `)` if the index is in bounds, else `None`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1, 2, 3]); + /// + /// assert_eq!(array.swap_pop(0), Some(1)); + /// assert_eq!(&array[..], &[3, 2]); + /// + /// assert_eq!(array.swap_pop(10), None); + /// ``` + pub fn swap_pop(&mut self, index: usize) -> Option<A::Item> { + let len = self.len(); + if index >= len { + return None; + } + self.swap(index, len - 1); + self.pop() + } + + /// Remove the element at `index` and shift down the following elements. + /// + /// The `index` must be strictly less than the length of the vector. + /// + /// ***Panics*** if the `index` is out of bounds. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1, 2, 3]); + /// + /// let removed_elt = array.remove(0); + /// assert_eq!(removed_elt, 1); + /// assert_eq!(&array[..], &[2, 3]); + /// ``` + pub fn remove(&mut self, index: usize) -> A::Item { + self.pop_at(index) + .unwrap_or_else(|| { + panic_oob!("remove", index, self.len()) + }) + } + + /// Remove the element at `index` and shift down the following elements. + /// + /// This is a checked version of `.remove(index)`. Returns `None` if there + /// is no element at `index`. Otherwise, return the element inside `Some`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1, 2, 3]); + /// + /// assert!(array.pop_at(0).is_some()); + /// assert_eq!(&array[..], &[2, 3]); + /// + /// assert!(array.pop_at(2).is_none()); + /// assert!(array.pop_at(10).is_none()); + /// ``` + pub fn pop_at(&mut self, index: usize) -> Option<A::Item> { + if index >= self.len() { + None + } else { + self.drain(index..index + 1).next() + } + } + + /// Shortens the vector, keeping the first `len` elements and dropping + /// the rest. + /// + /// If `len` is greater than the vector’s current length this has no + /// effect. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1, 2, 3, 4, 5]); + /// array.truncate(3); + /// assert_eq!(&array[..], &[1, 2, 3]); + /// array.truncate(4); + /// assert_eq!(&array[..], &[1, 2, 3]); + /// ``` + pub fn truncate(&mut self, new_len: usize) { + unsafe { + if new_len < self.len() { + let tail: *mut [_] = &mut self[new_len..]; + self.len = Index::from(new_len); + ptr::drop_in_place(tail); + } + } + } + + /// Remove all elements in the vector. + pub fn clear(&mut self) { + self.truncate(0) + } + + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all elements `e` such that `f(&mut e)` returns false. + /// This method operates in place and preserves the order of the retained + /// elements. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut array = ArrayVec::from([1, 2, 3, 4]); + /// array.retain(|x| *x & 1 != 0 ); + /// assert_eq!(&array[..], &[1, 3]); + /// ``` + pub fn retain<F>(&mut self, mut f: F) + where F: FnMut(&mut A::Item) -> bool + { + let len = self.len(); + let mut del = 0; + { + let v = &mut **self; + + for i in 0..len { + if !f(&mut v[i]) { + del += 1; + } else if del > 0 { + v.swap(i - del, i); + } + } + } + if del > 0 { + self.drain(len - del..); + } + } + + /// Set the vector’s length without dropping or moving out elements + /// + /// This method is `unsafe` because it changes the notion of the + /// number of “valid” elements in the vector. Use with care. + /// + /// This method uses *debug assertions* to check that `length` is + /// not greater than the capacity. + pub unsafe fn set_len(&mut self, length: usize) { + debug_assert!(length <= self.capacity()); + self.len = Index::from(length); + } + + /// Copy and appends all elements in a slice to the `ArrayVec`. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut vec: ArrayVec<[usize; 10]> = ArrayVec::new(); + /// vec.push(1); + /// vec.try_extend_from_slice(&[2, 3]).unwrap(); + /// assert_eq!(&vec[..], &[1, 2, 3]); + /// ``` + /// + /// # Errors + /// + /// This method will return an error if the capacity left (see + /// [`remaining_capacity`]) is smaller then the length of the provided + /// slice. + /// + /// [`remaining_capacity`]: #method.remaining_capacity + pub fn try_extend_from_slice(&mut self, other: &[A::Item]) -> Result<(), CapacityError> + where A::Item: Copy, + { + if self.remaining_capacity() < other.len() { + return Err(CapacityError::new(())); + } + + let self_len = self.len(); + let other_len = other.len(); + + unsafe { + let dst = self.xs.ptr_mut().add(self_len); + ptr::copy_nonoverlapping(other.as_ptr(), dst, other_len); + self.set_len(self_len + other_len); + } + Ok(()) + } + + /// Create a draining iterator that removes the specified range in the vector + /// and yields the removed items from start to end. The element range is + /// removed even if the iterator is not consumed until the end. + /// + /// Note: It is unspecified how many elements are removed from the vector, + /// if the `Drain` value is leaked. + /// + /// **Panics** if the starting point is greater than the end point or if + /// the end point is greater than the length of the vector. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// + /// let mut v = ArrayVec::from([1, 2, 3]); + /// let u: ArrayVec<[_; 3]> = v.drain(0..2).collect(); + /// assert_eq!(&v[..], &[3]); + /// assert_eq!(&u[..], &[1, 2]); + /// ``` + pub fn drain<R>(&mut self, range: R) -> Drain<A> + where R: RangeBounds<usize> + { + // Memory safety + // + // When the Drain is first created, it shortens the length of + // the source vector to make sure no uninitialized or moved-from elements + // are accessible at all if the Drain's destructor never gets to run. + // + // Drain will ptr::read out the values to remove. + // When finished, remaining tail of the vec is copied back to cover + // the hole, and the vector length is restored to the new length. + // + let len = self.len(); + let start = match range.start_bound() { + Bound::Unbounded => 0, + Bound::Included(&i) => i, + Bound::Excluded(&i) => i.saturating_add(1), + }; + let end = match range.end_bound() { + Bound::Excluded(&j) => j, + Bound::Included(&j) => j.saturating_add(1), + Bound::Unbounded => len, + }; + self.drain_range(start, end) + } + + fn drain_range(&mut self, start: usize, end: usize) -> Drain<A> + { + let len = self.len(); + + // bounds check happens here (before length is changed!) + let range_slice: *const _ = &self[start..end]; + + // Calling `set_len` creates a fresh and thus unique mutable references, making all + // older aliases we created invalid. So we cannot call that function. + self.len = Index::from(start); + + unsafe { + Drain { + tail_start: end, + tail_len: len - end, + iter: (*range_slice).iter(), + vec: self as *mut _, + } + } + } + + /// Return the inner fixed size array, if it is full to its capacity. + /// + /// Return an `Ok` value with the array if length equals capacity, + /// return an `Err` with self otherwise. + pub fn into_inner(self) -> Result<A, Self> { + if self.len() < self.capacity() { + Err(self) + } else { + unsafe { + let array = ptr::read(self.xs.ptr() as *const A); + mem::forget(self); + Ok(array) + } + } + } + + /// Dispose of `self` (same as drop) + #[deprecated="Use std::mem::drop instead, if at all needed."] + pub fn dispose(mut self) { + self.clear(); + mem::forget(self); + } + + /// Return a slice containing all elements of the vector. + pub fn as_slice(&self) -> &[A::Item] { + self + } + + /// Return a mutable slice containing all elements of the vector. + pub fn as_mut_slice(&mut self) -> &mut [A::Item] { + self + } + + /// Return a raw pointer to the vector's buffer. + pub fn as_ptr(&self) -> *const A::Item { + self.xs.ptr() + } + + /// Return a raw mutable pointer to the vector's buffer. + pub fn as_mut_ptr(&mut self) -> *mut A::Item { + self.xs.ptr_mut() + } +} + +impl<A: Array> Deref for ArrayVec<A> { + type Target = [A::Item]; + #[inline] + fn deref(&self) -> &[A::Item] { + unsafe { + slice::from_raw_parts(self.xs.ptr(), self.len()) + } + } +} + +impl<A: Array> DerefMut for ArrayVec<A> { + #[inline] + fn deref_mut(&mut self) -> &mut [A::Item] { + let len = self.len(); + unsafe { + slice::from_raw_parts_mut(self.xs.ptr_mut(), len) + } + } +} + +/// Create an `ArrayVec` from an array. +/// +/// ``` +/// use arrayvec::ArrayVec; +/// +/// let mut array = ArrayVec::from([1, 2, 3]); +/// assert_eq!(array.len(), 3); +/// assert_eq!(array.capacity(), 3); +/// ``` +impl<A: Array> From<A> for ArrayVec<A> { + fn from(array: A) -> Self { + ArrayVec { xs: MaybeUninit::from(array), len: Index::from(A::CAPACITY) } + } +} + + +/// Try to create an `ArrayVec` from a slice. This will return an error if the slice was too big to +/// fit. +/// +/// ``` +/// use arrayvec::ArrayVec; +/// use std::convert::TryInto as _; +/// +/// let array: ArrayVec<[_; 4]> = (&[1, 2, 3] as &[_]).try_into().unwrap(); +/// assert_eq!(array.len(), 3); +/// assert_eq!(array.capacity(), 4); +/// ``` +impl<A: Array> std::convert::TryFrom<&[A::Item]> for ArrayVec<A> + where + A::Item: Clone, +{ + type Error = CapacityError; + + fn try_from(slice: &[A::Item]) -> Result<Self, Self::Error> { + if A::CAPACITY < slice.len() { + Err(CapacityError::new(())) + } else { + let mut array = Self::new(); + array.extend(slice.iter().cloned()); + Ok(array) + } + } +} + + +/// Iterate the `ArrayVec` with references to each element. +/// +/// ``` +/// use arrayvec::ArrayVec; +/// +/// let array = ArrayVec::from([1, 2, 3]); +/// +/// for elt in &array { +/// // ... +/// } +/// ``` +impl<'a, A: Array> IntoIterator for &'a ArrayVec<A> { + type Item = &'a A::Item; + type IntoIter = slice::Iter<'a, A::Item>; + fn into_iter(self) -> Self::IntoIter { self.iter() } +} + +/// Iterate the `ArrayVec` with mutable references to each element. +/// +/// ``` +/// use arrayvec::ArrayVec; +/// +/// let mut array = ArrayVec::from([1, 2, 3]); +/// +/// for elt in &mut array { +/// // ... +/// } +/// ``` +impl<'a, A: Array> IntoIterator for &'a mut ArrayVec<A> { + type Item = &'a mut A::Item; + type IntoIter = slice::IterMut<'a, A::Item>; + fn into_iter(self) -> Self::IntoIter { self.iter_mut() } +} + +/// Iterate the `ArrayVec` with each element by value. +/// +/// The vector is consumed by this operation. +/// +/// ``` +/// use arrayvec::ArrayVec; +/// +/// for elt in ArrayVec::from([1, 2, 3]) { +/// // ... +/// } +/// ``` +impl<A: Array> IntoIterator for ArrayVec<A> { + type Item = A::Item; + type IntoIter = IntoIter<A>; + fn into_iter(self) -> IntoIter<A> { + IntoIter { index: Index::from(0), v: self, } + } +} + + +/// By-value iterator for `ArrayVec`. +pub struct IntoIter<A: Array> { + index: A::Index, + v: ArrayVec<A>, +} + +impl<A: Array> Iterator for IntoIter<A> { + type Item = A::Item; + + fn next(&mut self) -> Option<A::Item> { + if self.index == self.v.len { + None + } else { + unsafe { + let index = self.index.to_usize(); + self.index = Index::from(index + 1); + Some(ptr::read(self.v.get_unchecked_ptr(index))) + } + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + let len = self.v.len() - self.index.to_usize(); + (len, Some(len)) + } +} + +impl<A: Array> DoubleEndedIterator for IntoIter<A> { + fn next_back(&mut self) -> Option<A::Item> { + if self.index == self.v.len { + None + } else { + unsafe { + let new_len = self.v.len() - 1; + self.v.set_len(new_len); + Some(ptr::read(self.v.get_unchecked_ptr(new_len))) + } + } + } +} + +impl<A: Array> ExactSizeIterator for IntoIter<A> { } + +impl<A: Array> Drop for IntoIter<A> { + fn drop(&mut self) { + // panic safety: Set length to 0 before dropping elements. + let index = self.index.to_usize(); + let len = self.v.len(); + unsafe { + self.v.set_len(0); + let elements = slice::from_raw_parts_mut( + self.v.get_unchecked_ptr(index), + len - index); + ptr::drop_in_place(elements); + } + } +} + +impl<A: Array> Clone for IntoIter<A> +where + A::Item: Clone, +{ + fn clone(&self) -> IntoIter<A> { + self.v[self.index.to_usize()..] + .iter() + .cloned() + .collect::<ArrayVec<A>>() + .into_iter() + } +} + +impl<A: Array> fmt::Debug for IntoIter<A> +where + A::Item: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(&self.v[self.index.to_usize()..]) + .finish() + } +} + +/// A draining iterator for `ArrayVec`. +pub struct Drain<'a, A> + where A: Array, + A::Item: 'a, +{ + /// Index of tail to preserve + tail_start: usize, + /// Length of tail + tail_len: usize, + /// Current remaining range to remove + iter: slice::Iter<'a, A::Item>, + vec: *mut ArrayVec<A>, +} + +unsafe impl<'a, A: Array + Sync> Sync for Drain<'a, A> {} +unsafe impl<'a, A: Array + Send> Send for Drain<'a, A> {} + +impl<'a, A: Array> Iterator for Drain<'a, A> + where A::Item: 'a, +{ + type Item = A::Item; + + fn next(&mut self) -> Option<Self::Item> { + self.iter.next().map(|elt| + unsafe { + ptr::read(elt as *const _) + } + ) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + self.iter.size_hint() + } +} + +impl<'a, A: Array> DoubleEndedIterator for Drain<'a, A> + where A::Item: 'a, +{ + fn next_back(&mut self) -> Option<Self::Item> { + self.iter.next_back().map(|elt| + unsafe { + ptr::read(elt as *const _) + } + ) + } +} + +impl<'a, A: Array> ExactSizeIterator for Drain<'a, A> where A::Item: 'a {} + +impl<'a, A: Array> Drop for Drain<'a, A> + where A::Item: 'a +{ + fn drop(&mut self) { + // len is currently 0 so panicking while dropping will not cause a double drop. + + // exhaust self first + while let Some(_) = self.next() { } + + if self.tail_len > 0 { + unsafe { + let source_vec = &mut *self.vec; + // memmove back untouched tail, update to new length + let start = source_vec.len(); + let tail = self.tail_start; + let src = source_vec.as_ptr().add(tail); + let dst = source_vec.as_mut_ptr().add(start); + ptr::copy(src, dst, self.tail_len); + source_vec.set_len(start + self.tail_len); + } + } + } +} + +struct ScopeExitGuard<T, Data, F> + where F: FnMut(&Data, &mut T) +{ + value: T, + data: Data, + f: F, +} + +impl<T, Data, F> Drop for ScopeExitGuard<T, Data, F> + where F: FnMut(&Data, &mut T) +{ + fn drop(&mut self) { + (self.f)(&self.data, &mut self.value) + } +} + + + +/// Extend the `ArrayVec` with an iterator. +/// +/// Does not extract more items than there is space for. No error +/// occurs if there are more iterator elements. +impl<A: Array> Extend<A::Item> for ArrayVec<A> { + fn extend<T: IntoIterator<Item=A::Item>>(&mut self, iter: T) { + let take = self.capacity() - self.len(); + unsafe { + let len = self.len(); + let mut ptr = raw_ptr_add(self.as_mut_ptr(), len); + let end_ptr = raw_ptr_add(ptr, take); + // Keep the length in a separate variable, write it back on scope + // exit. To help the compiler with alias analysis and stuff. + // We update the length to handle panic in the iteration of the + // user's iterator, without dropping any elements on the floor. + let mut guard = ScopeExitGuard { + value: &mut self.len, + data: len, + f: move |&len, self_len| { + **self_len = Index::from(len); + } + }; + let mut iter = iter.into_iter(); + loop { + if ptr == end_ptr { break; } + if let Some(elt) = iter.next() { + raw_ptr_write(ptr, elt); + ptr = raw_ptr_add(ptr, 1); + guard.data += 1; + } else { + break; + } + } + } + } +} + +/// Rawptr add but uses arithmetic distance for ZST +unsafe fn raw_ptr_add<T>(ptr: *mut T, offset: usize) -> *mut T { + if mem::size_of::<T>() == 0 { + // Special case for ZST + (ptr as usize).wrapping_add(offset) as _ + } else { + ptr.add(offset) + } +} + +unsafe fn raw_ptr_write<T>(ptr: *mut T, value: T) { + if mem::size_of::<T>() == 0 { + /* nothing */ + } else { + ptr::write(ptr, value) + } +} + +/// Create an `ArrayVec` from an iterator. +/// +/// Does not extract more items than there is space for. No error +/// occurs if there are more iterator elements. +impl<A: Array> iter::FromIterator<A::Item> for ArrayVec<A> { + fn from_iter<T: IntoIterator<Item=A::Item>>(iter: T) -> Self { + let mut array = ArrayVec::new(); + array.extend(iter); + array + } +} + +impl<A: Array> Clone for ArrayVec<A> + where A::Item: Clone +{ + fn clone(&self) -> Self { + self.iter().cloned().collect() + } + + fn clone_from(&mut self, rhs: &Self) { + // recursive case for the common prefix + let prefix = cmp::min(self.len(), rhs.len()); + self[..prefix].clone_from_slice(&rhs[..prefix]); + + if prefix < self.len() { + // rhs was shorter + for _ in 0..self.len() - prefix { + self.pop(); + } + } else { + let rhs_elems = rhs[self.len()..].iter().cloned(); + self.extend(rhs_elems); + } + } +} + +impl<A: Array> Hash for ArrayVec<A> + where A::Item: Hash +{ + fn hash<H: Hasher>(&self, state: &mut H) { + Hash::hash(&**self, state) + } +} + +impl<A: Array> PartialEq for ArrayVec<A> + where A::Item: PartialEq +{ + fn eq(&self, other: &Self) -> bool { + **self == **other + } +} + +impl<A: Array> PartialEq<[A::Item]> for ArrayVec<A> + where A::Item: PartialEq +{ + fn eq(&self, other: &[A::Item]) -> bool { + **self == *other + } +} + +impl<A: Array> Eq for ArrayVec<A> where A::Item: Eq { } + +impl<A: Array> Borrow<[A::Item]> for ArrayVec<A> { + fn borrow(&self) -> &[A::Item] { self } +} + +impl<A: Array> BorrowMut<[A::Item]> for ArrayVec<A> { + fn borrow_mut(&mut self) -> &mut [A::Item] { self } +} + +impl<A: Array> AsRef<[A::Item]> for ArrayVec<A> { + fn as_ref(&self) -> &[A::Item] { self } +} + +impl<A: Array> AsMut<[A::Item]> for ArrayVec<A> { + fn as_mut(&mut self) -> &mut [A::Item] { self } +} + +impl<A: Array> fmt::Debug for ArrayVec<A> where A::Item: fmt::Debug { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } +} + +impl<A: Array> Default for ArrayVec<A> { + /// Return an empty array + fn default() -> ArrayVec<A> { + ArrayVec::new() + } +} + +impl<A: Array> PartialOrd for ArrayVec<A> where A::Item: PartialOrd { + fn partial_cmp(&self, other: &ArrayVec<A>) -> Option<cmp::Ordering> { + (**self).partial_cmp(other) + } + + fn lt(&self, other: &Self) -> bool { + (**self).lt(other) + } + + fn le(&self, other: &Self) -> bool { + (**self).le(other) + } + + fn ge(&self, other: &Self) -> bool { + (**self).ge(other) + } + + fn gt(&self, other: &Self) -> bool { + (**self).gt(other) + } +} + +impl<A: Array> Ord for ArrayVec<A> where A::Item: Ord { + fn cmp(&self, other: &ArrayVec<A>) -> cmp::Ordering { + (**self).cmp(other) + } +} + +#[cfg(feature="std")] +/// `Write` appends written data to the end of the vector. +/// +/// Requires `features="std"`. +impl<A: Array<Item=u8>> io::Write for ArrayVec<A> { + fn write(&mut self, data: &[u8]) -> io::Result<usize> { + let len = cmp::min(self.remaining_capacity(), data.len()); + let _result = self.try_extend_from_slice(&data[..len]); + debug_assert!(_result.is_ok()); + Ok(len) + } + fn flush(&mut self) -> io::Result<()> { Ok(()) } +} + +#[cfg(feature="serde")] +/// Requires crate feature `"serde"` +impl<T: Serialize, A: Array<Item=T>> Serialize for ArrayVec<A> { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where S: Serializer + { + serializer.collect_seq(self) + } +} + +#[cfg(feature="serde")] +/// Requires crate feature `"serde"` +impl<'de, T: Deserialize<'de>, A: Array<Item=T>> Deserialize<'de> for ArrayVec<A> { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where D: Deserializer<'de> + { + use serde::de::{Visitor, SeqAccess, Error}; + use std::marker::PhantomData; + + struct ArrayVecVisitor<'de, T: Deserialize<'de>, A: Array<Item=T>>(PhantomData<(&'de (), T, A)>); + + impl<'de, T: Deserialize<'de>, A: Array<Item=T>> Visitor<'de> for ArrayVecVisitor<'de, T, A> { + type Value = ArrayVec<A>; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "an array with no more than {} items", A::CAPACITY) + } + + fn visit_seq<SA>(self, mut seq: SA) -> Result<Self::Value, SA::Error> + where SA: SeqAccess<'de>, + { + let mut values = ArrayVec::<A>::new(); + + while let Some(value) = seq.next_element()? { + if let Err(_) = values.try_push(value) { + return Err(SA::Error::invalid_length(A::CAPACITY + 1, &self)); + } + } + + Ok(values) + } + } + + deserializer.deserialize_seq(ArrayVecVisitor::<T, A>(PhantomData)) + } +} diff --git a/vendor/arrayvec/src/maybe_uninit.rs b/vendor/arrayvec/src/maybe_uninit.rs new file mode 100644 index 0000000..e009abf --- /dev/null +++ b/vendor/arrayvec/src/maybe_uninit.rs @@ -0,0 +1,44 @@ + + +use crate::array::Array; +use std::mem::MaybeUninit as StdMaybeUninit; + +#[derive(Copy)] +pub struct MaybeUninit<T> { + inner: StdMaybeUninit<T>, +} + +impl<T> Clone for MaybeUninit<T> + where T: Copy +{ + fn clone(&self) -> Self { *self } +} + +impl<T> MaybeUninit<T> { + /// Create a new MaybeUninit with uninitialized interior + pub const unsafe fn uninitialized() -> Self { + MaybeUninit { inner: StdMaybeUninit::uninit() } + } + + /// Create a new MaybeUninit from the value `v`. + pub fn from(v: T) -> Self { + MaybeUninit { inner: StdMaybeUninit::new(v) } + } + + // Raw pointer casts written so that we don't reference or access the + // uninitialized interior value + + /// Return a raw pointer to the start of the interior array + pub fn ptr(&self) -> *const T::Item + where T: Array + { + self.inner.as_ptr() as *const T::Item + } + + /// Return a mut raw pointer to the start of the interior array + pub fn ptr_mut(&mut self) -> *mut T::Item + where T: Array + { + self.inner.as_mut_ptr() as *mut T::Item + } +} diff --git a/vendor/arrayvec/tests/serde.rs b/vendor/arrayvec/tests/serde.rs new file mode 100644 index 0000000..3876d2a --- /dev/null +++ b/vendor/arrayvec/tests/serde.rs @@ -0,0 +1,79 @@ +#![cfg(feature = "serde")] +extern crate arrayvec; +extern crate serde_test; + +mod array_vec { + use arrayvec::ArrayVec; + + use serde_test::{Token, assert_tokens, assert_de_tokens_error}; + + #[test] + fn test_ser_de_empty() { + let vec = ArrayVec::<[u32; 0]>::new(); + + assert_tokens(&vec, &[ + Token::Seq { len: Some(0) }, + Token::SeqEnd, + ]); + } + + + #[test] + fn test_ser_de() { + let mut vec = ArrayVec::<[u32; 3]>::new(); + vec.push(20); + vec.push(55); + vec.push(123); + + assert_tokens(&vec, &[ + Token::Seq { len: Some(3) }, + Token::U32(20), + Token::U32(55), + Token::U32(123), + Token::SeqEnd, + ]); + } + + #[test] + fn test_de_too_large() { + assert_de_tokens_error::<ArrayVec<[u32; 2]>>(&[ + Token::Seq { len: Some(3) }, + Token::U32(13), + Token::U32(42), + Token::U32(68), + ], "invalid length 3, expected an array with no more than 2 items"); + } +} + +mod array_string { + use arrayvec::ArrayString; + + use serde_test::{Token, assert_tokens, assert_de_tokens_error}; + + #[test] + fn test_ser_de_empty() { + let string = ArrayString::<[u8; 0]>::new(); + + assert_tokens(&string, &[ + Token::Str(""), + ]); + } + + + #[test] + fn test_ser_de() { + let string = ArrayString::<[u8; 9]>::from("1234 abcd") + .expect("expected exact specified capacity to be enough"); + + assert_tokens(&string, &[ + Token::Str("1234 abcd"), + ]); + } + + #[test] + fn test_de_too_large() { + assert_de_tokens_error::<ArrayString<[u8; 2]>>(&[ + Token::Str("afd") + ], "invalid length 3, expected a string no more than 2 bytes long"); + } +} diff --git a/vendor/arrayvec/tests/tests.rs b/vendor/arrayvec/tests/tests.rs new file mode 100644 index 0000000..c7ebcd0 --- /dev/null +++ b/vendor/arrayvec/tests/tests.rs @@ -0,0 +1,688 @@ +extern crate arrayvec; +#[macro_use] extern crate matches; + +use arrayvec::ArrayVec; +use arrayvec::ArrayString; +use std::mem; +use arrayvec::CapacityError; + +use std::collections::HashMap; + + +#[test] +fn test_simple() { + use std::ops::Add; + + let mut vec: ArrayVec<[Vec<i32>; 3]> = ArrayVec::new(); + + vec.push(vec![1, 2, 3, 4]); + vec.push(vec![10]); + vec.push(vec![-1, 13, -2]); + + for elt in &vec { + assert_eq!(elt.iter().fold(0, Add::add), 10); + } + + let sum_len = vec.into_iter().map(|x| x.len()).fold(0, Add::add); + assert_eq!(sum_len, 8); +} + +#[test] +fn test_capacity_left() { + let mut vec: ArrayVec<[usize; 4]> = ArrayVec::new(); + assert_eq!(vec.remaining_capacity(), 4); + vec.push(1); + assert_eq!(vec.remaining_capacity(), 3); + vec.push(2); + assert_eq!(vec.remaining_capacity(), 2); + vec.push(3); + assert_eq!(vec.remaining_capacity(), 1); + vec.push(4); + assert_eq!(vec.remaining_capacity(), 0); +} + +#[test] +fn test_extend_from_slice() { + let mut vec: ArrayVec<[usize; 10]> = ArrayVec::new(); + + vec.try_extend_from_slice(&[1, 2, 3]).unwrap(); + assert_eq!(vec.len(), 3); + assert_eq!(&vec[..], &[1, 2, 3]); + assert_eq!(vec.pop(), Some(3)); + assert_eq!(&vec[..], &[1, 2]); +} + +#[test] +fn test_extend_from_slice_error() { + let mut vec: ArrayVec<[usize; 10]> = ArrayVec::new(); + + vec.try_extend_from_slice(&[1, 2, 3]).unwrap(); + let res = vec.try_extend_from_slice(&[0; 8]); + assert_matches!(res, Err(_)); + + let mut vec: ArrayVec<[usize; 0]> = ArrayVec::new(); + let res = vec.try_extend_from_slice(&[0; 1]); + assert_matches!(res, Err(_)); +} + +#[test] +fn test_try_from_slice_error() { + use arrayvec::ArrayVec; + use std::convert::TryInto as _; + + let res: Result<ArrayVec<[_; 2]>, _> = (&[1, 2, 3] as &[_]).try_into(); + assert_matches!(res, Err(_)); +} + +#[test] +fn test_u16_index() { + const N: usize = 4096; + let mut vec: ArrayVec<[_; N]> = ArrayVec::new(); + for _ in 0..N { + assert!(vec.try_push(1u8).is_ok()); + } + assert!(vec.try_push(0).is_err()); + assert_eq!(vec.len(), N); +} + +#[test] +fn test_iter() { + let mut iter = ArrayVec::from([1, 2, 3]).into_iter(); + assert_eq!(iter.size_hint(), (3, Some(3))); + assert_eq!(iter.next_back(), Some(3)); + assert_eq!(iter.next(), Some(1)); + assert_eq!(iter.next_back(), Some(2)); + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next_back(), None); +} + +#[test] +fn test_drop() { + use std::cell::Cell; + + let flag = &Cell::new(0); + + #[derive(Clone)] + struct Bump<'a>(&'a Cell<i32>); + + impl<'a> Drop for Bump<'a> { + fn drop(&mut self) { + let n = self.0.get(); + self.0.set(n + 1); + } + } + + { + let mut array = ArrayVec::<[Bump; 128]>::new(); + array.push(Bump(flag)); + array.push(Bump(flag)); + } + assert_eq!(flag.get(), 2); + + // test something with the nullable pointer optimization + flag.set(0); + + { + let mut array = ArrayVec::<[_; 3]>::new(); + array.push(vec![Bump(flag)]); + array.push(vec![Bump(flag), Bump(flag)]); + array.push(vec![]); + let push4 = array.try_push(vec![Bump(flag)]); + assert_eq!(flag.get(), 0); + drop(push4); + assert_eq!(flag.get(), 1); + drop(array.pop()); + assert_eq!(flag.get(), 1); + drop(array.pop()); + assert_eq!(flag.get(), 3); + } + + assert_eq!(flag.get(), 4); + + // test into_inner + flag.set(0); + { + let mut array = ArrayVec::<[_; 3]>::new(); + array.push(Bump(flag)); + array.push(Bump(flag)); + array.push(Bump(flag)); + let inner = array.into_inner(); + assert!(inner.is_ok()); + assert_eq!(flag.get(), 0); + drop(inner); + assert_eq!(flag.get(), 3); + } + + // test cloning into_iter + flag.set(0); + { + let mut array = ArrayVec::<[_; 3]>::new(); + array.push(Bump(flag)); + array.push(Bump(flag)); + array.push(Bump(flag)); + let mut iter = array.into_iter(); + assert_eq!(flag.get(), 0); + iter.next(); + assert_eq!(flag.get(), 1); + let clone = iter.clone(); + assert_eq!(flag.get(), 1); + drop(clone); + assert_eq!(flag.get(), 3); + drop(iter); + assert_eq!(flag.get(), 5); + } +} + +#[test] +fn test_drop_panics() { + use std::cell::Cell; + use std::panic::catch_unwind; + use std::panic::AssertUnwindSafe; + + let flag = &Cell::new(0); + + struct Bump<'a>(&'a Cell<i32>); + + // Panic in the first drop + impl<'a> Drop for Bump<'a> { + fn drop(&mut self) { + let n = self.0.get(); + self.0.set(n + 1); + if n == 0 { + panic!("Panic in Bump's drop"); + } + } + } + // check if rust is new enough + flag.set(0); + { + let array = vec![Bump(flag), Bump(flag)]; + let res = catch_unwind(AssertUnwindSafe(|| { + drop(array); + })); + assert!(res.is_err()); + } + + if flag.get() != 2 { + println!("test_drop_panics: skip, this version of Rust doesn't continue in drop_in_place"); + return; + } + + flag.set(0); + { + let mut array = ArrayVec::<[Bump; 128]>::new(); + array.push(Bump(flag)); + array.push(Bump(flag)); + array.push(Bump(flag)); + + let res = catch_unwind(AssertUnwindSafe(|| { + drop(array); + })); + assert!(res.is_err()); + } + // Check that all the elements drop, even if the first drop panics. + assert_eq!(flag.get(), 3); + + + flag.set(0); + { + let mut array = ArrayVec::<[Bump; 16]>::new(); + array.push(Bump(flag)); + array.push(Bump(flag)); + array.push(Bump(flag)); + array.push(Bump(flag)); + array.push(Bump(flag)); + + let i = 2; + let tail_len = array.len() - i; + + let res = catch_unwind(AssertUnwindSafe(|| { + array.truncate(i); + })); + assert!(res.is_err()); + // Check that all the tail elements drop, even if the first drop panics. + assert_eq!(flag.get(), tail_len as i32); + } + + +} + +#[test] +fn test_extend() { + let mut range = 0..10; + + let mut array: ArrayVec<[_; 5]> = range.by_ref().collect(); + assert_eq!(&array[..], &[0, 1, 2, 3, 4]); + assert_eq!(range.next(), Some(5)); + + array.extend(range.by_ref()); + assert_eq!(range.next(), Some(6)); + + let mut array: ArrayVec<[_; 10]> = (0..3).collect(); + assert_eq!(&array[..], &[0, 1, 2]); + array.extend(3..5); + assert_eq!(&array[..], &[0, 1, 2, 3, 4]); +} + +#[test] +fn test_is_send_sync() { + let data = ArrayVec::<[Vec<i32>; 5]>::new(); + &data as &dyn Send; + &data as &dyn Sync; +} + +#[test] +fn test_compact_size() { + // Future rust will kill these drop flags! + // 4 elements size + 1 len + 1 enum tag + [1 drop flag] + type ByteArray = ArrayVec<[u8; 4]>; + println!("{}", mem::size_of::<ByteArray>()); + assert!(mem::size_of::<ByteArray>() <= 8); + + // 1 enum tag + 1 drop flag + type EmptyArray = ArrayVec<[u8; 0]>; + println!("{}", mem::size_of::<EmptyArray>()); + assert!(mem::size_of::<EmptyArray>() <= 2); + + // 12 element size + 1 enum tag + 3 padding + 1 len + 1 drop flag + 2 padding + type QuadArray = ArrayVec<[u32; 3]>; + println!("{}", mem::size_of::<QuadArray>()); + assert!(mem::size_of::<QuadArray>() <= 24); +} + +#[test] +fn test_still_works_with_option_arrayvec() { + type RefArray = ArrayVec<[&'static i32; 2]>; + let array = Some(RefArray::new()); + assert!(array.is_some()); + println!("{:?}", array); +} + +#[test] +fn test_drain() { + let mut v = ArrayVec::from([0; 8]); + v.pop(); + v.drain(0..7); + assert_eq!(&v[..], &[]); + + v.extend(0..); + v.drain(1..4); + assert_eq!(&v[..], &[0, 4, 5, 6, 7]); + let u: ArrayVec<[_; 3]> = v.drain(1..4).rev().collect(); + assert_eq!(&u[..], &[6, 5, 4]); + assert_eq!(&v[..], &[0, 7]); + v.drain(..); + assert_eq!(&v[..], &[]); +} + +#[test] +fn test_drain_range_inclusive() { + let mut v = ArrayVec::from([0; 8]); + v.drain(0..=7); + assert_eq!(&v[..], &[]); + + v.extend(0..); + v.drain(1..=4); + assert_eq!(&v[..], &[0, 5, 6, 7]); + let u: ArrayVec<[_; 3]> = v.drain(1..=2).rev().collect(); + assert_eq!(&u[..], &[6, 5]); + assert_eq!(&v[..], &[0, 7]); + v.drain(..); + assert_eq!(&v[..], &[]); +} + +#[test] +#[should_panic] +fn test_drain_range_inclusive_oob() { + let mut v = ArrayVec::from([0; 0]); + v.drain(0..=0); +} + +#[test] +fn test_retain() { + let mut v = ArrayVec::from([0; 8]); + for (i, elt) in v.iter_mut().enumerate() { + *elt = i; + } + v.retain(|_| true); + assert_eq!(&v[..], &[0, 1, 2, 3, 4, 5, 6, 7]); + v.retain(|elt| { + *elt /= 2; + *elt % 2 == 0 + }); + assert_eq!(&v[..], &[0, 0, 2, 2]); + v.retain(|_| false); + assert_eq!(&v[..], &[]); +} + +#[test] +#[should_panic] +fn test_drain_oob() { + let mut v = ArrayVec::from([0; 8]); + v.pop(); + v.drain(0..8); +} + +#[test] +#[should_panic] +fn test_drop_panic() { + struct DropPanic; + + impl Drop for DropPanic { + fn drop(&mut self) { + panic!("drop"); + } + } + + let mut array = ArrayVec::<[DropPanic; 1]>::new(); + array.push(DropPanic); +} + +#[test] +#[should_panic] +fn test_drop_panic_into_iter() { + struct DropPanic; + + impl Drop for DropPanic { + fn drop(&mut self) { + panic!("drop"); + } + } + + let mut array = ArrayVec::<[DropPanic; 1]>::new(); + array.push(DropPanic); + array.into_iter(); +} + +#[test] +fn test_insert() { + let mut v = ArrayVec::from([]); + assert_matches!(v.try_push(1), Err(_)); + + let mut v = ArrayVec::<[_; 3]>::new(); + v.insert(0, 0); + v.insert(1, 1); + //let ret1 = v.try_insert(3, 3); + //assert_matches!(ret1, Err(InsertError::OutOfBounds(_))); + assert_eq!(&v[..], &[0, 1]); + v.insert(2, 2); + assert_eq!(&v[..], &[0, 1, 2]); + + let ret2 = v.try_insert(1, 9); + assert_eq!(&v[..], &[0, 1, 2]); + assert_matches!(ret2, Err(_)); + + let mut v = ArrayVec::from([2]); + assert_matches!(v.try_insert(0, 1), Err(CapacityError { .. })); + assert_matches!(v.try_insert(1, 1), Err(CapacityError { .. })); + //assert_matches!(v.try_insert(2, 1), Err(CapacityError { .. })); +} + +#[test] +fn test_into_inner_1() { + let mut v = ArrayVec::from([1, 2]); + v.pop(); + let u = v.clone(); + assert_eq!(v.into_inner(), Err(u)); +} + +#[test] +fn test_into_inner_2() { + let mut v = ArrayVec::<[String; 4]>::new(); + v.push("a".into()); + v.push("b".into()); + v.push("c".into()); + v.push("d".into()); + assert_eq!(v.into_inner().unwrap(), ["a", "b", "c", "d"]); +} + +#[test] +fn test_into_inner_3_() { + let mut v = ArrayVec::<[i32; 4]>::new(); + v.extend(1..); + assert_eq!(v.into_inner().unwrap(), [1, 2, 3, 4]); +} + +#[cfg(feature="std")] +#[test] +fn test_write() { + use std::io::Write; + let mut v = ArrayVec::<[_; 8]>::new(); + write!(&mut v, "\x01\x02\x03").unwrap(); + assert_eq!(&v[..], &[1, 2, 3]); + let r = v.write(&[9; 16]).unwrap(); + assert_eq!(r, 5); + assert_eq!(&v[..], &[1, 2, 3, 9, 9, 9, 9, 9]); +} + +#[test] +fn array_clone_from() { + let mut v = ArrayVec::<[_; 4]>::new(); + v.push(vec![1, 2]); + v.push(vec![3, 4, 5]); + v.push(vec![6]); + let reference = v.to_vec(); + let mut u = ArrayVec::<[_; 4]>::new(); + u.clone_from(&v); + assert_eq!(&u, &reference[..]); + + let mut t = ArrayVec::<[_; 4]>::new(); + t.push(vec![97]); + t.push(vec![]); + t.push(vec![5, 6, 2]); + t.push(vec![2]); + t.clone_from(&v); + assert_eq!(&t, &reference[..]); + t.clear(); + t.clone_from(&v); + assert_eq!(&t, &reference[..]); +} + +#[cfg(feature="std")] +#[test] +fn test_string() { + use std::error::Error; + + let text = "hello world"; + let mut s = ArrayString::<[_; 16]>::new(); + s.try_push_str(text).unwrap(); + assert_eq!(&s, text); + assert_eq!(text, &s); + + // Make sure Hash / Eq / Borrow match up so we can use HashMap + let mut map = HashMap::new(); + map.insert(s, 1); + assert_eq!(map[text], 1); + + let mut t = ArrayString::<[_; 2]>::new(); + assert!(t.try_push_str(text).is_err()); + assert_eq!(&t, ""); + + t.push_str("ab"); + // DerefMut + let tmut: &mut str = &mut t; + assert_eq!(tmut, "ab"); + + // Test Error trait / try + let t = || -> Result<(), Box<dyn Error>> { + let mut t = ArrayString::<[_; 2]>::new(); + t.try_push_str(text)?; + Ok(()) + }(); + assert!(t.is_err()); +} + +#[test] +fn test_string_from() { + let text = "hello world"; + // Test `from` constructor + let u = ArrayString::<[_; 11]>::from(text).unwrap(); + assert_eq!(&u, text); + assert_eq!(u.len(), text.len()); +} + +#[test] +fn test_string_parse_from_str() { + let text = "hello world"; + let u: ArrayString<[_; 11]> = text.parse().unwrap(); + assert_eq!(&u, text); + assert_eq!(u.len(), text.len()); +} + +#[test] +fn test_string_from_bytes() { + let text = "hello world"; + let u = ArrayString::from_byte_string(b"hello world").unwrap(); + assert_eq!(&u, text); + assert_eq!(u.len(), text.len()); +} + +#[test] +fn test_string_clone() { + let text = "hi"; + let mut s = ArrayString::<[_; 4]>::new(); + s.push_str("abcd"); + let t = ArrayString::<[_; 4]>::from(text).unwrap(); + s.clone_from(&t); + assert_eq!(&t, &s); +} + +#[test] +fn test_string_push() { + let text = "abcαβγ"; + let mut s = ArrayString::<[_; 8]>::new(); + for c in text.chars() { + if let Err(_) = s.try_push(c) { + break; + } + } + assert_eq!("abcαβ", &s[..]); + s.push('x'); + assert_eq!("abcαβx", &s[..]); + assert!(s.try_push('x').is_err()); +} + + +#[test] +fn test_insert_at_length() { + let mut v = ArrayVec::<[_; 8]>::new(); + let result1 = v.try_insert(0, "a"); + let result2 = v.try_insert(1, "b"); + assert!(result1.is_ok() && result2.is_ok()); + assert_eq!(&v[..], &["a", "b"]); +} + +#[should_panic] +#[test] +fn test_insert_out_of_bounds() { + let mut v = ArrayVec::<[_; 8]>::new(); + let _ = v.try_insert(1, "test"); +} + +/* + * insert that pushes out the last + let mut u = ArrayVec::from([1, 2, 3, 4]); + let ret = u.try_insert(3, 99); + assert_eq!(&u[..], &[1, 2, 3, 99]); + assert_matches!(ret, Err(_)); + let ret = u.try_insert(4, 77); + assert_eq!(&u[..], &[1, 2, 3, 99]); + assert_matches!(ret, Err(_)); +*/ + +#[test] +fn test_drop_in_insert() { + use std::cell::Cell; + + let flag = &Cell::new(0); + + struct Bump<'a>(&'a Cell<i32>); + + impl<'a> Drop for Bump<'a> { + fn drop(&mut self) { + let n = self.0.get(); + self.0.set(n + 1); + } + } + + flag.set(0); + + { + let mut array = ArrayVec::<[_; 2]>::new(); + array.push(Bump(flag)); + array.insert(0, Bump(flag)); + assert_eq!(flag.get(), 0); + let ret = array.try_insert(1, Bump(flag)); + assert_eq!(flag.get(), 0); + assert_matches!(ret, Err(_)); + drop(ret); + assert_eq!(flag.get(), 1); + } + assert_eq!(flag.get(), 3); +} + +#[test] +fn test_pop_at() { + let mut v = ArrayVec::<[String; 4]>::new(); + let s = String::from; + v.push(s("a")); + v.push(s("b")); + v.push(s("c")); + v.push(s("d")); + + assert_eq!(v.pop_at(4), None); + assert_eq!(v.pop_at(1), Some(s("b"))); + assert_eq!(v.pop_at(1), Some(s("c"))); + assert_eq!(v.pop_at(2), None); + assert_eq!(&v[..], &["a", "d"]); +} + +#[test] +fn test_sizes() { + let v = ArrayVec::from([0u8; 1 << 16]); + assert_eq!(vec![0u8; v.len()], &v[..]); +} + +#[test] +fn test_default() { + use std::net; + let s: ArrayString<[u8; 4]> = Default::default(); + // Something without `Default` implementation. + let v: ArrayVec<[net::TcpStream; 4]> = Default::default(); + assert_eq!(s.len(), 0); + assert_eq!(v.len(), 0); +} + +#[cfg(feature="array-sizes-33-128")] +#[test] +fn test_sizes_33_128() { + ArrayVec::from([0u8; 52]); + ArrayVec::from([0u8; 127]); +} + +#[cfg(feature="array-sizes-129-255")] +#[test] +fn test_sizes_129_255() { + ArrayVec::from([0u8; 237]); + ArrayVec::from([0u8; 255]); +} + +#[test] +fn test_extend_zst() { + let mut range = 0..10; + #[derive(Copy, Clone, PartialEq, Debug)] + struct Z; // Zero sized type + + let mut array: ArrayVec<[_; 5]> = range.by_ref().map(|_| Z).collect(); + assert_eq!(&array[..], &[Z; 5]); + assert_eq!(range.next(), Some(5)); + + array.extend(range.by_ref().map(|_| Z)); + assert_eq!(range.next(), Some(6)); + + let mut array: ArrayVec<[_; 10]> = (0..3).map(|_| Z).collect(); + assert_eq!(&array[..], &[Z; 3]); + array.extend((3..5).map(|_| Z)); + assert_eq!(&array[..], &[Z; 5]); + assert_eq!(array.len(), 5); +} |