arrayvec-0.7.4/.cargo_vcs_info.json0000644000000001360000000000100126600ustar { "git": { "sha1": "2c92a59bed0d1669cede3806000d2e61d5994c4e" }, "path_in_vcs": "" }arrayvec-0.7.4/.github/workflows/ci.yml000064400000000000000000000031131046102023000161610ustar 00000000000000on: push: branches: [ master ] pull_request: branches: [ master ] name: Continuous integration env: CARGO_TERM_COLOR: always CARGO_INCREMENTAL: 0 jobs: tests: runs-on: ubuntu-latest continue-on-error: ${{ matrix.experimental }} strategy: matrix: include: - rust: 1.51.0 # MSRV features: serde experimental: false - rust: stable features: bench: true experimental: false - rust: beta features: serde experimental: false - rust: nightly features: serde, zeroize experimental: false steps: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: ${{ matrix.rust }} override: true - name: Tests run: | cargo build --verbose --features "${{ matrix.features }}" cargo doc --verbose --features "${{ matrix.features }}" --no-deps cargo test --verbose --features "${{ matrix.features }}" cargo test --release --verbose --features "${{ matrix.features }}" - name: Test run benchmarks if: matrix.bench != '' run: cargo test -v --benches miri: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Install Miri run: | rustup toolchain install nightly --component miri rustup override set nightly cargo miri setup - name: Test with Miri run: cargo miri test --all-features arrayvec-0.7.4/.gitignore000064400000000000000000000001461046102023000134410ustar 00000000000000# Compiled files *.o *.so *.rlib *.dll # Executables *.exe # Generated by Cargo /Cargo.lock /target arrayvec-0.7.4/CHANGELOG.md000064400000000000000000000233471046102023000132720ustar 00000000000000Recent Changes (arrayvec) ========================= ## 0.7.4 - Add feature zeroize to support the `Zeroize` trait by @elichai ## 0.7.3 - Use track_caller on multiple methods like push and similar, for capacity overflows by @kornelski - impl BorrowMut for ArrayString by @msrd0 - Fix stacked borrows violations by @clubby789 - Update Miri CI by @RalfJung ## 0.7.2 - Add `.as_mut_str()` to `ArrayString` by @clarfonthey - Add `remaining_capacity` to `ArrayString` by @bhgomes - Add `zero_filled` constructor by @c410-f3r - Optimize `retain` by @TennyZhuang and @niklasf - Make the following methods `const` by @bhgomes: - len - is_empty - capacity - is_full - remaining_capacity - CapacityError::new ## 0.7.1 - Add new ArrayVec methods `.take()` and `.into_inner_unchecked()` by @conradludgate - `clone_from` now uses `truncate` when needed by @a1phyr ## 0.7.0 - `fn new_const` is now the way to const-construct arrayvec and arraystring, and `fn new` has been reverted to a regular "non-const" function. This works around performance issue #182, where the const fn version did not optimize well. Change by @bluss with thanks to @rodrimati1992 and @niklasf for analyzing the problem. - The deprecated feature flag `unstable-const-fn` was removed, since it's not needed - Optimize `.retain()` by using the same algorithm as in std, change by @niklasf, issue #174. Original optimization in Rust std by @oxalica in rust-lang/rust/pull/81126 ## 0.6.1 - The ``ArrayVec::new`` and ``ArrayString::new`` constructors are properly const fns on stable and the feature flag ``unstable-const-fn`` is now deprecated. by @rodrimati1992 - Small fix to the capacity check macro by @Xaeroxe - Typo fix in documentation by @cuviper - Small code cleanup by @bluss ## 0.6.0 - The **const generics** release šŸŽ‰. Arrayvec finally implements what it wanted to implement, since its first version: a vector backed by an array, with generic parameters for the arbitrary element type *and* backing array capacity. The New type syntax is `ArrayVec` where `CAP` is the arrayvec capacity. For arraystring the syntax is `ArrayString`. Length is stored internally as u32; this limits the maximum capacity. The size of the `ArrayVec` or `ArrayString` structs for the same capacity may grow slightly compared with the previous version (depending on padding requirements for the element type). Change by @bluss. - Arrayvec's `.extend()` and `FromIterator`/`.collect()` to arrayvec now **panic** if the capacity of the arrayvec is exceeded. Change by @bluss. - Arraystring now implements `TryFrom<&str>` and `TryFrom` by @c410-f3r - Minimum supported rust version is Rust 1.51 ## 0.5.2 - Add `is_empty` methods for ArrayVec and ArrayString by @nicbn - Implement `TryFrom` 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. ## Older releases - 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` - `.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` 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() arrayvec-0.7.4/Cargo.toml0000644000000031540000000000100106610ustar # 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 are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "arrayvec" version = "0.7.4" 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/" readme = "README.md" keywords = [ "stack", "vector", "array", "data-structure", "no_std", ] categories = [ "data-structures", "no-std", ] license = "MIT OR Apache-2.0" repository = "https://github.com/bluss/arrayvec" [package.metadata.docs.rs] features = [ "serde", "zeroize", ] [package.metadata.release] no-dev-version = true tag-name = "{{version}}" [profile.bench] debug = 2 [profile.release] debug = 2 [[bench]] name = "extend" harness = false [[bench]] name = "arraystring" harness = false [dependencies.serde] version = "1.0" optional = true default-features = false [dependencies.zeroize] version = "1.4" 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] default = ["std"] std = [] arrayvec-0.7.4/Cargo.toml.orig000064400000000000000000000021101046102023000143310ustar 00000000000000[package] name = "arrayvec" version = "0.7.4" authors = ["bluss"] license = "MIT OR Apache-2.0" edition = "2018" 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/" repository = "https://github.com/bluss/arrayvec" keywords = ["stack", "vector", "array", "data-structure", "no_std"] categories = ["data-structures", "no-std"] [build-dependencies] [dependencies.serde] version = "1.0" optional = true default-features = false [dependencies.zeroize] version = "1.4" optional = true default-features = false [dev-dependencies.serde_test] version = "1.0" [dev-dependencies] matches = { version = "0.1" } bencher = "0.1.4" [[bench]] name = "extend" harness = false [[bench]] name = "arraystring" harness = false [features] default = ["std"] std = [] [profile.bench] debug = true [profile.release] debug = true [package.metadata.docs.rs] features = ["serde", "zeroize"] [package.metadata.release] no-dev-version = true tag-name = "{{version}}" arrayvec-0.7.4/LICENSE-APACHE000064400000000000000000000251371046102023000134040ustar 00000000000000 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. arrayvec-0.7.4/LICENSE-MIT000064400000000000000000000020571046102023000131100ustar 00000000000000Copyright (c) Ulrik Sverdrup "bluss" 2015-2023 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. arrayvec-0.7.4/README.md000064400000000000000000000016761046102023000127410ustar 00000000000000 arrayvec ======== [![Crates.io: arrayvec](https://img.shields.io/crates/v/arrayvec.svg)](https://crates.io/crates/arrayvec) [![Documentation](https://docs.rs/arrayvec/badge.svg)](https://docs.rs/arrayvec) [![Build Status](https://github.com/bluss/arrayvec/workflows/Continuous%20integration/badge.svg?branch=master)](https://github.com/bluss/arrayvec/actions) [![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. arrayvec-0.7.4/benches/arraystring.rs000064400000000000000000000036531046102023000160010ustar 00000000000000 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::<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::<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::<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::<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::<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::<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); arrayvec-0.7.4/benches/extend.rs000064400000000000000000000033131046102023000147140ustar 00000000000000 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::::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::::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::::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::::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::::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); arrayvec-0.7.4/src/array_string.rs000064400000000000000000000462341046102023000153220ustar 00000000000000use std::borrow::{Borrow, BorrowMut}; use std::cmp; use std::convert::TryFrom; use std::fmt; use std::hash::{Hash, Hasher}; use std::mem::MaybeUninit; use std::ops::{Deref, DerefMut}; use std::ptr; use std::slice; use std::str; use std::str::FromStr; use std::str::Utf8Error; use crate::CapacityError; use crate::LenUint; use crate::char::encode_utf8; use crate::utils::MakeMaybeUninit; #[cfg(feature="serde")] use serde::{Serialize, Deserialize, Serializer, Deserializer}; /// A string with a fixed capacity. /// /// The `ArrayString` is a string backed by a fixed size array. It keeps track /// of its length, and is parameterized by `CAP` for the maximum capacity. /// /// `CAP` is of type `usize` but is range limited to `u32::MAX`; attempting to create larger /// arrayvecs with larger capacity will panic. /// /// The string is a contiguous value that you can store directly on the stack /// if needed. #[derive(Copy)] pub struct ArrayString { // the `len` first elements of the array are initialized xs: [MaybeUninit; CAP], len: LenUint, } impl Default for ArrayString { /// Return an empty `ArrayString` fn default() -> ArrayString { ArrayString::new() } } impl ArrayString { /// 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); /// ``` pub fn new() -> ArrayString { assert_capacity_limit!(CAP); unsafe { ArrayString { xs: MaybeUninit::uninit().assume_init(), len: 0 } } } /// Create a new empty `ArrayString` (const fn). /// /// Capacity is inferred from the type parameter. /// /// ``` /// use arrayvec::ArrayString; /// /// static ARRAY: ArrayString<1024> = ArrayString::new_const(); /// ``` pub const fn new_const() -> ArrayString { assert_capacity_limit_const!(CAP); ArrayString { xs: MakeMaybeUninit::ARRAY, len: 0 } } /// Return the length of the string. #[inline] pub const fn len(&self) -> usize { self.len as usize } /// Returns whether the string is empty. #[inline] pub const 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> { 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: &[u8; CAP]) -> Result { let len = str::from_utf8(b)?.len(); debug_assert_eq!(len, CAP); let mut vec = Self::new(); unsafe { (b as *const [u8; CAP] as *const [MaybeUninit; CAP]) .copy_to_nonoverlapping(&mut vec.xs as *mut [MaybeUninit; CAP], 1); vec.set_len(CAP); } Ok(vec) } /// Create a new `ArrayString` value fully filled with ASCII NULL characters (`\0`). Useful /// to be used as a buffer to collect external data or as a buffer for intermediate processing. /// /// ``` /// use arrayvec::ArrayString; /// /// let string = ArrayString::<16>::zero_filled(); /// assert_eq!(string.len(), 16); /// ``` #[inline] pub fn zero_filled() -> Self { assert_capacity_limit!(CAP); // SAFETY: `assert_capacity_limit` asserts that `len` won't overflow and // `zeroed` fully fills the array with nulls. unsafe { ArrayString { xs: MaybeUninit::zeroed().assume_init(), len: CAP as _ } } } /// Return the capacity of the `ArrayString`. /// /// ``` /// use arrayvec::ArrayString; /// /// let string = ArrayString::<3>::new(); /// assert_eq!(string.capacity(), 3); /// ``` #[inline(always)] pub const fn capacity(&self) -> usize { CAP } /// 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 const fn is_full(&self) -> bool { self.len() == self.capacity() } /// Returns the capacity left in the `ArrayString`. /// /// ``` /// use arrayvec::ArrayString; /// /// let mut string = ArrayString::<3>::from("abc").unwrap(); /// string.pop(); /// assert_eq!(string.remaining_capacity(), 1); /// ``` pub const fn remaining_capacity(&self) -> usize { self.capacity() - self.len() } /// 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"); /// ``` #[track_caller] 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> { let len = self.len(); unsafe { let ptr = self.as_mut_ptr().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"); /// ``` #[track_caller] 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.as_mut_ptr().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 { 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(); let ptr = self.as_mut_ptr(); unsafe { ptr::copy( ptr.add(next), ptr.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) { // type invariant that capacity always fits in LenUint debug_assert!(length <= self.capacity()); self.len = length as LenUint; } /// Return a string slice of the whole `ArrayString`. pub fn as_str(&self) -> &str { self } /// Return a mutable string slice of the whole `ArrayString`. pub fn as_mut_str(&mut self) -> &mut str { self } fn as_ptr(&self) -> *const u8 { self.xs.as_ptr() as *const u8 } fn as_mut_ptr(&mut self) -> *mut u8 { self.xs.as_mut_ptr() as *mut u8 } } impl Deref for ArrayString { type Target = str; #[inline] fn deref(&self) -> &str { unsafe { let sl = slice::from_raw_parts(self.as_ptr(), self.len()); str::from_utf8_unchecked(sl) } } } impl DerefMut for ArrayString { #[inline] fn deref_mut(&mut self) -> &mut str { unsafe { let len = self.len(); let sl = slice::from_raw_parts_mut(self.as_mut_ptr(), len); str::from_utf8_unchecked_mut(sl) } } } impl PartialEq for ArrayString { fn eq(&self, rhs: &Self) -> bool { **self == **rhs } } impl PartialEq for ArrayString { fn eq(&self, rhs: &str) -> bool { &**self == rhs } } impl PartialEq> for str { fn eq(&self, rhs: &ArrayString) -> bool { self == &**rhs } } impl Eq for ArrayString { } impl Hash for ArrayString { fn hash(&self, h: &mut H) { (**self).hash(h) } } impl Borrow for ArrayString { fn borrow(&self) -> &str { self } } impl BorrowMut for ArrayString { fn borrow_mut(&mut self) -> &mut str { self } } impl AsRef for ArrayString { fn as_ref(&self) -> &str { self } } impl fmt::Debug for ArrayString { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } } impl fmt::Display for ArrayString { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } } /// `Write` appends written data to the end of the string. impl fmt::Write for ArrayString { 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 Clone for ArrayString { fn clone(&self) -> ArrayString { *self } fn clone_from(&mut self, rhs: &Self) { // guaranteed to fit due to types matching. self.clear(); self.try_push_str(rhs).ok(); } } impl PartialOrd for ArrayString { fn partial_cmp(&self, rhs: &Self) -> Option { (**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 PartialOrd for ArrayString { fn partial_cmp(&self, rhs: &str) -> Option { (**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 PartialOrd> for str { fn partial_cmp(&self, rhs: &ArrayString) -> Option { self.partial_cmp(&**rhs) } fn lt(&self, rhs: &ArrayString) -> bool { self < &**rhs } fn le(&self, rhs: &ArrayString) -> bool { self <= &**rhs } fn gt(&self, rhs: &ArrayString) -> bool { self > &**rhs } fn ge(&self, rhs: &ArrayString) -> bool { self >= &**rhs } } impl Ord for ArrayString { fn cmp(&self, rhs: &Self) -> cmp::Ordering { (**self).cmp(&**rhs) } } impl FromStr for ArrayString { type Err = CapacityError; fn from_str(s: &str) -> Result { Self::from(s).map_err(CapacityError::simplify) } } #[cfg(feature="serde")] /// Requires crate feature `"serde"` impl Serialize for ArrayString { fn serialize(&self, serializer: S) -> Result where S: Serializer { serializer.serialize_str(&*self) } } #[cfg(feature="serde")] /// Requires crate feature `"serde"` impl<'de, const CAP: usize> Deserialize<'de> for ArrayString { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { use serde::de::{self, Visitor}; use std::marker::PhantomData; struct ArrayStringVisitor(PhantomData<[u8; CAP]>); impl<'de, const CAP: usize> Visitor<'de> for ArrayStringVisitor { type Value = ArrayString; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "a string no more than {} bytes long", CAP) } fn visit_str(self, v: &str) -> Result where E: de::Error, { ArrayString::from(v).map_err(|_| E::invalid_length(v.len(), &self)) } fn visit_bytes(self, v: &[u8]) -> Result 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(PhantomData)) } } impl<'a, const CAP: usize> TryFrom<&'a str> for ArrayString { type Error = CapacityError<&'a str>; fn try_from(f: &'a str) -> Result { let mut v = Self::new(); v.try_push_str(f)?; Ok(v) } } impl<'a, const CAP: usize> TryFrom> for ArrayString { type Error = CapacityError; fn try_from(f: fmt::Arguments<'a>) -> Result { use fmt::Write; let mut v = Self::new(); v.write_fmt(f).map_err(|e| CapacityError::new(e))?; Ok(v) } } #[cfg(feature = "zeroize")] /// "Best efforts" zeroing of the `ArrayString`'s buffer when the `zeroize` feature is enabled. /// /// The length is set to 0, and the buffer is dropped and zeroized. /// Cannot ensure that previous moves of the `ArrayString` did not leave values on the stack. /// /// ``` /// use arrayvec::ArrayString; /// use zeroize::Zeroize; /// let mut string = ArrayString::<6>::from("foobar").unwrap(); /// string.zeroize(); /// assert_eq!(string.len(), 0); /// unsafe { string.set_len(string.capacity()) }; /// assert_eq!(&*string, "\0\0\0\0\0\0"); /// ``` impl zeroize::Zeroize for ArrayString { fn zeroize(&mut self) { // There are no elements to drop self.clear(); // Zeroize the backing array. self.xs.zeroize(); } } arrayvec-0.7.4/src/arrayvec.rs000064400000000000000000001131411046102023000144220ustar 00000000000000 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; use std::mem::ManuallyDrop; use std::mem::MaybeUninit; #[cfg(feature="serde")] use serde::{Serialize, Deserialize, Serializer, Deserializer}; use crate::LenUint; use crate::errors::CapacityError; use crate::arrayvec_impl::ArrayVecImpl; use crate::utils::MakeMaybeUninit; /// 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 `ArrayVec` is parameterized /// by `T` for the element type and `CAP` for the maximum capacity. /// /// `CAP` is of type `usize` but is range limited to `u32::MAX`; attempting to create larger /// arrayvecs with larger capacity will panic. /// /// The vector is a contiguous value (storing the elements inline) 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. The ArrayVec can be converted into a by value iterator. pub struct ArrayVec { // the `len` first elements of the array are initialized xs: [MaybeUninit; CAP], len: LenUint, } impl Drop for ArrayVec { 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 ArrayVec { /// Capacity const CAPACITY: usize = CAP; /// Create a new empty `ArrayVec`. /// /// The maximum capacity is given by the generic parameter `CAP`. /// /// ``` /// 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); /// ``` #[inline] #[track_caller] pub fn new() -> ArrayVec { assert_capacity_limit!(CAP); unsafe { ArrayVec { xs: MaybeUninit::uninit().assume_init(), len: 0 } } } /// Create a new empty `ArrayVec` (const fn). /// /// The maximum capacity is given by the generic parameter `CAP`. /// /// ``` /// use arrayvec::ArrayVec; /// /// static ARRAY: ArrayVec = ArrayVec::new_const(); /// ``` pub const fn new_const() -> ArrayVec { assert_capacity_limit_const!(CAP); ArrayVec { xs: MakeMaybeUninit::ARRAY, len: 0 } } /// 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(always)] pub const fn len(&self) -> usize { self.len as 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 const 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 const fn capacity(&self) -> usize { CAP } /// Return true if the `ArrayVec` is completely filled to its capacity, false otherwise. /// /// ``` /// use arrayvec::ArrayVec; /// /// let mut array = ArrayVec::<_, 1>::new(); /// assert!(!array.is_full()); /// array.push(1); /// assert!(array.is_full()); /// ``` pub const 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 const 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]); /// ``` #[track_caller] pub fn push(&mut self, element: T) { ArrayVecImpl::push(self, element) } /// 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: T) -> Result<(), CapacityError> { ArrayVecImpl::try_push(self, 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: T) { ArrayVecImpl::push_unchecked(self, element) } /// 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) { ArrayVecImpl::truncate(self, new_len) } /// Remove all elements in the vector. pub fn clear(&mut self) { ArrayVecImpl::clear(self) } /// Get pointer to where element at `index` would be unsafe fn get_unchecked_ptr(&mut self, index: usize) -> *mut T { self.as_mut_ptr().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"]); /// /// ``` #[track_caller] pub fn insert(&mut self, index: usize, element: T) { 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: T) -> Result<(), CapacityError> { 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 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 { ArrayVecImpl::pop(self) } /// 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) -> T { 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 { 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) -> T { 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 { if index >= self.len() { None } else { self.drain(index..index + 1).next() } } /// 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(&mut self, mut f: F) where F: FnMut(&mut T) -> bool { // Check the implementation of // https://doc.rust-lang.org/std/vec/struct.Vec.html#method.retain // for safety arguments (especially regarding panics in f and when // dropping elements). Implementation closely mirrored here. let original_len = self.len(); unsafe { self.set_len(0) }; struct BackshiftOnDrop<'a, T, const CAP: usize> { v: &'a mut ArrayVec, processed_len: usize, deleted_cnt: usize, original_len: usize, } impl Drop for BackshiftOnDrop<'_, T, CAP> { fn drop(&mut self) { if self.deleted_cnt > 0 { unsafe { ptr::copy( self.v.as_ptr().add(self.processed_len), self.v.as_mut_ptr().add(self.processed_len - self.deleted_cnt), self.original_len - self.processed_len ); } } unsafe { self.v.set_len(self.original_len - self.deleted_cnt); } } } let mut g = BackshiftOnDrop { v: self, processed_len: 0, deleted_cnt: 0, original_len }; #[inline(always)] fn process_one bool, T, const CAP: usize, const DELETED: bool>( f: &mut F, g: &mut BackshiftOnDrop<'_, T, CAP> ) -> bool { let cur = unsafe { g.v.as_mut_ptr().add(g.processed_len) }; if !f(unsafe { &mut *cur }) { g.processed_len += 1; g.deleted_cnt += 1; unsafe { ptr::drop_in_place(cur) }; return false; } if DELETED { unsafe { let hole_slot = cur.sub(g.deleted_cnt); ptr::copy_nonoverlapping(cur, hole_slot, 1); } } g.processed_len += 1; true } // Stage 1: Nothing was deleted. while g.processed_len != original_len { if !process_one::(&mut f, &mut g) { break; } } // Stage 2: Some elements were deleted. while g.processed_len != original_len { process_one::(&mut f, &mut g); } drop(g); } /// 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) { // type invariant that capacity always fits in LenUint debug_assert!(length <= self.capacity()); self.len = length as LenUint; } /// Copy all elements from the slice and append to the `ArrayVec`. /// /// ``` /// use arrayvec::ArrayVec; /// /// let mut vec: ArrayVec = 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: &[T]) -> Result<(), CapacityError> where T: 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.get_unchecked_ptr(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 v1 = ArrayVec::from([1, 2, 3]); /// let v2: ArrayVec<_, 3> = v1.drain(0..2).collect(); /// assert_eq!(&v1[..], &[3]); /// assert_eq!(&v2[..], &[1, 2]); /// ``` pub fn drain(&mut self, range: R) -> Drain where R: RangeBounds { // 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 { 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 = start as LenUint; 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<[T; CAP], Self> { if self.len() < self.capacity() { Err(self) } else { unsafe { Ok(self.into_inner_unchecked()) } } } /// Return the inner fixed size array. /// /// Safety: /// This operation is safe if and only if length equals capacity. pub unsafe fn into_inner_unchecked(self) -> [T; CAP] { debug_assert_eq!(self.len(), self.capacity()); let self_ = ManuallyDrop::new(self); let array = ptr::read(self_.as_ptr() as *const [T; CAP]); array } /// Returns the ArrayVec, replacing the original with a new empty ArrayVec. /// /// ``` /// use arrayvec::ArrayVec; /// /// let mut v = ArrayVec::from([0, 1, 2, 3]); /// assert_eq!([0, 1, 2, 3], v.take().into_inner().unwrap()); /// assert!(v.is_empty()); /// ``` pub fn take(&mut self) -> Self { mem::replace(self, Self::new()) } /// Return a slice containing all elements of the vector. pub fn as_slice(&self) -> &[T] { ArrayVecImpl::as_slice(self) } /// Return a mutable slice containing all elements of the vector. pub fn as_mut_slice(&mut self) -> &mut [T] { ArrayVecImpl::as_mut_slice(self) } /// Return a raw pointer to the vector's buffer. pub fn as_ptr(&self) -> *const T { ArrayVecImpl::as_ptr(self) } /// Return a raw mutable pointer to the vector's buffer. pub fn as_mut_ptr(&mut self) -> *mut T { ArrayVecImpl::as_mut_ptr(self) } } impl ArrayVecImpl for ArrayVec { type Item = T; const CAPACITY: usize = CAP; fn len(&self) -> usize { self.len() } unsafe fn set_len(&mut self, length: usize) { debug_assert!(length <= CAP); self.len = length as LenUint; } fn as_ptr(&self) -> *const Self::Item { self.xs.as_ptr() as _ } fn as_mut_ptr(&mut self) -> *mut Self::Item { self.xs.as_mut_ptr() as _ } } impl Deref for ArrayVec { type Target = [T]; #[inline] fn deref(&self) -> &Self::Target { self.as_slice() } } impl DerefMut for ArrayVec { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { self.as_mut_slice() } } /// 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 From<[T; CAP]> for ArrayVec { #[track_caller] fn from(array: [T; CAP]) -> Self { let array = ManuallyDrop::new(array); let mut vec = >::new(); unsafe { (&*array as *const [T; CAP] as *const [MaybeUninit; CAP]) .copy_to_nonoverlapping(&mut vec.xs as *mut [MaybeUninit; CAP], 1); vec.set_len(CAP); } vec } } /// 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 std::convert::TryFrom<&[T]> for ArrayVec where T: Clone, { type Error = CapacityError; fn try_from(slice: &[T]) -> Result { if Self::CAPACITY < slice.len() { Err(CapacityError::new(())) } else { let mut array = Self::new(); array.extend_from_slice(slice); 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, T: 'a, const CAP: usize> IntoIterator for &'a ArrayVec { type Item = &'a T; type IntoIter = slice::Iter<'a, T>; 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, T: 'a, const CAP: usize> IntoIterator for &'a mut ArrayVec { type Item = &'a mut T; type IntoIter = slice::IterMut<'a, T>; 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 IntoIterator for ArrayVec { type Item = T; type IntoIter = IntoIter; fn into_iter(self) -> IntoIter { IntoIter { index: 0, v: self, } } } #[cfg(feature = "zeroize")] /// "Best efforts" zeroing of the `ArrayVec`'s buffer when the `zeroize` feature is enabled. /// /// The length is set to 0, and the buffer is dropped and zeroized. /// Cannot ensure that previous moves of the `ArrayVec` did not leave values on the stack. /// /// ``` /// use arrayvec::ArrayVec; /// use zeroize::Zeroize; /// let mut array = ArrayVec::from([1, 2, 3]); /// array.zeroize(); /// assert_eq!(array.len(), 0); /// let data = unsafe { core::slice::from_raw_parts(array.as_ptr(), array.capacity()) }; /// assert_eq!(data, [0, 0, 0]); /// ``` impl zeroize::Zeroize for ArrayVec { fn zeroize(&mut self) { // Zeroize all the contained elements. self.iter_mut().zeroize(); // Drop all the elements and set the length to 0. self.clear(); // Zeroize the backing array. self.xs.zeroize(); } } /// By-value iterator for `ArrayVec`. pub struct IntoIter { index: usize, v: ArrayVec, } impl Iterator for IntoIter { type Item = T; fn next(&mut self) -> Option { if self.index == self.v.len() { None } else { unsafe { let index = self.index; self.index = index + 1; Some(ptr::read(self.v.get_unchecked_ptr(index))) } } } fn size_hint(&self) -> (usize, Option) { let len = self.v.len() - self.index; (len, Some(len)) } } impl DoubleEndedIterator for IntoIter { fn next_back(&mut self) -> Option { 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 ExactSizeIterator for IntoIter { } impl Drop for IntoIter { fn drop(&mut self) { // panic safety: Set length to 0 before dropping elements. let index = self.index; 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 Clone for IntoIter where T: Clone, { fn clone(&self) -> IntoIter { let mut v = ArrayVec::new(); v.extend_from_slice(&self.v[self.index..]); v.into_iter() } } impl fmt::Debug for IntoIter where T: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list() .entries(&self.v[self.index..]) .finish() } } /// A draining iterator for `ArrayVec`. pub struct Drain<'a, T: 'a, const CAP: usize> { /// Index of tail to preserve tail_start: usize, /// Length of tail tail_len: usize, /// Current remaining range to remove iter: slice::Iter<'a, T>, vec: *mut ArrayVec, } unsafe impl<'a, T: Sync, const CAP: usize> Sync for Drain<'a, T, CAP> {} unsafe impl<'a, T: Send, const CAP: usize> Send for Drain<'a, T, CAP> {} impl<'a, T: 'a, const CAP: usize> Iterator for Drain<'a, T, CAP> { type Item = T; fn next(&mut self) -> Option { self.iter.next().map(|elt| unsafe { ptr::read(elt as *const _) } ) } fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } impl<'a, T: 'a, const CAP: usize> DoubleEndedIterator for Drain<'a, T, CAP> { fn next_back(&mut self) -> Option { self.iter.next_back().map(|elt| unsafe { ptr::read(elt as *const _) } ) } } impl<'a, T: 'a, const CAP: usize> ExactSizeIterator for Drain<'a, T, CAP> {} impl<'a, T: 'a, const CAP: usize> Drop for Drain<'a, T, CAP> { 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 ptr = source_vec.as_mut_ptr(); ptr::copy(ptr.add(tail), ptr.add(start), self.tail_len); source_vec.set_len(start + self.tail_len); } } } } struct ScopeExitGuard where F: FnMut(&Data, &mut T) { value: T, data: Data, f: F, } impl Drop for ScopeExitGuard where F: FnMut(&Data, &mut T) { fn drop(&mut self) { (self.f)(&self.data, &mut self.value) } } /// Extend the `ArrayVec` with an iterator. /// /// ***Panics*** if extending the vector exceeds its capacity. impl Extend for ArrayVec { /// Extend the `ArrayVec` with an iterator. /// /// ***Panics*** if extending the vector exceeds its capacity. #[track_caller] fn extend>(&mut self, iter: I) { unsafe { self.extend_from_iter::<_, true>(iter) } } } #[inline(never)] #[cold] #[track_caller] fn extend_panic() { panic!("ArrayVec: capacity exceeded in extend/from_iter"); } impl ArrayVec { /// Extend the arrayvec from the iterable. /// /// ## Safety /// /// Unsafe because if CHECK is false, the length of the input is not checked. /// The caller must ensure the length of the input fits in the capacity. #[track_caller] pub(crate) unsafe fn extend_from_iter(&mut self, iterable: I) where I: IntoIterator { let take = self.capacity() - self.len(); 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 = len as LenUint; } }; let mut iter = iterable.into_iter(); loop { if let Some(elt) = iter.next() { if ptr == end_ptr && CHECK { extend_panic(); } debug_assert_ne!(ptr, end_ptr); ptr.write(elt); ptr = raw_ptr_add(ptr, 1); guard.data += 1; } else { return; // success } } } /// Extend the ArrayVec with clones of elements from the slice; /// the length of the slice must be <= the remaining capacity in the arrayvec. pub(crate) fn extend_from_slice(&mut self, slice: &[T]) where T: Clone { let take = self.capacity() - self.len(); debug_assert!(slice.len() <= take); unsafe { let slice = if take < slice.len() { &slice[..take] } else { slice }; self.extend_from_iter::<_, false>(slice.iter().cloned()); } } } /// Rawptr add but uses arithmetic distance for ZST unsafe fn raw_ptr_add(ptr: *mut T, offset: usize) -> *mut T { if mem::size_of::() == 0 { // Special case for ZST ptr.cast::().wrapping_add(offset).cast() } else { ptr.add(offset) } } /// Create an `ArrayVec` from an iterator. /// /// ***Panics*** if the number of elements in the iterator exceeds the arrayvec's capacity. impl iter::FromIterator for ArrayVec { /// Create an `ArrayVec` from an iterator. /// /// ***Panics*** if the number of elements in the iterator exceeds the arrayvec's capacity. fn from_iter>(iter: I) -> Self { let mut array = ArrayVec::new(); array.extend(iter); array } } impl Clone for ArrayVec where T: 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 self.truncate(prefix); } else { let rhs_elems = &rhs[self.len()..]; self.extend_from_slice(rhs_elems); } } } impl Hash for ArrayVec where T: Hash { fn hash(&self, state: &mut H) { Hash::hash(&**self, state) } } impl PartialEq for ArrayVec where T: PartialEq { fn eq(&self, other: &Self) -> bool { **self == **other } } impl PartialEq<[T]> for ArrayVec where T: PartialEq { fn eq(&self, other: &[T]) -> bool { **self == *other } } impl Eq for ArrayVec where T: Eq { } impl Borrow<[T]> for ArrayVec { fn borrow(&self) -> &[T] { self } } impl BorrowMut<[T]> for ArrayVec { fn borrow_mut(&mut self) -> &mut [T] { self } } impl AsRef<[T]> for ArrayVec { fn as_ref(&self) -> &[T] { self } } impl AsMut<[T]> for ArrayVec { fn as_mut(&mut self) -> &mut [T] { self } } impl fmt::Debug for ArrayVec where T: fmt::Debug { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } } impl Default for ArrayVec { /// Return an empty array fn default() -> ArrayVec { ArrayVec::new() } } impl PartialOrd for ArrayVec where T: PartialOrd { fn partial_cmp(&self, other: &Self) -> Option { (**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 Ord for ArrayVec where T: Ord { fn cmp(&self, other: &Self) -> cmp::Ordering { (**self).cmp(other) } } #[cfg(feature="std")] /// `Write` appends written data to the end of the vector. /// /// Requires `features="std"`. impl io::Write for ArrayVec { fn write(&mut self, data: &[u8]) -> io::Result { 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 Serialize for ArrayVec { fn serialize(&self, serializer: S) -> Result where S: Serializer { serializer.collect_seq(self) } } #[cfg(feature="serde")] /// Requires crate feature `"serde"` impl<'de, T: Deserialize<'de>, const CAP: usize> Deserialize<'de> for ArrayVec { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { use serde::de::{Visitor, SeqAccess, Error}; use std::marker::PhantomData; struct ArrayVecVisitor<'de, T: Deserialize<'de>, const CAP: usize>(PhantomData<(&'de (), [T; CAP])>); impl<'de, T: Deserialize<'de>, const CAP: usize> Visitor<'de> for ArrayVecVisitor<'de, T, CAP> { type Value = ArrayVec; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "an array with no more than {} items", CAP) } fn visit_seq(self, mut seq: SA) -> Result where SA: SeqAccess<'de>, { let mut values = ArrayVec::::new(); while let Some(value) = seq.next_element()? { if let Err(_) = values.try_push(value) { return Err(SA::Error::invalid_length(CAP + 1, &self)); } } Ok(values) } } deserializer.deserialize_seq(ArrayVecVisitor::(PhantomData)) } } arrayvec-0.7.4/src/arrayvec_impl.rs000064400000000000000000000044431046102023000154470ustar 00000000000000use std::ptr; use std::slice; use crate::CapacityError; /// Implements basic arrayvec methods - based on a few required methods /// for length and element access. pub(crate) trait ArrayVecImpl { type Item; const CAPACITY: usize; fn len(&self) -> usize; unsafe fn set_len(&mut self, new_len: usize); /// Return a slice containing all elements of the vector. fn as_slice(&self) -> &[Self::Item] { let len = self.len(); unsafe { slice::from_raw_parts(self.as_ptr(), len) } } /// Return a mutable slice containing all elements of the vector. fn as_mut_slice(&mut self) -> &mut [Self::Item] { let len = self.len(); unsafe { std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) } } /// Return a raw pointer to the vector's buffer. fn as_ptr(&self) -> *const Self::Item; /// Return a raw mutable pointer to the vector's buffer. fn as_mut_ptr(&mut self) -> *mut Self::Item; #[track_caller] fn push(&mut self, element: Self::Item) { self.try_push(element).unwrap() } fn try_push(&mut self, element: Self::Item) -> Result<(), CapacityError> { if self.len() < Self::CAPACITY { unsafe { self.push_unchecked(element); } Ok(()) } else { Err(CapacityError::new(element)) } } unsafe fn push_unchecked(&mut self, element: Self::Item) { let len = self.len(); debug_assert!(len < Self::CAPACITY); ptr::write(self.as_mut_ptr().add(len), element); self.set_len(len + 1); } fn pop(&mut self) -> Option { if self.len() == 0 { return None; } unsafe { let new_len = self.len() - 1; self.set_len(new_len); Some(ptr::read(self.as_ptr().add(new_len))) } } fn clear(&mut self) { self.truncate(0) } fn truncate(&mut self, new_len: usize) { unsafe { let len = self.len(); if new_len < len { self.set_len(new_len); let tail = slice::from_raw_parts_mut(self.as_mut_ptr().add(new_len), len - new_len); ptr::drop_in_place(tail); } } } } arrayvec-0.7.4/src/char.rs000064400000000000000000000063631046102023000135320ustar 00000000000000// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. // // Original authors: alexchrichton, bluss // 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; /// Encode a char into buf using UTF-8. /// /// On success, return the byte length of the encoding (1, 2, 3 or 4).
/// 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 { let code = ch as u32; if code < MAX_ONE_B && len >= 1 { ptr.add(0).write(code as u8); return Ok(1); } else if code < MAX_TWO_B && len >= 2 { ptr.add(0).write((code >> 6 & 0x1F) as u8 | TAG_TWO_B); ptr.add(1).write((code & 0x3F) as u8 | TAG_CONT); return Ok(2); } else if code < MAX_THREE_B && len >= 3 { ptr.add(0).write((code >> 12 & 0x0F) as u8 | TAG_THREE_B); ptr.add(1).write((code >> 6 & 0x3F) as u8 | TAG_CONT); ptr.add(2).write((code & 0x3F) as u8 | TAG_CONT); return Ok(3); } else if len >= 4 { ptr.add(0).write((code >> 18 & 0x07) as u8 | TAG_FOUR_B); ptr.add(1).write((code >> 12 & 0x3F) as u8 | TAG_CONT); ptr.add(2).write((code >> 6 & 0x3F) as u8 | TAG_CONT); ptr.add(3).write((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(_))); } } } arrayvec-0.7.4/src/errors.rs000064400000000000000000000022511046102023000141210ustar 00000000000000use 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 { element: T, } impl CapacityError { /// Create a new `CapacityError` from `element`. pub const fn new(element: T) -> CapacityError { 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 Error for CapacityError {} impl fmt::Display for CapacityError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", CAPERROR) } } impl fmt::Debug for CapacityError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}: {}", "CapacityError", CAPERROR) } } arrayvec-0.7.4/src/lib.rs000064400000000000000000000031501046102023000133520ustar 00000000000000//! **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 //! //! - `zeroize` //! - Optional //! - Implement `Zeroize` for ArrayVec and ArrayString //! //! ## Rust Version //! //! This version of arrayvec requires Rust 1.51 or later. //! #![doc(html_root_url="https://docs.rs/arrayvec/0.7/")] #![cfg_attr(not(feature="std"), no_std)] #[cfg(feature="serde")] extern crate serde; #[cfg(not(feature="std"))] extern crate core as std; pub(crate) type LenUint = u32; macro_rules! assert_capacity_limit { ($cap:expr) => { if std::mem::size_of::() > std::mem::size_of::() { if $cap > LenUint::MAX as usize { panic!("ArrayVec: largest supported capacity is u32::MAX") } } } } macro_rules! assert_capacity_limit_const { ($cap:expr) => { if std::mem::size_of::() > std::mem::size_of::() { if $cap > LenUint::MAX as usize { [/*ArrayVec: largest supported capacity is u32::MAX*/][$cap] } } } } mod arrayvec_impl; mod arrayvec; mod array_string; mod char; mod errors; mod utils; pub use crate::array_string::ArrayString; pub use crate::errors::CapacityError; pub use crate::arrayvec::{ArrayVec, IntoIter, Drain}; arrayvec-0.7.4/src/utils.rs000064400000000000000000000005051046102023000137450ustar 00000000000000use std::marker::PhantomData; use std::mem::MaybeUninit; pub(crate) struct MakeMaybeUninit(PhantomData T>); impl MakeMaybeUninit { pub(crate) const VALUE: MaybeUninit = MaybeUninit::uninit(); pub(crate) const ARRAY: [MaybeUninit; N] = [Self::VALUE; N]; } arrayvec-0.7.4/tests/serde.rs000064400000000000000000000034211046102023000142620ustar 00000000000000#![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::::new(); assert_tokens(&vec, &[ Token::Seq { len: Some(0) }, Token::SeqEnd, ]); } #[test] fn test_ser_de() { let mut vec = ArrayVec::::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::>(&[ 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::<0>::new(); assert_tokens(&string, &[ Token::Str(""), ]); } #[test] fn test_ser_de() { let string = ArrayString::<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::>(&[ Token::Str("afd") ], "invalid length 3, expected a string no more than 2 bytes long"); } } arrayvec-0.7.4/tests/tests.rs000064400000000000000000000460351046102023000143320ustar 00000000000000extern 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, 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 = 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 = 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 = 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 = 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, _> = (&[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); impl<'a> Drop for Bump<'a> { fn drop(&mut self) { let n = self.0.get(); self.0.set(n + 1); } } { let mut array = ArrayVec::::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 take flag.set(0); { let mut array1 = ArrayVec::<_, 3>::new(); array1.push(Bump(flag)); array1.push(Bump(flag)); array1.push(Bump(flag)); let array2 = array1.take(); assert_eq!(flag.get(), 0); drop(array1); assert_eq!(flag.get(), 0); drop(array2); 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); // 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::::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::::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().take(5).collect(); assert_eq!(&array[..], &[0, 1, 2, 3, 4]); assert_eq!(range.next(), Some(5)); array.extend(range.by_ref().take(0)); 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]); } #[should_panic] #[test] fn test_extend_capacity_panic_1() { let mut range = 0..10; let _: ArrayVec<_, 5> = range.by_ref().collect(); } #[should_panic] #[test] fn test_extend_capacity_panic_2() { let mut range = 0..10; let mut array: ArrayVec<_, 5> = range.by_ref().take(5).collect(); assert_eq!(&array[..], &[0, 1, 2, 3, 4]); assert_eq!(range.next(), Some(5)); array.extend(range.by_ref().take(1)); } #[test] fn test_is_send_sync() { let data = ArrayVec::, 5>::new(); &data as &dyn Send; &data as &dyn Sync; } #[test] fn test_compact_size() { // 4 bytes + padding + length type ByteArray = ArrayVec; println!("{}", mem::size_of::()); assert!(mem::size_of::() <= 2 * mem::size_of::()); // just length type EmptyArray = ArrayVec; println!("{}", mem::size_of::()); assert!(mem::size_of::() <= mem::size_of::()); // 3 elements + padding + length type QuadArray = ArrayVec; println!("{}", mem::size_of::()); assert!(mem::size_of::() <= 4 * 4 + mem::size_of::()); } #[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..8); 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..8); 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::::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::::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::::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::::new(); v.extend(1..=4); assert_eq!(v.into_inner().unwrap(), [1, 2, 3, 4]); } #[test] fn test_take() { let mut v1 = ArrayVec::::new(); v1.extend(1..=4); let v2 = v1.take(); assert!(v1.into_inner().is_err()); assert_eq!(v2.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> { 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); 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::::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<4> = Default::default(); // Something without `Default` implementation. let v: ArrayVec = 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().take(5).map(|_| Z).collect(); assert_eq!(&array[..], &[Z; 5]); assert_eq!(range.next(), Some(5)); array.extend(range.by_ref().take(0).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); } #[test] fn test_try_from_argument() { use core::convert::TryFrom; let v = ArrayString::<16>::try_from(format_args!("Hello {}", 123)).unwrap(); assert_eq!(&v, "Hello 123"); } #[test] fn allow_max_capacity_arrayvec_type() { // this type is allowed to be used (but can't be constructed) let _v: ArrayVec<(), {usize::MAX}>; } #[should_panic(expected="largest supported capacity")] #[test] fn deny_max_capacity_arrayvec_value() { if mem::size_of::() <= mem::size_of::() { panic!("This test does not work on this platform. 'largest supported capacity'"); } // this type is allowed to be used (but can't be constructed) let _v: ArrayVec<(), {usize::MAX}> = ArrayVec::new(); } #[should_panic(expected="index out of bounds")] #[test] fn deny_max_capacity_arrayvec_value_const() { if mem::size_of::() <= mem::size_of::() { panic!("This test does not work on this platform. 'index out of bounds'"); } // this type is allowed to be used (but can't be constructed) let _v: ArrayVec<(), {usize::MAX}> = ArrayVec::new_const(); } #[test] fn test_arrayvec_const_constructible() { const OF_U8: ArrayVec, 10> = ArrayVec::new_const(); let mut var = OF_U8; assert!(var.is_empty()); assert_eq!(var, ArrayVec::new()); var.push(vec![3, 5, 8]); assert_eq!(var[..], [vec![3, 5, 8]]); } #[test] fn test_arraystring_const_constructible() { const AS: ArrayString<10> = ArrayString::new_const(); let mut var = AS; assert!(var.is_empty()); assert_eq!(var, ArrayString::new()); var.push_str("hello"); assert_eq!(var, *"hello"); } #[test] fn test_arraystring_zero_filled_has_some_sanity_checks() { let string = ArrayString::<4>::zero_filled(); assert_eq!(string.as_str(), "\0\0\0\0"); assert_eq!(string.len(), 4); }