arrayvec-0.5.2/.cargo_vcs_info.json0000644000000001121374460271300127130ustar { "git": { "sha1": "d336f8c5c54df87154deb59ffc5c0a91749069be" } } arrayvec-0.5.2/.gitignore010064400017500001750000000001461374460075100135130ustar 00000000000000# Compiled files *.o *.so *.rlib *.dll # Executables *.exe # Generated by Cargo /Cargo.lock /target arrayvec-0.5.2/.travis.yml010064400017500001750000000020721374460075100136340ustar 00000000000000language: rust sudo: false env: - FEATURES='serde' matrix: include: - rust: 1.36.0 env: - FEATURES='array-sizes-33-128 array-sizes-129-255' - rust: stable - rust: stable env: - FEATURES='serde' - rust: stable env: - FEATURES='array-sizes-33-128 array-sizes-129-255' - rust: beta - rust: nightly - rust: nightly env: - FEATURES='serde' - rust: nightly env: - FEATURES='array-sizes-33-128 array-sizes-129-255' - rust: nightly env: - FEATURES='unstable-const-fn' - name: "miri" script: sh ci/miri.sh branches: only: - master - 0.4 script: - | cargo build -v --no-default-features && cargo build -v --features "$FEATURES" && cargo test -v --features "$FEATURES" && cargo test -v --release --features "$FEATURES" && cargo bench -v --features "$FEATURES" --no-run && cargo doc -v --features "$FEATURES" && cargo build -v --manifest-path=nodrop/Cargo.toml && cargo test -v --manifest-path=nodrop/Cargo.toml arrayvec-0.5.2/CHANGELOG.md010064400017500001750000000162351374460237600133470ustar 00000000000000Recent Changes (arrayvec) ------------------------- - 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. - 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.5.2/Cargo.toml0000644000000031171374460271300107210ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] edition = "2018" name = "arrayvec" version = "0.5.2" authors = ["bluss"] description = "A vector with fixed capacity, backed by an array (it can be stored on the stack too). Implements fixed capacity ArrayVec and ArrayString." documentation = "https://docs.rs/arrayvec/" keywords = ["stack", "vector", "array", "data-structure", "no_std"] categories = ["data-structures", "no-std"] license = "MIT/Apache-2.0" repository = "https://github.com/bluss/arrayvec" [package.metadata.docs.rs] features = ["serde"] [package.metadata.release] no-dev-version = true tag-name = "{{version}}" [profile.bench] debug = true [profile.release] debug = true [[bench]] name = "extend" harness = false [[bench]] name = "arraystring" harness = false [dependencies.serde] version = "1.0" optional = true default-features = false [dev-dependencies.bencher] version = "0.1.4" [dev-dependencies.matches] version = "0.1" [dev-dependencies.serde_test] version = "1.0" [build-dependencies] [features] array-sizes-129-255 = [] array-sizes-33-128 = [] default = ["std"] std = [] unstable-const-fn = [] arrayvec-0.5.2/Cargo.toml.orig010064400017500001750000000020621374460253200144100ustar 00000000000000[package] name = "arrayvec" version = "0.5.2" authors = ["bluss"] license = "MIT/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 [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 = [] unstable-const-fn = [] array-sizes-33-128 = [] array-sizes-129-255 = [] [profile.bench] debug = true [profile.release] debug = true [package.metadata.docs.rs] features = ["serde"] [package.metadata.release] no-dev-version = true tag-name = "{{version}}" arrayvec-0.5.2/LICENSE-APACHE010064400017500001750000000251371374460075100134560ustar 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.5.2/LICENSE-MIT010064400017500001750000000020571374460075100131620ustar 00000000000000Copyright (c) Ulrik Sverdrup "bluss" 2015-2017 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. arrayvec-0.5.2/README.md010064400017500001750000000017631374460075100130100ustar 00000000000000 arrayvec ======== [![Crates.io: arrayvec](https://img.shields.io/crates/v/arrayvec.svg)](https://crates.io/crates/arrayvec) [![Crates.io: nodrop](https://img.shields.io/crates/v/nodrop.svg)](https://crates.io/crates/nodrop) [![Documentation](https://docs.rs/arrayvec/badge.svg)](https://docs.rs/arrayvec) [![Build Status](https://travis-ci.org/bluss/arrayvec.svg?branch=master)](https://travis-ci.org/bluss/arrayvec) [![License: Apache](https://img.shields.io/badge/License-Apache%202.0-red.svg)](LICENSE-APACHE) OR [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) A vector with fixed capacity. Please read the [`API documentation here`](https://docs.rs/arrayvec) # License Dual-licensed to be compatible with the Rust project. Licensed under the Apache License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0 or the MIT license http://opensource.org/licenses/MIT, at your option. This file may not be copied, modified, or distributed except according to those terms. arrayvec-0.5.2/benches/arraystring.rs010064400017500001750000000037171374460075100160540ustar 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::<[u8; 512]>::new(); b.iter(|| { v.clear(); while v.try_push('c').is_ok() { } v.len() }); b.bytes = v.capacity() as u64; } fn try_push_alpha(b: &mut Bencher) { let mut v = ArrayString::<[u8; 512]>::new(); b.iter(|| { v.clear(); while v.try_push('α').is_ok() { } v.len() }); b.bytes = v.capacity() as u64; } // Yes, pushing a string char-by-char is slow. Use .push_str. fn try_push_string(b: &mut Bencher) { let mut v = ArrayString::<[u8; 512]>::new(); let input = "abcαβγ“”"; b.iter(|| { v.clear(); for ch in input.chars().cycle() { if !v.try_push(ch).is_ok() { break; } } v.len() }); b.bytes = v.capacity() as u64; } fn push_c(b: &mut Bencher) { let mut v = ArrayString::<[u8; 512]>::new(); b.iter(|| { v.clear(); while !v.is_full() { v.push('c'); } v.len() }); b.bytes = v.capacity() as u64; } fn push_alpha(b: &mut Bencher) { let mut v = ArrayString::<[u8; 512]>::new(); b.iter(|| { v.clear(); while !v.is_full() { v.push('α'); } v.len() }); b.bytes = v.capacity() as u64; } fn push_string(b: &mut Bencher) { let mut v = ArrayString::<[u8; 512]>::new(); let input = "abcαβγ“”"; b.iter(|| { v.clear(); for ch in input.chars().cycle() { if !v.is_full() { v.push(ch); } else { break; } } v.len() }); b.bytes = v.capacity() as u64; } benchmark_group!(benches, try_push_c, try_push_alpha, try_push_string, push_c, push_alpha, push_string); benchmark_main!(benches); arrayvec-0.5.2/benches/extend.rs010064400017500001750000000033251374460075100147710ustar 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::<[u8; 512]>::new(); let cap = v.capacity(); b.iter(|| { v.clear(); let constant = black_box(1); v.extend((0..cap).map(move |_| constant)); v[511] }); b.bytes = v.capacity() as u64; } fn extend_with_range(b: &mut Bencher) { let mut v = ArrayVec::<[u8; 512]>::new(); let cap = v.capacity(); b.iter(|| { v.clear(); let range = 0..cap; v.extend(range.map(|x| black_box(x as _))); v[511] }); b.bytes = v.capacity() as u64; } fn extend_with_slice(b: &mut Bencher) { let mut v = ArrayVec::<[u8; 512]>::new(); let data = [1; 512]; b.iter(|| { v.clear(); let iter = data.iter().map(|&x| x); v.extend(iter); v[511] }); b.bytes = v.capacity() as u64; } fn extend_with_write(b: &mut Bencher) { let mut v = ArrayVec::<[u8; 512]>::new(); let data = [1; 512]; b.iter(|| { v.clear(); v.write(&data[..]).ok(); v[511] }); b.bytes = v.capacity() as u64; } fn extend_from_slice(b: &mut Bencher) { let mut v = ArrayVec::<[u8; 512]>::new(); let data = [1; 512]; b.iter(|| { v.clear(); v.try_extend_from_slice(&data).ok(); v[511] }); b.bytes = v.capacity() as u64; } benchmark_group!(benches, extend_with_constant, extend_with_range, extend_with_slice, extend_with_write, extend_from_slice ); benchmark_main!(benches); arrayvec-0.5.2/ci/miri.sh010064400017500001750000000005341374460075100134130ustar 00000000000000#!/usr/bin/env sh set -ex export CARGO_NET_RETRY=5 export CARGO_NET_TIMEOUT=10 MIRI_NIGHTLY=nightly-$(curl -s https://rust-lang.github.io/rustup-components-history/x86_64-unknown-linux-gnu/miri) echo "Installing latest nightly with Miri: $MIRI_NIGHTLY" rustup default "$MIRI_NIGHTLY" rustup component add miri cargo miri setup cargo miri test arrayvec-0.5.2/custom.css010064400017500001750000000010251374460075100135440ustar 00000000000000 .docblock pre.rust { background: #eeeeff; } pre.trait, pre.fn, pre.struct, pre.enum, pre.typedef { background: #fcfefc; } /* Small “example” label for doc examples */ .docblock pre.rust::before { content: "example"; float: right; font-style: italic; font-size: 0.8em; margin-top: -10px; margin-right: -5px; } /* Fixup where display in trait listing */ pre.trait .where::before { content: '\a '; } .docblock code { background-color: inherit; font-weight: bold; padding: 0 0.1em; } arrayvec-0.5.2/src/array.rs010064400017500001750000000116131374460075100137770ustar 00000000000000 /// Trait for fixed size arrays. /// /// This trait is implemented for some specific array sizes, see /// the implementor list below. At the current state of Rust we can't /// make this fully general for every array size. /// /// The following crate features add more array sizes (and they are not /// enabled by default due to their impact on compliation speed). /// /// - `array-sizes-33-128`: All sizes 33 to 128 are implemented /// (a few in this range are included by default). /// - `array-sizes-129-255`: All sizes 129 to 255 are implemented /// (a few in this range are included by default). /// /// ## Safety /// /// This trait can *only* be implemented by fixed-size arrays or types with /// *exactly* the representation of a fixed size array (of the right element /// type and capacity). /// /// Normally this trait is an implementation detail of arrayvec and doesn’t /// need implementing. pub unsafe trait Array { /// The array’s element type type Item; /// The smallest type that can index and tell the length of the array. #[doc(hidden)] type Index: Index; /// The array's element capacity const CAPACITY: usize; fn as_slice(&self) -> &[Self::Item]; fn as_mut_slice(&mut self) -> &mut [Self::Item]; } pub trait Index : PartialEq + Copy { const ZERO: Self; fn to_usize(self) -> usize; fn from(_: usize) -> Self; } impl Index for () { const ZERO: Self = (); #[inline(always)] fn to_usize(self) -> usize { 0 } #[inline(always)] fn from(_ix: usize) -> Self { () } } impl Index for bool { const ZERO: Self = false; #[inline(always)] fn to_usize(self) -> usize { self as usize } #[inline(always)] fn from(ix: usize) -> Self { ix != 0 } } impl Index for u8 { const ZERO: Self = 0; #[inline(always)] fn to_usize(self) -> usize { self as usize } #[inline(always)] fn from(ix: usize) -> Self { ix as u8 } } impl Index for u16 { const ZERO: Self = 0; #[inline(always)] fn to_usize(self) -> usize { self as usize } #[inline(always)] fn from(ix: usize) -> Self { ix as u16 } } impl Index for u32 { const ZERO: Self = 0; #[inline(always)] fn to_usize(self) -> usize { self as usize } #[inline(always)] fn from(ix: usize) -> Self { ix as u32 } } impl Index for usize { const ZERO: Self = 0; #[inline(always)] fn to_usize(self) -> usize { self } #[inline(always)] fn from(ix: usize) -> Self { ix } } macro_rules! fix_array_impl { ($index_type:ty, $len:expr ) => ( unsafe impl Array for [T; $len] { type Item = T; type Index = $index_type; const CAPACITY: usize = $len; #[doc(hidden)] fn as_slice(&self) -> &[Self::Item] { self } #[doc(hidden)] fn as_mut_slice(&mut self) -> &mut [Self::Item] { self } } ) } macro_rules! fix_array_impl_recursive { ($index_type:ty, ) => (); ($index_type:ty, $($len:expr,)*) => ( $(fix_array_impl!($index_type, $len);)* ); } fix_array_impl_recursive!((), 0,); fix_array_impl_recursive!(bool, 1,); fix_array_impl_recursive!(u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, ); #[cfg(not(feature="array-sizes-33-128"))] fix_array_impl_recursive!(u8, 32, 40, 48, 50, 56, 64, 72, 96, 100, 128, ); #[cfg(feature="array-sizes-33-128")] fix_array_impl_recursive!(u8, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, ); #[cfg(not(feature="array-sizes-129-255"))] fix_array_impl_recursive!(u8, 160, 192, 200, 224,); #[cfg(feature="array-sizes-129-255")] fix_array_impl_recursive!(u8, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, ); fix_array_impl_recursive!(u16, 256, 384, 512, 768, 1024, 2048, 4096, 8192, 16384, 32768,); // This array size doesn't exist on 16-bit #[cfg(any(target_pointer_width="32", target_pointer_width="64"))] fix_array_impl_recursive!(u32, 1 << 16,); arrayvec-0.5.2/src/array_string.rs010064400017500001750000000401311374460075100153620ustar 00000000000000use std::borrow::Borrow; use std::cmp; use std::fmt; use std::hash::{Hash, Hasher}; use std::ptr; use std::ops::{Deref, DerefMut}; use std::str; use std::str::FromStr; use std::str::Utf8Error; use std::slice; use crate::array::Array; use crate::array::Index; use crate::CapacityError; use crate::char::encode_utf8; #[cfg(feature="serde")] use serde::{Serialize, Deserialize, Serializer, Deserializer}; use super::MaybeUninit as MaybeUninitCopy; /// A string with a fixed capacity. /// /// The `ArrayString` is a string backed by a fixed size array. It keeps track /// of its length. /// /// The string is a contiguous value that you can store directly on the stack /// if needed. #[derive(Copy)] pub struct ArrayString where A: Array + Copy { xs: MaybeUninitCopy, len: A::Index, } impl Default for ArrayString where A: Array + Copy { /// Return an empty `ArrayString` fn default() -> ArrayString { ArrayString::new() } } impl ArrayString where A: Array + Copy { /// Create a new empty `ArrayString`. /// /// Capacity is inferred from the type parameter. /// /// ``` /// use arrayvec::ArrayString; /// /// let mut string = ArrayString::<[_; 16]>::new(); /// string.push_str("foo"); /// assert_eq!(&string[..], "foo"); /// assert_eq!(string.capacity(), 16); /// ``` #[cfg(not(feature="unstable-const-fn"))] pub fn new() -> ArrayString { unsafe { ArrayString { xs: MaybeUninitCopy::uninitialized(), len: Index::ZERO, } } } #[cfg(feature="unstable-const-fn")] pub const fn new() -> ArrayString { unsafe { ArrayString { xs: MaybeUninitCopy::uninitialized(), len: Index::ZERO, } } } /// Return the length of the string. #[inline] pub fn len(&self) -> usize { self.len.to_usize() } /// Returns whether the string is empty. #[inline] pub fn is_empty(&self) -> bool { self.len() == 0 } /// Create a new `ArrayString` from a `str`. /// /// Capacity is inferred from the type parameter. /// /// **Errors** if the backing array is not large enough to fit the string. /// /// ``` /// use arrayvec::ArrayString; /// /// let mut string = ArrayString::<[_; 3]>::from("foo").unwrap(); /// assert_eq!(&string[..], "foo"); /// assert_eq!(string.len(), 3); /// assert_eq!(string.capacity(), 3); /// ``` pub fn from(s: &str) -> Result> { let mut arraystr = Self::new(); arraystr.try_push_str(s)?; Ok(arraystr) } /// Create a new `ArrayString` from a byte string literal. /// /// **Errors** if the byte string literal is not valid UTF-8. /// /// ``` /// use arrayvec::ArrayString; /// /// let string = ArrayString::from_byte_string(b"hello world").unwrap(); /// ``` pub fn from_byte_string(b: &A) -> Result { let len = str::from_utf8(b.as_slice())?.len(); debug_assert_eq!(len, A::CAPACITY); Ok(ArrayString { xs: MaybeUninitCopy::from(*b), len: Index::from(A::CAPACITY), }) } /// Return the capacity of the `ArrayString`. /// /// ``` /// use arrayvec::ArrayString; /// /// let string = ArrayString::<[_; 3]>::new(); /// assert_eq!(string.capacity(), 3); /// ``` #[inline(always)] pub fn capacity(&self) -> usize { A::CAPACITY } /// Return if the `ArrayString` is completely filled. /// /// ``` /// use arrayvec::ArrayString; /// /// let mut string = ArrayString::<[_; 1]>::new(); /// assert!(!string.is_full()); /// string.push_str("A"); /// assert!(string.is_full()); /// ``` pub fn is_full(&self) -> bool { self.len() == self.capacity() } /// Adds the given char to the end of the string. /// /// ***Panics*** if the backing array is not large enough to fit the additional char. /// /// ``` /// use arrayvec::ArrayString; /// /// let mut string = ArrayString::<[_; 2]>::new(); /// /// string.push('a'); /// string.push('b'); /// /// assert_eq!(&string[..], "ab"); /// ``` pub fn push(&mut self, c: char) { self.try_push(c).unwrap(); } /// Adds the given char to the end of the string. /// /// Returns `Ok` if the push succeeds. /// /// **Errors** if the backing array is not large enough to fit the additional char. /// /// ``` /// use arrayvec::ArrayString; /// /// let mut string = ArrayString::<[_; 2]>::new(); /// /// string.try_push('a').unwrap(); /// string.try_push('b').unwrap(); /// let overflow = string.try_push('c'); /// /// assert_eq!(&string[..], "ab"); /// assert_eq!(overflow.unwrap_err().element(), 'c'); /// ``` pub fn try_push(&mut self, c: char) -> Result<(), CapacityError> { let len = self.len(); unsafe { let ptr = self.xs.ptr_mut().add(len); let remaining_cap = self.capacity() - len; match encode_utf8(c, ptr, remaining_cap) { Ok(n) => { self.set_len(len + n); Ok(()) } Err(_) => Err(CapacityError::new(c)), } } } /// Adds the given string slice to the end of the string. /// /// ***Panics*** if the backing array is not large enough to fit the string. /// /// ``` /// use arrayvec::ArrayString; /// /// let mut string = ArrayString::<[_; 2]>::new(); /// /// string.push_str("a"); /// string.push_str("d"); /// /// assert_eq!(&string[..], "ad"); /// ``` pub fn push_str(&mut self, s: &str) { self.try_push_str(s).unwrap() } /// Adds the given string slice to the end of the string. /// /// Returns `Ok` if the push succeeds. /// /// **Errors** if the backing array is not large enough to fit the string. /// /// ``` /// use arrayvec::ArrayString; /// /// let mut string = ArrayString::<[_; 2]>::new(); /// /// string.try_push_str("a").unwrap(); /// let overflow1 = string.try_push_str("bc"); /// string.try_push_str("d").unwrap(); /// let overflow2 = string.try_push_str("ef"); /// /// assert_eq!(&string[..], "ad"); /// assert_eq!(overflow1.unwrap_err().element(), "bc"); /// assert_eq!(overflow2.unwrap_err().element(), "ef"); /// ``` pub fn try_push_str<'a>(&mut self, s: &'a str) -> Result<(), CapacityError<&'a str>> { if s.len() > self.capacity() - self.len() { return Err(CapacityError::new(s)); } unsafe { let dst = self.xs.ptr_mut().add(self.len()); let src = s.as_ptr(); ptr::copy_nonoverlapping(src, dst, s.len()); let newl = self.len() + s.len(); self.set_len(newl); } Ok(()) } /// Removes the last character from the string and returns it. /// /// Returns `None` if this `ArrayString` is empty. /// /// ``` /// use arrayvec::ArrayString; /// /// let mut s = ArrayString::<[_; 3]>::from("foo").unwrap(); /// /// assert_eq!(s.pop(), Some('o')); /// assert_eq!(s.pop(), Some('o')); /// assert_eq!(s.pop(), Some('f')); /// /// assert_eq!(s.pop(), None); /// ``` pub fn pop(&mut self) -> Option { let ch = match self.chars().rev().next() { Some(ch) => ch, None => return None, }; let new_len = self.len() - ch.len_utf8(); unsafe { self.set_len(new_len); } Some(ch) } /// Shortens this `ArrayString` to the specified length. /// /// If `new_len` is greater than the string’s current length, this has no /// effect. /// /// ***Panics*** if `new_len` does not lie on a `char` boundary. /// /// ``` /// use arrayvec::ArrayString; /// /// let mut string = ArrayString::<[_; 6]>::from("foobar").unwrap(); /// string.truncate(3); /// assert_eq!(&string[..], "foo"); /// string.truncate(4); /// assert_eq!(&string[..], "foo"); /// ``` pub fn truncate(&mut self, new_len: usize) { if new_len <= self.len() { assert!(self.is_char_boundary(new_len)); unsafe { // In libstd truncate is called on the underlying vector, // which in turns drops each element. // As we know we don't have to worry about Drop, // we can just set the length (a la clear.) self.set_len(new_len); } } } /// Removes a `char` from this `ArrayString` at a byte position and returns it. /// /// This is an `O(n)` operation, as it requires copying every element in the /// array. /// /// ***Panics*** if `idx` is larger than or equal to the `ArrayString`’s length, /// or if it does not lie on a `char` boundary. /// /// ``` /// use arrayvec::ArrayString; /// /// let mut s = ArrayString::<[_; 3]>::from("foo").unwrap(); /// /// assert_eq!(s.remove(0), 'f'); /// assert_eq!(s.remove(1), 'o'); /// assert_eq!(s.remove(0), 'o'); /// ``` pub fn remove(&mut self, idx: usize) -> char { let ch = match self[idx..].chars().next() { Some(ch) => ch, None => panic!("cannot remove a char from the end of a string"), }; let next = idx + ch.len_utf8(); let len = self.len(); unsafe { ptr::copy(self.xs.ptr().add(next), self.xs.ptr_mut().add(idx), len - next); self.set_len(len - (next - idx)); } ch } /// Make the string empty. pub fn clear(&mut self) { unsafe { self.set_len(0); } } /// Set the strings’s length. /// /// This function is `unsafe` because it changes the notion of the /// number of “valid” bytes in the string. Use with care. /// /// This method uses *debug assertions* to check the validity of `length` /// and may use other debug assertions. pub unsafe fn set_len(&mut self, length: usize) { debug_assert!(length <= self.capacity()); self.len = Index::from(length); } /// Return a string slice of the whole `ArrayString`. pub fn as_str(&self) -> &str { self } } impl Deref for ArrayString where A: Array + Copy { type Target = str; #[inline] fn deref(&self) -> &str { unsafe { let sl = slice::from_raw_parts(self.xs.ptr(), self.len.to_usize()); str::from_utf8_unchecked(sl) } } } impl DerefMut for ArrayString where A: Array + Copy { #[inline] fn deref_mut(&mut self) -> &mut str { unsafe { let sl = slice::from_raw_parts_mut(self.xs.ptr_mut(), self.len.to_usize()); str::from_utf8_unchecked_mut(sl) } } } impl PartialEq for ArrayString where A: Array + Copy { fn eq(&self, rhs: &Self) -> bool { **self == **rhs } } impl PartialEq for ArrayString where A: Array + Copy { fn eq(&self, rhs: &str) -> bool { &**self == rhs } } impl PartialEq> for str where A: Array + Copy { fn eq(&self, rhs: &ArrayString) -> bool { self == &**rhs } } impl Eq for ArrayString where A: Array + Copy { } impl Hash for ArrayString where A: Array + Copy { fn hash(&self, h: &mut H) { (**self).hash(h) } } impl Borrow for ArrayString where A: Array + Copy { fn borrow(&self) -> &str { self } } impl AsRef for ArrayString where A: Array + Copy { fn as_ref(&self) -> &str { self } } impl fmt::Debug for ArrayString where A: Array + Copy { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } } impl fmt::Display for ArrayString where A: Array + Copy { 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 where A: Array + Copy { fn write_char(&mut self, c: char) -> fmt::Result { self.try_push(c).map_err(|_| fmt::Error) } fn write_str(&mut self, s: &str) -> fmt::Result { self.try_push_str(s).map_err(|_| fmt::Error) } } impl Clone for ArrayString where A: Array + Copy { 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 where A: Array + Copy { 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 where A: Array + Copy { 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 where A: Array + Copy { 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 where A: Array + Copy { fn cmp(&self, rhs: &Self) -> cmp::Ordering { (**self).cmp(&**rhs) } } impl FromStr for ArrayString where A: Array + Copy { 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 where A: Array + Copy { fn serialize(&self, serializer: S) -> Result where S: Serializer { serializer.serialize_str(&*self) } } #[cfg(feature="serde")] /// Requires crate feature `"serde"` impl<'de, A> Deserialize<'de> for ArrayString where A: Array + Copy { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { use serde::de::{self, Visitor}; use std::marker::PhantomData; struct ArrayStringVisitor>(PhantomData); impl<'de, A: Copy + Array> 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", A::CAPACITY) } 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)) } } arrayvec-0.5.2/src/char.rs010064400017500001750000000065161374460075100136040ustar 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 use std::ptr; // UTF-8 ranges and tags for encoding characters const TAG_CONT: u8 = 0b1000_0000; const TAG_TWO_B: u8 = 0b1100_0000; const TAG_THREE_B: u8 = 0b1110_0000; const TAG_FOUR_B: u8 = 0b1111_0000; const MAX_ONE_B: u32 = 0x80; const MAX_TWO_B: u32 = 0x800; const MAX_THREE_B: u32 = 0x10000; /// Placeholder pub struct EncodeUtf8Error; #[inline] unsafe fn write(ptr: *mut u8, index: usize, byte: u8) { ptr::write(ptr.add(index), byte) } /// Encode a char into buf using UTF-8. /// /// On success, return the byte length of the encoding (1, 2, 3 or 4).
/// 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 { write(ptr, 0, code as u8); return Ok(1); } else if code < MAX_TWO_B && len >= 2 { write(ptr, 0, (code >> 6 & 0x1F) as u8 | TAG_TWO_B); write(ptr, 1, (code & 0x3F) as u8 | TAG_CONT); return Ok(2); } else if code < MAX_THREE_B && len >= 3 { write(ptr, 0, (code >> 12 & 0x0F) as u8 | TAG_THREE_B); write(ptr, 1, (code >> 6 & 0x3F) as u8 | TAG_CONT); write(ptr, 2, (code & 0x3F) as u8 | TAG_CONT); return Ok(3); } else if len >= 4 { write(ptr, 0, (code >> 18 & 0x07) as u8 | TAG_FOUR_B); write(ptr, 1, (code >> 12 & 0x3F) as u8 | TAG_CONT); write(ptr, 2, (code >> 6 & 0x3F) as u8 | TAG_CONT); write(ptr, 3, (code & 0x3F) as u8 | TAG_CONT); return Ok(4); }; Err(EncodeUtf8Error) } #[test] #[cfg_attr(miri, ignore)] // Miri is too slow fn test_encode_utf8() { // Test that all codepoints are encoded correctly let mut data = [0u8; 16]; for codepoint in 0..=(std::char::MAX as u32) { if let Some(ch) = std::char::from_u32(codepoint) { for elt in &mut data { *elt = 0; } let ptr = data.as_mut_ptr(); let len = data.len(); unsafe { let res = encode_utf8(ch, ptr, len).ok().unwrap(); assert_eq!(res, ch.len_utf8()); } let string = std::str::from_utf8(&data).unwrap(); assert_eq!(string.chars().next(), Some(ch)); } } } #[test] fn test_encode_utf8_oob() { // test that we report oob if the buffer is too short let mut data = [0u8; 16]; let chars = ['a', 'α', '�', '𐍈']; for (len, &ch) in (1..=4).zip(&chars) { assert_eq!(len, ch.len_utf8(), "Len of ch={}", ch); let ptr = data.as_mut_ptr(); unsafe { assert!(matches::matches!(encode_utf8(ch, ptr, len - 1), Err(_))); assert!(matches::matches!(encode_utf8(ch, ptr, len), Ok(_))); } } } arrayvec-0.5.2/src/errors.rs010064400017500001750000000022431374460075100141740ustar 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 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.5.2/src/lib.rs010064400017500001750000001025551374460075100134350ustar 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 //! - `array-sizes-33-128`, `array-sizes-129-255` //! - Optional //! - Enable more array sizes (see [Array] for more information) //! //! - `unstable-const-fn` //! - Optional //! - Makes [`ArrayVec::new`] and [`ArrayString::new`] `const fn`s, //! using the nightly `const_fn` feature. //! - Unstable and requires nightly. //! //! ## Rust Version //! //! This version of arrayvec requires Rust 1.36 or later. //! #![doc(html_root_url="https://docs.rs/arrayvec/0.4/")] #![cfg_attr(not(feature="std"), no_std)] #![cfg_attr(feature="unstable-const-fn", feature(const_fn))] #[cfg(feature="serde")] extern crate serde; #[cfg(not(feature="std"))] extern crate core as std; use std::cmp; use std::iter; use std::mem; use std::ops::{Bound, Deref, DerefMut, RangeBounds}; use std::ptr; use std::slice; // extra traits use std::borrow::{Borrow, BorrowMut}; use std::hash::{Hash, Hasher}; use std::fmt; #[cfg(feature="std")] use std::io; mod maybe_uninit; use crate::maybe_uninit::MaybeUninit; #[cfg(feature="serde")] use serde::{Serialize, Deserialize, Serializer, Deserializer}; mod array; mod array_string; mod char; mod errors; pub use crate::array::Array; use crate::array::Index; pub use crate::array_string::ArrayString; pub use crate::errors::CapacityError; /// A vector with a fixed capacity. /// /// The `ArrayVec` is a vector backed by a fixed size array. It keeps track of /// the number of initialized elements. /// /// The vector is a contiguous value that you can store directly on the stack /// if needed. /// /// It offers a simple API but also dereferences to a slice, so /// that the full slice API is available. /// /// ArrayVec can be converted into a by value iterator. pub struct ArrayVec { xs: MaybeUninit
, len: A::Index, } 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 { /// Create a new empty `ArrayVec`. /// /// Capacity is inferred from the type parameter. /// /// ``` /// use arrayvec::ArrayVec; /// /// let mut array = ArrayVec::<[_; 16]>::new(); /// array.push(1); /// array.push(2); /// assert_eq!(&array[..], &[1, 2]); /// assert_eq!(array.capacity(), 16); /// ``` #[cfg(not(feature="unstable-const-fn"))] pub fn new() -> ArrayVec { unsafe { ArrayVec { xs: MaybeUninit::uninitialized(), len: Index::ZERO } } } #[cfg(feature="unstable-const-fn")] pub const fn new() -> ArrayVec { unsafe { ArrayVec { xs: MaybeUninit::uninitialized(), len: Index::ZERO } } } /// Return the number of elements in the `ArrayVec`. /// /// ``` /// use arrayvec::ArrayVec; /// /// let mut array = ArrayVec::from([1, 2, 3]); /// array.pop(); /// assert_eq!(array.len(), 2); /// ``` #[inline] pub fn len(&self) -> usize { self.len.to_usize() } /// Returns whether the `ArrayVec` is empty. /// /// ``` /// use arrayvec::ArrayVec; /// /// let mut array = ArrayVec::from([1]); /// array.pop(); /// assert_eq!(array.is_empty(), true); /// ``` #[inline] pub fn is_empty(&self) -> bool { self.len() == 0 } /// Return the capacity of the `ArrayVec`. /// /// ``` /// use arrayvec::ArrayVec; /// /// let array = ArrayVec::from([1, 2, 3]); /// assert_eq!(array.capacity(), 3); /// ``` #[inline(always)] pub fn capacity(&self) -> usize { A::CAPACITY } /// Return if the `ArrayVec` is completely filled. /// /// ``` /// use arrayvec::ArrayVec; /// /// let mut array = ArrayVec::<[_; 1]>::new(); /// assert!(!array.is_full()); /// array.push(1); /// assert!(array.is_full()); /// ``` pub fn is_full(&self) -> bool { self.len() == self.capacity() } /// Returns the capacity left in the `ArrayVec`. /// /// ``` /// use arrayvec::ArrayVec; /// /// let mut array = ArrayVec::from([1, 2, 3]); /// array.pop(); /// assert_eq!(array.remaining_capacity(), 1); /// ``` pub fn remaining_capacity(&self) -> usize { self.capacity() - self.len() } /// Push `element` to the end of the vector. /// /// ***Panics*** if the vector is already full. /// /// ``` /// use arrayvec::ArrayVec; /// /// let mut array = ArrayVec::<[_; 2]>::new(); /// /// array.push(1); /// array.push(2); /// /// assert_eq!(&array[..], &[1, 2]); /// ``` pub fn push(&mut self, element: A::Item) { self.try_push(element).unwrap() } /// Push `element` to the end of the vector. /// /// Return `Ok` if the push succeeds, or return an error if the vector /// is already full. /// /// ``` /// use arrayvec::ArrayVec; /// /// let mut array = ArrayVec::<[_; 2]>::new(); /// /// let push1 = array.try_push(1); /// let push2 = array.try_push(2); /// /// assert!(push1.is_ok()); /// assert!(push2.is_ok()); /// /// assert_eq!(&array[..], &[1, 2]); /// /// let overflow = array.try_push(3); /// /// assert!(overflow.is_err()); /// ``` pub fn try_push(&mut self, element: A::Item) -> Result<(), CapacityError> { if self.len() < A::CAPACITY { unsafe { self.push_unchecked(element); } Ok(()) } else { Err(CapacityError::new(element)) } } /// Push `element` to the end of the vector without checking the capacity. /// /// It is up to the caller to ensure the capacity of the vector is /// sufficiently large. /// /// This method uses *debug assertions* to check that the arrayvec is not full. /// /// ``` /// use arrayvec::ArrayVec; /// /// let mut array = ArrayVec::<[_; 2]>::new(); /// /// if array.len() + 2 <= array.capacity() { /// unsafe { /// array.push_unchecked(1); /// array.push_unchecked(2); /// } /// } /// /// assert_eq!(&array[..], &[1, 2]); /// ``` pub unsafe fn push_unchecked(&mut self, element: A::Item) { let len = self.len(); debug_assert!(len < A::CAPACITY); ptr::write(self.get_unchecked_ptr(len), element); self.set_len(len + 1); } /// Get pointer to where element at `index` would be unsafe fn get_unchecked_ptr(&mut self, index: usize) -> *mut A::Item { self.xs.ptr_mut().add(index) } /// Insert `element` at position `index`. /// /// Shift up all elements after `index`. /// /// It is an error if the index is greater than the length or if the /// arrayvec is full. /// /// ***Panics*** if the array is full or the `index` is out of bounds. See /// `try_insert` for fallible version. /// /// ``` /// use arrayvec::ArrayVec; /// /// let mut array = ArrayVec::<[_; 2]>::new(); /// /// array.insert(0, "x"); /// array.insert(0, "y"); /// assert_eq!(&array[..], &["y", "x"]); /// /// ``` pub fn insert(&mut self, index: usize, element: A::Item) { self.try_insert(index, element).unwrap() } /// Insert `element` at position `index`. /// /// Shift up all elements after `index`; the `index` must be less than /// or equal to the length. /// /// Returns an error if vector is already at full capacity. /// /// ***Panics*** `index` is out of bounds. /// /// ``` /// use arrayvec::ArrayVec; /// /// let mut array = ArrayVec::<[_; 2]>::new(); /// /// assert!(array.try_insert(0, "x").is_ok()); /// assert!(array.try_insert(0, "y").is_ok()); /// assert!(array.try_insert(0, "z").is_err()); /// assert_eq!(&array[..], &["y", "x"]); /// /// ``` pub fn try_insert(&mut self, index: usize, element: A::Item) -> Result<(), CapacityError> { 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 { if self.len() == 0 { return None; } unsafe { let new_len = self.len() - 1; self.set_len(new_len); Some(ptr::read(self.get_unchecked_ptr(new_len))) } } /// Remove the element at `index` and swap the last element into its place. /// /// This operation is O(1). /// /// Return the *element* if the index is in bounds, else panic. /// /// ***Panics*** if the `index` is out of bounds. /// /// ``` /// use arrayvec::ArrayVec; /// /// let mut array = ArrayVec::from([1, 2, 3]); /// /// assert_eq!(array.swap_remove(0), 1); /// assert_eq!(&array[..], &[3, 2]); /// /// assert_eq!(array.swap_remove(1), 2); /// assert_eq!(&array[..], &[3]); /// ``` pub fn swap_remove(&mut self, index: usize) -> A::Item { self.swap_pop(index) .unwrap_or_else(|| { panic_oob!("swap_remove", index, self.len()) }) } /// Remove the element at `index` and swap the last element into its place. /// /// This is a checked version of `.swap_remove`. /// This operation is O(1). /// /// Return `Some(` *element* `)` if the index is in bounds, else `None`. /// /// ``` /// use arrayvec::ArrayVec; /// /// let mut array = ArrayVec::from([1, 2, 3]); /// /// assert_eq!(array.swap_pop(0), Some(1)); /// assert_eq!(&array[..], &[3, 2]); /// /// assert_eq!(array.swap_pop(10), None); /// ``` pub fn swap_pop(&mut self, index: usize) -> Option { let len = self.len(); if index >= len { return None; } self.swap(index, len - 1); self.pop() } /// Remove the element at `index` and shift down the following elements. /// /// The `index` must be strictly less than the length of the vector. /// /// ***Panics*** if the `index` is out of bounds. /// /// ``` /// use arrayvec::ArrayVec; /// /// let mut array = ArrayVec::from([1, 2, 3]); /// /// let removed_elt = array.remove(0); /// assert_eq!(removed_elt, 1); /// assert_eq!(&array[..], &[2, 3]); /// ``` pub fn remove(&mut self, index: usize) -> A::Item { self.pop_at(index) .unwrap_or_else(|| { panic_oob!("remove", index, self.len()) }) } /// Remove the element at `index` and shift down the following elements. /// /// This is a checked version of `.remove(index)`. Returns `None` if there /// is no element at `index`. Otherwise, return the element inside `Some`. /// /// ``` /// use arrayvec::ArrayVec; /// /// let mut array = ArrayVec::from([1, 2, 3]); /// /// assert!(array.pop_at(0).is_some()); /// assert_eq!(&array[..], &[2, 3]); /// /// assert!(array.pop_at(2).is_none()); /// assert!(array.pop_at(10).is_none()); /// ``` pub fn pop_at(&mut self, index: usize) -> Option { if index >= self.len() { None } else { self.drain(index..index + 1).next() } } /// Shortens the vector, keeping the first `len` elements and dropping /// the rest. /// /// If `len` is greater than the vector’s current length this has no /// effect. /// /// ``` /// use arrayvec::ArrayVec; /// /// let mut array = ArrayVec::from([1, 2, 3, 4, 5]); /// array.truncate(3); /// assert_eq!(&array[..], &[1, 2, 3]); /// array.truncate(4); /// assert_eq!(&array[..], &[1, 2, 3]); /// ``` pub fn truncate(&mut self, new_len: usize) { unsafe { if new_len < self.len() { let tail: *mut [_] = &mut self[new_len..]; self.len = Index::from(new_len); ptr::drop_in_place(tail); } } } /// Remove all elements in the vector. pub fn clear(&mut self) { self.truncate(0) } /// Retains only the elements specified by the predicate. /// /// In other words, remove all elements `e` such that `f(&mut e)` returns false. /// This method operates in place and preserves the order of the retained /// elements. /// /// ``` /// use arrayvec::ArrayVec; /// /// let mut array = ArrayVec::from([1, 2, 3, 4]); /// array.retain(|x| *x & 1 != 0 ); /// assert_eq!(&array[..], &[1, 3]); /// ``` pub fn retain(&mut self, mut f: F) where F: FnMut(&mut A::Item) -> bool { let len = self.len(); let mut del = 0; { let v = &mut **self; for i in 0..len { if !f(&mut v[i]) { del += 1; } else if del > 0 { v.swap(i - del, i); } } } if del > 0 { self.drain(len - del..); } } /// Set the vector’s length without dropping or moving out elements /// /// This method is `unsafe` because it changes the notion of the /// number of “valid” elements in the vector. Use with care. /// /// This method uses *debug assertions* to check that `length` is /// not greater than the capacity. pub unsafe fn set_len(&mut self, length: usize) { debug_assert!(length <= self.capacity()); self.len = Index::from(length); } /// Copy and appends all elements in a slice to the `ArrayVec`. /// /// ``` /// use arrayvec::ArrayVec; /// /// let mut vec: ArrayVec<[usize; 10]> = ArrayVec::new(); /// vec.push(1); /// vec.try_extend_from_slice(&[2, 3]).unwrap(); /// assert_eq!(&vec[..], &[1, 2, 3]); /// ``` /// /// # Errors /// /// This method will return an error if the capacity left (see /// [`remaining_capacity`]) is smaller then the length of the provided /// slice. /// /// [`remaining_capacity`]: #method.remaining_capacity pub fn try_extend_from_slice(&mut self, other: &[A::Item]) -> Result<(), CapacityError> where A::Item: Copy, { if self.remaining_capacity() < other.len() { return Err(CapacityError::new(())); } let self_len = self.len(); let other_len = other.len(); unsafe { let dst = self.xs.ptr_mut().add(self_len); ptr::copy_nonoverlapping(other.as_ptr(), dst, other_len); self.set_len(self_len + other_len); } Ok(()) } /// Create a draining iterator that removes the specified range in the vector /// and yields the removed items from start to end. The element range is /// removed even if the iterator is not consumed until the end. /// /// Note: It is unspecified how many elements are removed from the vector, /// if the `Drain` value is leaked. /// /// **Panics** if the starting point is greater than the end point or if /// the end point is greater than the length of the vector. /// /// ``` /// use arrayvec::ArrayVec; /// /// let mut v = ArrayVec::from([1, 2, 3]); /// let u: ArrayVec<[_; 3]> = v.drain(0..2).collect(); /// assert_eq!(&v[..], &[3]); /// assert_eq!(&u[..], &[1, 2]); /// ``` pub fn drain(&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 = Index::from(start); unsafe { Drain { tail_start: end, tail_len: len - end, iter: (*range_slice).iter(), vec: self as *mut _, } } } /// Return the inner fixed size array, if it is full to its capacity. /// /// Return an `Ok` value with the array if length equals capacity, /// return an `Err` with self otherwise. pub fn into_inner(self) -> Result { if self.len() < self.capacity() { Err(self) } else { unsafe { let array = ptr::read(self.xs.ptr() as *const A); mem::forget(self); Ok(array) } } } /// Dispose of `self` (same as drop) #[deprecated="Use std::mem::drop instead, if at all needed."] pub fn dispose(mut self) { self.clear(); mem::forget(self); } /// Return a slice containing all elements of the vector. pub fn as_slice(&self) -> &[A::Item] { self } /// Return a mutable slice containing all elements of the vector. pub fn as_mut_slice(&mut self) -> &mut [A::Item] { self } /// Return a raw pointer to the vector's buffer. pub fn as_ptr(&self) -> *const A::Item { self.xs.ptr() } /// Return a raw mutable pointer to the vector's buffer. pub fn as_mut_ptr(&mut self) -> *mut A::Item { self.xs.ptr_mut() } } impl Deref for ArrayVec { type Target = [A::Item]; #[inline] fn deref(&self) -> &[A::Item] { unsafe { slice::from_raw_parts(self.xs.ptr(), self.len()) } } } impl DerefMut for ArrayVec { #[inline] fn deref_mut(&mut self) -> &mut [A::Item] { let len = self.len(); unsafe { slice::from_raw_parts_mut(self.xs.ptr_mut(), len) } } } /// Create an `ArrayVec` from an array. /// /// ``` /// use arrayvec::ArrayVec; /// /// let mut array = ArrayVec::from([1, 2, 3]); /// assert_eq!(array.len(), 3); /// assert_eq!(array.capacity(), 3); /// ``` impl From for ArrayVec { fn from(array: A) -> Self { ArrayVec { xs: MaybeUninit::from(array), len: Index::from(A::CAPACITY) } } } /// Try to create an `ArrayVec` from a slice. This will return an error if the slice was too big to /// fit. /// /// ``` /// use arrayvec::ArrayVec; /// use std::convert::TryInto as _; /// /// let array: ArrayVec<[_; 4]> = (&[1, 2, 3] as &[_]).try_into().unwrap(); /// assert_eq!(array.len(), 3); /// assert_eq!(array.capacity(), 4); /// ``` impl std::convert::TryFrom<&[A::Item]> for ArrayVec where A::Item: Clone, { type Error = CapacityError; fn try_from(slice: &[A::Item]) -> Result { if A::CAPACITY < slice.len() { Err(CapacityError::new(())) } else { let mut array = Self::new(); array.extend(slice.iter().cloned()); Ok(array) } } } /// Iterate the `ArrayVec` with references to each element. /// /// ``` /// use arrayvec::ArrayVec; /// /// let array = ArrayVec::from([1, 2, 3]); /// /// for elt in &array { /// // ... /// } /// ``` impl<'a, A: Array> IntoIterator for &'a ArrayVec { type Item = &'a A::Item; type IntoIter = slice::Iter<'a, A::Item>; fn into_iter(self) -> Self::IntoIter { self.iter() } } /// Iterate the `ArrayVec` with mutable references to each element. /// /// ``` /// use arrayvec::ArrayVec; /// /// let mut array = ArrayVec::from([1, 2, 3]); /// /// for elt in &mut array { /// // ... /// } /// ``` impl<'a, A: Array> IntoIterator for &'a mut ArrayVec { type Item = &'a mut A::Item; type IntoIter = slice::IterMut<'a, A::Item>; fn into_iter(self) -> Self::IntoIter { self.iter_mut() } } /// Iterate the `ArrayVec` with each element by value. /// /// The vector is consumed by this operation. /// /// ``` /// use arrayvec::ArrayVec; /// /// for elt in ArrayVec::from([1, 2, 3]) { /// // ... /// } /// ``` impl IntoIterator for ArrayVec { type Item = A::Item; type IntoIter = IntoIter; fn into_iter(self) -> IntoIter { IntoIter { index: Index::from(0), v: self, } } } /// By-value iterator for `ArrayVec`. pub struct IntoIter { index: A::Index, v: ArrayVec, } impl Iterator for IntoIter { type Item = A::Item; fn next(&mut self) -> Option { if self.index == self.v.len { None } else { unsafe { let index = self.index.to_usize(); self.index = Index::from(index + 1); Some(ptr::read(self.v.get_unchecked_ptr(index))) } } } fn size_hint(&self) -> (usize, Option) { let len = self.v.len() - self.index.to_usize(); (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.to_usize(); let len = self.v.len(); unsafe { self.v.set_len(0); let elements = slice::from_raw_parts_mut( self.v.get_unchecked_ptr(index), len - index); ptr::drop_in_place(elements); } } } impl Clone for IntoIter where A::Item: Clone, { fn clone(&self) -> IntoIter { self.v[self.index.to_usize()..] .iter() .cloned() .collect::>() .into_iter() } } impl fmt::Debug for IntoIter where A::Item: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list() .entries(&self.v[self.index.to_usize()..]) .finish() } } /// A draining iterator for `ArrayVec`. pub struct Drain<'a, A> where A: Array, A::Item: 'a, { /// Index of tail to preserve tail_start: usize, /// Length of tail tail_len: usize, /// Current remaining range to remove iter: slice::Iter<'a, A::Item>, vec: *mut ArrayVec, } unsafe impl<'a, A: Array + Sync> Sync for Drain<'a, A> {} unsafe impl<'a, A: Array + Send> Send for Drain<'a, A> {} impl<'a, A: Array> Iterator for Drain<'a, A> where A::Item: 'a, { type Item = A::Item; fn next(&mut self) -> Option { self.iter.next().map(|elt| unsafe { ptr::read(elt as *const _) } ) } fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } impl<'a, A: Array> DoubleEndedIterator for Drain<'a, A> where A::Item: 'a, { fn next_back(&mut self) -> Option { self.iter.next_back().map(|elt| unsafe { ptr::read(elt as *const _) } ) } } impl<'a, A: Array> ExactSizeIterator for Drain<'a, A> where A::Item: 'a {} impl<'a, A: Array> Drop for Drain<'a, A> where A::Item: 'a { fn drop(&mut self) { // len is currently 0 so panicking while dropping will not cause a double drop. // exhaust self first while let Some(_) = self.next() { } if self.tail_len > 0 { unsafe { let source_vec = &mut *self.vec; // memmove back untouched tail, update to new length let start = source_vec.len(); let tail = self.tail_start; let src = source_vec.as_ptr().add(tail); let dst = source_vec.as_mut_ptr().add(start); ptr::copy(src, dst, self.tail_len); source_vec.set_len(start + self.tail_len); } } } } struct ScopeExitGuard 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. /// /// Does not extract more items than there is space for. No error /// occurs if there are more iterator elements. impl Extend for ArrayVec { fn extend>(&mut self, iter: T) { let take = self.capacity() - self.len(); unsafe { let len = self.len(); let mut ptr = raw_ptr_add(self.as_mut_ptr(), len); let end_ptr = raw_ptr_add(ptr, take); // Keep the length in a separate variable, write it back on scope // exit. To help the compiler with alias analysis and stuff. // We update the length to handle panic in the iteration of the // user's iterator, without dropping any elements on the floor. let mut guard = ScopeExitGuard { value: &mut self.len, data: len, f: move |&len, self_len| { **self_len = Index::from(len); } }; let mut iter = iter.into_iter(); loop { if ptr == end_ptr { break; } if let Some(elt) = iter.next() { raw_ptr_write(ptr, elt); ptr = raw_ptr_add(ptr, 1); guard.data += 1; } else { break; } } } } } /// Rawptr add but uses arithmetic distance for ZST unsafe fn raw_ptr_add(ptr: *mut T, offset: usize) -> *mut T { if mem::size_of::() == 0 { // Special case for ZST (ptr as usize).wrapping_add(offset) as _ } else { ptr.add(offset) } } unsafe fn raw_ptr_write(ptr: *mut T, value: T) { if mem::size_of::() == 0 { /* nothing */ } else { ptr::write(ptr, value) } } /// Create an `ArrayVec` from an iterator. /// /// Does not extract more items than there is space for. No error /// occurs if there are more iterator elements. impl iter::FromIterator for ArrayVec { fn from_iter>(iter: T) -> Self { let mut array = ArrayVec::new(); array.extend(iter); array } } impl Clone for ArrayVec where A::Item: Clone { fn clone(&self) -> Self { self.iter().cloned().collect() } fn clone_from(&mut self, rhs: &Self) { // recursive case for the common prefix let prefix = cmp::min(self.len(), rhs.len()); self[..prefix].clone_from_slice(&rhs[..prefix]); if prefix < self.len() { // rhs was shorter for _ in 0..self.len() - prefix { self.pop(); } } else { let rhs_elems = rhs[self.len()..].iter().cloned(); self.extend(rhs_elems); } } } impl Hash for ArrayVec where A::Item: Hash { fn hash(&self, state: &mut H) { Hash::hash(&**self, state) } } impl PartialEq for ArrayVec where A::Item: PartialEq { fn eq(&self, other: &Self) -> bool { **self == **other } } impl PartialEq<[A::Item]> for ArrayVec where A::Item: PartialEq { fn eq(&self, other: &[A::Item]) -> bool { **self == *other } } impl Eq for ArrayVec where A::Item: Eq { } impl Borrow<[A::Item]> for ArrayVec { fn borrow(&self) -> &[A::Item] { self } } impl BorrowMut<[A::Item]> for ArrayVec { fn borrow_mut(&mut self) -> &mut [A::Item] { self } } impl AsRef<[A::Item]> for ArrayVec { fn as_ref(&self) -> &[A::Item] { self } } impl AsMut<[A::Item]> for ArrayVec { fn as_mut(&mut self) -> &mut [A::Item] { self } } impl fmt::Debug for ArrayVec where A::Item: 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 A::Item: PartialOrd { fn partial_cmp(&self, other: &ArrayVec) -> 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 A::Item: Ord { fn cmp(&self, other: &ArrayVec) -> 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>, A: Array> 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>, A: Array>(PhantomData<(&'de (), T, A)>); impl<'de, T: Deserialize<'de>, A: Array> Visitor<'de> for ArrayVecVisitor<'de, T, A> { type Value = ArrayVec; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "an array with no more than {} items", A::CAPACITY) } 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(A::CAPACITY + 1, &self)); } } Ok(values) } } deserializer.deserialize_seq(ArrayVecVisitor::(PhantomData)) } } arrayvec-0.5.2/src/maybe_uninit.rs010064400017500001750000000020751374460075100153460ustar 00000000000000 use crate::array::Array; use std::mem::MaybeUninit as StdMaybeUninit; #[derive(Copy)] pub struct MaybeUninit { inner: StdMaybeUninit, } impl Clone for MaybeUninit where T: Copy { fn clone(&self) -> Self { *self } } impl MaybeUninit { /// Create a new MaybeUninit with uninitialized interior pub const unsafe fn uninitialized() -> Self { MaybeUninit { inner: StdMaybeUninit::uninit() } } /// Create a new MaybeUninit from the value `v`. pub fn from(v: T) -> Self { MaybeUninit { inner: StdMaybeUninit::new(v) } } // Raw pointer casts written so that we don't reference or access the // uninitialized interior value /// Return a raw pointer to the start of the interior array pub fn ptr(&self) -> *const T::Item where T: Array { self.inner.as_ptr() as *const T::Item } /// Return a mut raw pointer to the start of the interior array pub fn ptr_mut(&mut self) -> *mut T::Item where T: Array { self.inner.as_mut_ptr() as *mut T::Item } } arrayvec-0.5.2/tests/serde.rs010064400017500001750000000034511374460075100143370ustar 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::<[u32; 0]>::new(); assert_tokens(&vec, &[ Token::Seq { len: Some(0) }, Token::SeqEnd, ]); } #[test] fn test_ser_de() { let mut vec = ArrayVec::<[u32; 3]>::new(); vec.push(20); vec.push(55); vec.push(123); assert_tokens(&vec, &[ Token::Seq { len: Some(3) }, Token::U32(20), Token::U32(55), Token::U32(123), Token::SeqEnd, ]); } #[test] fn test_de_too_large() { assert_de_tokens_error::>(&[ Token::Seq { len: Some(3) }, Token::U32(13), Token::U32(42), Token::U32(68), ], "invalid length 3, expected an array with no more than 2 items"); } } mod array_string { use arrayvec::ArrayString; use serde_test::{Token, assert_tokens, assert_de_tokens_error}; #[test] fn test_ser_de_empty() { let string = ArrayString::<[u8; 0]>::new(); assert_tokens(&string, &[ Token::Str(""), ]); } #[test] fn test_ser_de() { let string = ArrayString::<[u8; 9]>::from("1234 abcd") .expect("expected exact specified capacity to be enough"); assert_tokens(&string, &[ Token::Str("1234 abcd"), ]); } #[test] fn test_de_too_large() { assert_de_tokens_error::>(&[ Token::Str("afd") ], "invalid length 3, expected a string no more than 2 bytes long"); } } arrayvec-0.5.2/tests/tests.rs010064400017500001750000000405071374460075100144020ustar 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<[Vec; 3]> = ArrayVec::new(); vec.push(vec![1, 2, 3, 4]); vec.push(vec![10]); vec.push(vec![-1, 13, -2]); for elt in &vec { assert_eq!(elt.iter().fold(0, Add::add), 10); } let sum_len = vec.into_iter().map(|x| x.len()).fold(0, Add::add); assert_eq!(sum_len, 8); } #[test] fn test_capacity_left() { let mut vec: ArrayVec<[usize; 4]> = ArrayVec::new(); assert_eq!(vec.remaining_capacity(), 4); vec.push(1); assert_eq!(vec.remaining_capacity(), 3); vec.push(2); assert_eq!(vec.remaining_capacity(), 2); vec.push(3); assert_eq!(vec.remaining_capacity(), 1); vec.push(4); assert_eq!(vec.remaining_capacity(), 0); } #[test] fn test_extend_from_slice() { let mut vec: ArrayVec<[usize; 10]> = ArrayVec::new(); vec.try_extend_from_slice(&[1, 2, 3]).unwrap(); assert_eq!(vec.len(), 3); assert_eq!(&vec[..], &[1, 2, 3]); assert_eq!(vec.pop(), Some(3)); assert_eq!(&vec[..], &[1, 2]); } #[test] fn test_extend_from_slice_error() { let mut vec: ArrayVec<[usize; 10]> = ArrayVec::new(); vec.try_extend_from_slice(&[1, 2, 3]).unwrap(); let res = vec.try_extend_from_slice(&[0; 8]); assert_matches!(res, Err(_)); let mut vec: ArrayVec<[usize; 0]> = ArrayVec::new(); let res = vec.try_extend_from_slice(&[0; 1]); assert_matches!(res, Err(_)); } #[test] fn test_try_from_slice_error() { use arrayvec::ArrayVec; use std::convert::TryInto as _; let res: Result, _> = (&[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::<[Bump; 128]>::new(); array.push(Bump(flag)); array.push(Bump(flag)); } assert_eq!(flag.get(), 2); // test something with the nullable pointer optimization flag.set(0); { let mut array = ArrayVec::<[_; 3]>::new(); array.push(vec![Bump(flag)]); array.push(vec![Bump(flag), Bump(flag)]); array.push(vec![]); let push4 = array.try_push(vec![Bump(flag)]); assert_eq!(flag.get(), 0); drop(push4); assert_eq!(flag.get(), 1); drop(array.pop()); assert_eq!(flag.get(), 1); drop(array.pop()); assert_eq!(flag.get(), 3); } assert_eq!(flag.get(), 4); // test into_inner flag.set(0); { let mut array = ArrayVec::<[_; 3]>::new(); array.push(Bump(flag)); array.push(Bump(flag)); array.push(Bump(flag)); let inner = array.into_inner(); assert!(inner.is_ok()); assert_eq!(flag.get(), 0); drop(inner); assert_eq!(flag.get(), 3); } // test cloning into_iter flag.set(0); { let mut array = ArrayVec::<[_; 3]>::new(); array.push(Bump(flag)); array.push(Bump(flag)); array.push(Bump(flag)); let mut iter = array.into_iter(); assert_eq!(flag.get(), 0); iter.next(); assert_eq!(flag.get(), 1); let clone = iter.clone(); assert_eq!(flag.get(), 1); drop(clone); assert_eq!(flag.get(), 3); drop(iter); assert_eq!(flag.get(), 5); } } #[test] fn test_drop_panics() { use std::cell::Cell; use std::panic::catch_unwind; use std::panic::AssertUnwindSafe; let flag = &Cell::new(0); struct Bump<'a>(&'a Cell); // Panic in the first drop impl<'a> Drop for Bump<'a> { fn drop(&mut self) { let n = self.0.get(); self.0.set(n + 1); if n == 0 { panic!("Panic in Bump's drop"); } } } // check if rust is new enough flag.set(0); { let array = vec![Bump(flag), Bump(flag)]; let res = catch_unwind(AssertUnwindSafe(|| { drop(array); })); assert!(res.is_err()); } if flag.get() != 2 { println!("test_drop_panics: skip, this version of Rust doesn't continue in drop_in_place"); return; } flag.set(0); { let mut array = ArrayVec::<[Bump; 128]>::new(); array.push(Bump(flag)); array.push(Bump(flag)); array.push(Bump(flag)); let res = catch_unwind(AssertUnwindSafe(|| { drop(array); })); assert!(res.is_err()); } // Check that all the elements drop, even if the first drop panics. assert_eq!(flag.get(), 3); flag.set(0); { let mut array = ArrayVec::<[Bump; 16]>::new(); array.push(Bump(flag)); array.push(Bump(flag)); array.push(Bump(flag)); array.push(Bump(flag)); array.push(Bump(flag)); let i = 2; let tail_len = array.len() - i; let res = catch_unwind(AssertUnwindSafe(|| { array.truncate(i); })); assert!(res.is_err()); // Check that all the tail elements drop, even if the first drop panics. assert_eq!(flag.get(), tail_len as i32); } } #[test] fn test_extend() { let mut range = 0..10; let mut array: ArrayVec<[_; 5]> = range.by_ref().collect(); assert_eq!(&array[..], &[0, 1, 2, 3, 4]); assert_eq!(range.next(), Some(5)); array.extend(range.by_ref()); assert_eq!(range.next(), Some(6)); let mut array: ArrayVec<[_; 10]> = (0..3).collect(); assert_eq!(&array[..], &[0, 1, 2]); array.extend(3..5); assert_eq!(&array[..], &[0, 1, 2, 3, 4]); } #[test] fn test_is_send_sync() { let data = ArrayVec::<[Vec; 5]>::new(); &data as &dyn Send; &data as &dyn Sync; } #[test] fn test_compact_size() { // Future rust will kill these drop flags! // 4 elements size + 1 len + 1 enum tag + [1 drop flag] type ByteArray = ArrayVec<[u8; 4]>; println!("{}", mem::size_of::()); assert!(mem::size_of::() <= 8); // 1 enum tag + 1 drop flag type EmptyArray = ArrayVec<[u8; 0]>; println!("{}", mem::size_of::()); assert!(mem::size_of::() <= 2); // 12 element size + 1 enum tag + 3 padding + 1 len + 1 drop flag + 2 padding type QuadArray = ArrayVec<[u32; 3]>; println!("{}", mem::size_of::()); assert!(mem::size_of::() <= 24); } #[test] fn test_still_works_with_option_arrayvec() { type RefArray = ArrayVec<[&'static i32; 2]>; let array = Some(RefArray::new()); assert!(array.is_some()); println!("{:?}", array); } #[test] fn test_drain() { let mut v = ArrayVec::from([0; 8]); v.pop(); v.drain(0..7); assert_eq!(&v[..], &[]); v.extend(0..); v.drain(1..4); assert_eq!(&v[..], &[0, 4, 5, 6, 7]); let u: ArrayVec<[_; 3]> = v.drain(1..4).rev().collect(); assert_eq!(&u[..], &[6, 5, 4]); assert_eq!(&v[..], &[0, 7]); v.drain(..); assert_eq!(&v[..], &[]); } #[test] fn test_drain_range_inclusive() { let mut v = ArrayVec::from([0; 8]); v.drain(0..=7); assert_eq!(&v[..], &[]); v.extend(0..); v.drain(1..=4); assert_eq!(&v[..], &[0, 5, 6, 7]); let u: ArrayVec<[_; 3]> = v.drain(1..=2).rev().collect(); assert_eq!(&u[..], &[6, 5]); assert_eq!(&v[..], &[0, 7]); v.drain(..); assert_eq!(&v[..], &[]); } #[test] #[should_panic] fn test_drain_range_inclusive_oob() { let mut v = ArrayVec::from([0; 0]); v.drain(0..=0); } #[test] fn test_retain() { let mut v = ArrayVec::from([0; 8]); for (i, elt) in v.iter_mut().enumerate() { *elt = i; } v.retain(|_| true); assert_eq!(&v[..], &[0, 1, 2, 3, 4, 5, 6, 7]); v.retain(|elt| { *elt /= 2; *elt % 2 == 0 }); assert_eq!(&v[..], &[0, 0, 2, 2]); v.retain(|_| false); assert_eq!(&v[..], &[]); } #[test] #[should_panic] fn test_drain_oob() { let mut v = ArrayVec::from([0; 8]); v.pop(); v.drain(0..8); } #[test] #[should_panic] fn test_drop_panic() { struct DropPanic; impl Drop for DropPanic { fn drop(&mut self) { panic!("drop"); } } let mut array = ArrayVec::<[DropPanic; 1]>::new(); array.push(DropPanic); } #[test] #[should_panic] fn test_drop_panic_into_iter() { struct DropPanic; impl Drop for DropPanic { fn drop(&mut self) { panic!("drop"); } } let mut array = ArrayVec::<[DropPanic; 1]>::new(); array.push(DropPanic); array.into_iter(); } #[test] fn test_insert() { let mut v = ArrayVec::from([]); assert_matches!(v.try_push(1), Err(_)); let mut v = ArrayVec::<[_; 3]>::new(); v.insert(0, 0); v.insert(1, 1); //let ret1 = v.try_insert(3, 3); //assert_matches!(ret1, Err(InsertError::OutOfBounds(_))); assert_eq!(&v[..], &[0, 1]); v.insert(2, 2); assert_eq!(&v[..], &[0, 1, 2]); let ret2 = v.try_insert(1, 9); assert_eq!(&v[..], &[0, 1, 2]); assert_matches!(ret2, Err(_)); let mut v = ArrayVec::from([2]); assert_matches!(v.try_insert(0, 1), Err(CapacityError { .. })); assert_matches!(v.try_insert(1, 1), Err(CapacityError { .. })); //assert_matches!(v.try_insert(2, 1), Err(CapacityError { .. })); } #[test] fn test_into_inner_1() { let mut v = ArrayVec::from([1, 2]); v.pop(); let u = v.clone(); assert_eq!(v.into_inner(), Err(u)); } #[test] fn test_into_inner_2() { let mut v = ArrayVec::<[String; 4]>::new(); v.push("a".into()); v.push("b".into()); v.push("c".into()); v.push("d".into()); assert_eq!(v.into_inner().unwrap(), ["a", "b", "c", "d"]); } #[test] fn test_into_inner_3_() { let mut v = ArrayVec::<[i32; 4]>::new(); v.extend(1..); assert_eq!(v.into_inner().unwrap(), [1, 2, 3, 4]); } #[cfg(feature="std")] #[test] fn test_write() { use std::io::Write; let mut v = ArrayVec::<[_; 8]>::new(); write!(&mut v, "\x01\x02\x03").unwrap(); assert_eq!(&v[..], &[1, 2, 3]); let r = v.write(&[9; 16]).unwrap(); assert_eq!(r, 5); assert_eq!(&v[..], &[1, 2, 3, 9, 9, 9, 9, 9]); } #[test] fn array_clone_from() { let mut v = ArrayVec::<[_; 4]>::new(); v.push(vec![1, 2]); v.push(vec![3, 4, 5]); v.push(vec![6]); let reference = v.to_vec(); let mut u = ArrayVec::<[_; 4]>::new(); u.clone_from(&v); assert_eq!(&u, &reference[..]); let mut t = ArrayVec::<[_; 4]>::new(); t.push(vec![97]); t.push(vec![]); t.push(vec![5, 6, 2]); t.push(vec![2]); t.clone_from(&v); assert_eq!(&t, &reference[..]); t.clear(); t.clone_from(&v); assert_eq!(&t, &reference[..]); } #[cfg(feature="std")] #[test] fn test_string() { use std::error::Error; let text = "hello world"; let mut s = ArrayString::<[_; 16]>::new(); s.try_push_str(text).unwrap(); assert_eq!(&s, text); assert_eq!(text, &s); // Make sure Hash / Eq / Borrow match up so we can use HashMap let mut map = HashMap::new(); map.insert(s, 1); assert_eq!(map[text], 1); let mut t = ArrayString::<[_; 2]>::new(); assert!(t.try_push_str(text).is_err()); assert_eq!(&t, ""); t.push_str("ab"); // DerefMut let tmut: &mut str = &mut t; assert_eq!(tmut, "ab"); // Test Error trait / try let t = || -> Result<(), Box> { 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::<[String; 4]>::new(); let s = String::from; v.push(s("a")); v.push(s("b")); v.push(s("c")); v.push(s("d")); assert_eq!(v.pop_at(4), None); assert_eq!(v.pop_at(1), Some(s("b"))); assert_eq!(v.pop_at(1), Some(s("c"))); assert_eq!(v.pop_at(2), None); assert_eq!(&v[..], &["a", "d"]); } #[test] fn test_sizes() { let v = ArrayVec::from([0u8; 1 << 16]); assert_eq!(vec![0u8; v.len()], &v[..]); } #[test] fn test_default() { use std::net; let s: ArrayString<[u8; 4]> = Default::default(); // Something without `Default` implementation. let v: ArrayVec<[net::TcpStream; 4]> = Default::default(); assert_eq!(s.len(), 0); assert_eq!(v.len(), 0); } #[cfg(feature="array-sizes-33-128")] #[test] fn test_sizes_33_128() { ArrayVec::from([0u8; 52]); ArrayVec::from([0u8; 127]); } #[cfg(feature="array-sizes-129-255")] #[test] fn test_sizes_129_255() { ArrayVec::from([0u8; 237]); ArrayVec::from([0u8; 255]); } #[test] fn test_extend_zst() { let mut range = 0..10; #[derive(Copy, Clone, PartialEq, Debug)] struct Z; // Zero sized type let mut array: ArrayVec<[_; 5]> = range.by_ref().map(|_| Z).collect(); assert_eq!(&array[..], &[Z; 5]); assert_eq!(range.next(), Some(5)); array.extend(range.by_ref().map(|_| Z)); assert_eq!(range.next(), Some(6)); let mut array: ArrayVec<[_; 10]> = (0..3).map(|_| Z).collect(); assert_eq!(&array[..], &[Z; 3]); array.extend((3..5).map(|_| Z)); assert_eq!(&array[..], &[Z; 5]); assert_eq!(array.len(), 5); }