├── .github └── workflows │ └── ci.yml ├── .gitignore ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── benches ├── arraystring.rs └── extend.rs ├── src ├── array_string.rs ├── arrayvec.rs ├── arrayvec_impl.rs ├── char.rs ├── errors.rs ├── lib.rs └── utils.rs └── tests ├── borsh.rs ├── serde.rs └── tests.rs /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: [ master ] 4 | pull_request: 5 | branches: [ master ] 6 | 7 | name: Continuous integration 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | CARGO_INCREMENTAL: 0 12 | 13 | jobs: 14 | tests: 15 | runs-on: ubuntu-latest 16 | continue-on-error: ${{ matrix.experimental }} 17 | strategy: 18 | matrix: 19 | include: 20 | - rust: 1.51.0 # MSRV 21 | features: serde 22 | experimental: false 23 | # doctest of `ArrayVec::spare_capacity_mut` has MSRV 1.55 24 | test-args: --skip spare_capacity_mut 25 | - rust: 1.70.0 26 | features: serde 27 | experimental: false 28 | - rust: stable 29 | features: 30 | bench: true 31 | experimental: false 32 | - rust: beta 33 | features: serde 34 | experimental: false 35 | - rust: nightly 36 | features: serde, borsh, zeroize 37 | experimental: false 38 | 39 | steps: 40 | - uses: actions/checkout@v4 41 | - uses: dtolnay/rust-toolchain@master 42 | with: 43 | toolchain: ${{ matrix.rust }} 44 | - name: Pin versions for MSRV 45 | if: "${{ matrix.rust == '1.51.0' }}" 46 | run: | 47 | cargo update -p serde_test --precise 1.0.163 48 | cargo update -p serde --precise 1.0.69 49 | - name: Build 50 | run: | 51 | cargo build -v --no-default-features 52 | cargo build --verbose --features "${{ matrix.features }}" 53 | - name: Tests 54 | run: | 55 | cargo doc --verbose --features "${{ matrix.features }}" --no-deps 56 | cargo test --verbose --features "${{ matrix.features }}" -- ${{ matrix.test-args }} 57 | cargo test --release --verbose --features "${{ matrix.features }}" -- ${{ matrix.test-args }} 58 | - name: Test run benchmarks 59 | if: matrix.bench != '' 60 | run: cargo test -v --benches 61 | 62 | nostd: 63 | runs-on: ubuntu-latest 64 | continue-on-error: false 65 | strategy: 66 | matrix: 67 | include: 68 | - rust: stable 69 | target: thumbv6m-none-eabi 70 | features: zeroize 71 | 72 | name: nostd/${{ matrix.target }}/${{ matrix.rust }} 73 | steps: 74 | - uses: actions/checkout@v4 75 | - uses: dtolnay/rust-toolchain@stable 76 | with: 77 | toolchain: ${{ matrix.rust }} 78 | targets: ${{ matrix.target }} 79 | - name: Tests 80 | run: | 81 | cargo rustc "--target=${{ matrix.target }}" --no-default-features --features "${{ matrix.features }}" 82 | 83 | 84 | miri: 85 | runs-on: ubuntu-latest 86 | steps: 87 | - uses: actions/checkout@v4 88 | - name: Install Miri 89 | run: | 90 | rustup toolchain install nightly --component miri 91 | rustup override set nightly 92 | cargo miri setup 93 | - name: Test with Miri 94 | run: cargo miri test --all-features 95 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled files 2 | *.o 3 | *.so 4 | *.rlib 5 | *.dll 6 | 7 | # Executables 8 | *.exe 9 | 10 | # Generated by Cargo 11 | /Cargo.lock 12 | /target 13 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Recent Changes (arrayvec) 2 | ========================= 3 | 4 | ## 0.7.6 5 | 6 | - Fix no-std build [#274](https://github.com/bluss/arrayvec/pull/274) 7 | 8 | ## 0.7.5 9 | 10 | - Add `as_ptr` and `as_mut_ptr` to `ArrayString` [@YuhanLiin](https://github.com/YuhanLiin) [#260](https://github.com/bluss/arrayvec/pull/260) 11 | - Add borsh serialization support by @honzasp and @Fuuzetsu [#259](https://github.com/bluss/arrayvec/pull/259) 12 | - Move length field before before data in ArrayVec and ArrayString by @JakkuSakura [#255](https://github.com/bluss/arrayvec/pull/255) 13 | - Fix miri error for ZST case in extend by @bluss 14 | - implement AsRef for ArrayString by [@Zoybean](https://github.com/Zoybean) [#218](https://github.com/bluss/arrayvec/pull/218) 15 | - Fix typos in changelog by [@striezel](https://github.com/striezel) [#241](https://github.com/bluss/arrayvec/pull/241) 16 | - Add `as_slice`, `as_mut_slice` methods to `IntoIter` by [@clarfonthey](https://github.com/clarfonthey) [#224](https://github.com/bluss/arrayvec/pull/224) 17 | 18 | 19 | ## 0.7.4 20 | 21 | - Add feature zeroize to support the `Zeroize` trait by @elichai 22 | 23 | ## 0.7.3 24 | 25 | - Use track_caller on multiple methods like push and similar, for capacity 26 | overflows by @kornelski 27 | - impl BorrowMut for ArrayString by @msrd0 28 | - Fix stacked borrows violations by @clubby789 29 | - Update Miri CI by @RalfJung 30 | 31 | ## 0.7.2 32 | 33 | - Add `.as_mut_str()` to `ArrayString` by @clarfonthey 34 | - Add `remaining_capacity` to `ArrayString` by @bhgomes 35 | - Add `zero_filled` constructor by @c410-f3r 36 | - Optimize `retain` by @TennyZhuang and @niklasf 37 | - Make the following methods `const` by @bhgomes: 38 | - len 39 | - is_empty 40 | - capacity 41 | - is_full 42 | - remaining_capacity 43 | - CapacityError::new 44 | 45 | ## 0.7.1 46 | 47 | - Add new ArrayVec methods `.take()` and `.into_inner_unchecked()` by @conradludgate 48 | - `clone_from` now uses `truncate` when needed by @a1phyr 49 | 50 | ## 0.7.0 51 | 52 | - `fn new_const` is now the way to const-construct arrayvec and arraystring, 53 | and `fn new` has been reverted to a regular "non-const" function. 54 | This works around performance issue #182, where the const fn version did not 55 | optimize well. Change by @bluss with thanks to @rodrimati1992 and @niklasf 56 | for analyzing the problem. 57 | 58 | - The deprecated feature flag `unstable-const-fn` was removed, since it's not needed 59 | 60 | - Optimize `.retain()` by using the same algorithm as in std, change by @niklasf, 61 | issue #174. Original optimization in Rust std by @oxalica in rust-lang/rust/pull/81126 62 | 63 | ## 0.6.1 64 | 65 | - The ``ArrayVec::new`` and ``ArrayString::new`` constructors are properly 66 | const fns on stable and the feature flag ``unstable-const-fn`` is now deprecated. 67 | by @rodrimati1992 68 | 69 | - Small fix to the capacity check macro by @Xaeroxe 70 | - Typo fix in documentation by @cuviper 71 | - Small code cleanup by @bluss 72 | 73 | ## 0.6.0 74 | 75 | - The **const generics** release 🎉. Arrayvec finally implements what it 76 | wanted to implement, since its first version: a vector backed by an array, 77 | with generic parameters for the arbitrary element type *and* backing array 78 | capacity. 79 | 80 | The New type syntax is `ArrayVec` where `CAP` is the arrayvec capacity. 81 | For arraystring the syntax is `ArrayString`. 82 | 83 | Length is stored internally as u32; this limits the maximum capacity. The size 84 | of the `ArrayVec` or `ArrayString` structs for the same capacity may grow 85 | slightly compared with the previous version (depending on padding requirements 86 | for the element type). Change by @bluss. 87 | 88 | - Arrayvec's `.extend()` and `FromIterator`/`.collect()` to arrayvec now 89 | **panic** if the capacity of the arrayvec is exceeded. Change by @bluss. 90 | 91 | - Arraystring now implements `TryFrom<&str>` and `TryFrom` by 92 | @c410-f3r 93 | 94 | - Minimum supported rust version is Rust 1.51 95 | 96 | ## 0.5.2 97 | 98 | - Add `is_empty` methods for ArrayVec and ArrayString by @nicbn 99 | - Implement `TryFrom` for ArrayVec by @paulkernfeld 100 | - Add `unstable-const-fn` to make `new` methods const by @m-ou-se 101 | - Run miri in CI and a few related fixes by @RalfJung 102 | - Fix outdated comment by @Phlosioneer 103 | - Move changelog to a separate file by @Luro02 104 | - Remove deprecated `Error::description` by @AnderEnder 105 | - Use pointer method `add` by @hbina 106 | 107 | ## 0.5.1 108 | 109 | - Add `as_ptr`, `as_mut_ptr` accessors directly on the `ArrayVec` by @tbu- 110 | (matches the same addition to `Vec` which happened in Rust 1.37). 111 | - Add method `ArrayString::len` (now available directly, not just through deref to str). 112 | - Use raw pointers instead of `&mut [u8]` for encoding chars into `ArrayString` 113 | (uninit best practice fix). 114 | - Use raw pointers instead of `get_unchecked_mut` where the target may be 115 | uninitialized everywhere relevant in the ArrayVec implementation 116 | (uninit best practice fix). 117 | - Changed inline hints on many methods, mainly removing inline hints 118 | - `ArrayVec::dispose` is now deprecated (it has no purpose anymore) 119 | 120 | ## 0.4.12 121 | 122 | - Use raw pointers instead of `get_unchecked_mut` where the target may be 123 | uninitialized everywhere relevant in the ArrayVec implementation. 124 | 125 | ## 0.5.0 126 | 127 | - Use `MaybeUninit` (now unconditionally) in the implementation of 128 | `ArrayVec` 129 | - Use `MaybeUninit` (now unconditionally) in the implementation of 130 | `ArrayString` 131 | - The crate feature for serde serialization is now named `serde`. 132 | - Updated the `Array` trait interface, and it is now easier to use for 133 | users outside the crate. 134 | - Add `FromStr` impl for `ArrayString` by @despawnerer 135 | - Add method `try_extend_from_slice` to `ArrayVec`, which is always 136 | efficient by @Thomasdezeeuw. 137 | - Add method `remaining_capacity` by @Thomasdezeeuw 138 | - Improve performance of the `extend` method. 139 | - The index type of zero capacity vectors is now itself zero size, by 140 | @clarfon 141 | - Use `drop_in_place` for truncate and clear methods. This affects drop order 142 | and resume from panic during drop. 143 | - Use Rust 2018 edition for the implementation 144 | - Require Rust 1.36 or later, for the unconditional `MaybeUninit` 145 | improvements. 146 | 147 | ## Older releases 148 | 149 | - 0.4.11 150 | 151 | - In Rust 1.36 or later, use newly stable `MaybeUninit`. This extends the 152 | soundness work introduced in 0.4.9, we are finally able to use this in 153 | stable. We use feature detection (build script) to enable this at build 154 | time. 155 | 156 | - 0.4.10 157 | 158 | - Use `repr(C)` in the `union` version that was introduced in 0.4.9, to 159 | allay some soundness concerns. 160 | 161 | - 0.4.9 162 | 163 | - Use `union` in the implementation on when this is detected to be supported 164 | (nightly only for now). This is a better solution for treating uninitialized 165 | regions correctly, and we'll use it in stable Rust as soon as we are able. 166 | When this is enabled, the `ArrayVec` has no space overhead in its memory 167 | layout, although the size of the vec should not be relied upon. (See [#114](https://github.com/bluss/arrayvec/pull/114)) 168 | - `ArrayString` updated to not use uninitialized memory, it instead zeros its 169 | backing array. This will be refined in the next version, since we 170 | need to make changes to the user visible API. 171 | - The `use_union` feature now does nothing (like its documentation foretold). 172 | 173 | 174 | - 0.4.8 175 | 176 | - Implement Clone and Debug for `IntoIter` by @clarcharr 177 | - Add more array sizes under crate features. These cover all in the range 178 | up to 128 and 129 to 255 respectively (we have a few of those by default): 179 | 180 | - `array-size-33-128` 181 | - `array-size-129-255` 182 | 183 | - 0.4.7 184 | 185 | - Fix future compat warning about raw pointer casts 186 | - Use `drop_in_place` when dropping the arrayvec by-value iterator 187 | - Decrease minimum Rust version (see docs) by @jeehoonkang 188 | 189 | - 0.3.25 190 | 191 | - Fix future compat warning about raw pointer casts 192 | 193 | - 0.4.6 194 | 195 | - Fix compilation on 16-bit targets. This means, the 65536 array size is not 196 | included on these targets. 197 | 198 | - 0.3.24 199 | 200 | - Fix compilation on 16-bit targets. This means, the 65536 array size is not 201 | included on these targets. 202 | - Fix license files so that they are both included (was fixed in 0.4 before) 203 | 204 | - 0.4.5 205 | 206 | - Add methods to `ArrayString` by @DenialAdams: 207 | 208 | - `.pop() -> Option` 209 | - `.truncate(new_len)` 210 | - `.remove(index) -> char` 211 | 212 | - Remove dependency on crate odds 213 | - Document debug assertions in unsafe methods better 214 | 215 | - 0.4.4 216 | 217 | - Add method `ArrayVec::truncate()` by @niklasf 218 | 219 | - 0.4.3 220 | 221 | - Improve performance for `ArrayVec::extend` with a lower level 222 | implementation (#74) 223 | - Small cleanup in dependencies (use no std for crates where we don't need more) 224 | 225 | - 0.4.2 226 | 227 | - Add constructor method `new` to `CapacityError`. 228 | 229 | - 0.4.1 230 | 231 | - Add `Default` impl to `ArrayString` by @tbu- 232 | 233 | - 0.4.0 234 | 235 | - Reformed signatures and error handling by @bluss and @tbu-: 236 | 237 | - `ArrayVec`'s `push, insert, remove, swap_remove` now match `Vec`'s 238 | corresponding signature and panic on capacity errors where applicable. 239 | - Add fallible methods `try_push, insert` and checked methods 240 | `pop_at, swap_pop`. 241 | - Similar changes to `ArrayString`'s push methods. 242 | 243 | - Use a local version of the `RangeArgument` trait 244 | - Add array sizes 50, 150, 200 by @daboross 245 | - Support serde 1.0 by @daboross 246 | - New method `.push_unchecked()` by @niklasf 247 | - `ArrayString` implements `PartialOrd, Ord` by @tbu- 248 | - Require Rust 1.14 249 | - crate feature `use_generic_array` was dropped. 250 | 251 | - 0.3.23 252 | 253 | - Implement `PartialOrd, Ord` as well as `PartialOrd` for 254 | `ArrayString`. 255 | 256 | - 0.3.22 257 | 258 | - Implement `Array` for the 65536 size 259 | 260 | - 0.3.21 261 | 262 | - Use `encode_utf8` from crate odds 263 | - Add constructor `ArrayString::from_byte_string` 264 | 265 | - 0.3.20 266 | 267 | - Simplify and speed up `ArrayString`’s `.push(char)`- 268 | 269 | - 0.3.19 270 | 271 | - Add new crate feature `use_generic_array` which allows using their 272 | `GenericArray` just like a regular fixed size array for the storage 273 | of an `ArrayVec`. 274 | 275 | - 0.3.18 276 | 277 | - Fix bounds check in `ArrayVec::insert`! 278 | It would be buggy if `self.len() < index < self.capacity()`. Take note of 279 | the push out behavior specified in the docs. 280 | 281 | - 0.3.17 282 | 283 | - Added crate feature `use_union` which forwards to the nodrop crate feature 284 | - Added methods `.is_full()` to `ArrayVec` and `ArrayString`. 285 | 286 | - 0.3.16 287 | 288 | - Added method `.retain()` to `ArrayVec`. 289 | - Added methods `.as_slice(), .as_mut_slice()` to `ArrayVec` and `.as_str()` 290 | to `ArrayString`. 291 | 292 | - 0.3.15 293 | 294 | - Add feature std, which you can opt out of to use `no_std` (requires Rust 1.6 295 | to opt out). 296 | - Implement `Clone::clone_from` for ArrayVec and ArrayString 297 | 298 | - 0.3.14 299 | 300 | - Add `ArrayString::from(&str)` 301 | 302 | - 0.3.13 303 | 304 | - Added `DerefMut` impl for `ArrayString`. 305 | - Added method `.simplify()` to drop the element for `CapacityError`. 306 | - Added method `.dispose()` to `ArrayVec` 307 | 308 | - 0.3.12 309 | 310 | - Added ArrayString, a fixed capacity analogy of String 311 | 312 | - 0.3.11 313 | 314 | - Added trait impls Default, PartialOrd, Ord, Write for ArrayVec 315 | 316 | - 0.3.10 317 | 318 | - Go back to using external NoDrop, fixing a panic safety bug (issue #3) 319 | 320 | - 0.3.8 321 | 322 | - Inline the non-dropping logic to remove one drop flag in the 323 | ArrayVec representation. 324 | 325 | - 0.3.7 326 | 327 | - Added method .into_inner() 328 | - Added unsafe method .set_len() 329 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "arrayvec" 3 | version = "0.7.6" 4 | authors = ["bluss"] 5 | license = "MIT OR Apache-2.0" 6 | edition = "2018" 7 | rust-version = "1.51" 8 | 9 | description = "A vector with fixed capacity, backed by an array (it can be stored on the stack too). Implements fixed capacity ArrayVec and ArrayString." 10 | documentation = "https://docs.rs/arrayvec/" 11 | repository = "https://github.com/bluss/arrayvec" 12 | 13 | keywords = ["stack", "vector", "array", "data-structure", "no_std"] 14 | categories = ["data-structures", "no-std"] 15 | 16 | [build-dependencies] 17 | 18 | [dependencies.borsh] 19 | version = "1.2.0" 20 | optional = true 21 | default-features = false 22 | 23 | [dependencies.serde] 24 | version = "1.0" 25 | optional = true 26 | default-features = false 27 | 28 | [dependencies.zeroize] 29 | version = "1.4" 30 | optional = true 31 | default-features = false 32 | 33 | [dev-dependencies.serde_test] 34 | version = "1.0" 35 | 36 | [dev-dependencies] 37 | matches = { version = "0.1" } 38 | bencher = "0.1.4" 39 | 40 | [[bench]] 41 | name = "extend" 42 | harness = false 43 | 44 | [[bench]] 45 | name = "arraystring" 46 | harness = false 47 | 48 | [features] 49 | default = ["std"] 50 | std = [] 51 | 52 | [profile.bench] 53 | debug = true 54 | [profile.release] 55 | debug = true 56 | 57 | [package.metadata.docs.rs] 58 | features = ["borsh", "serde", "zeroize"] 59 | 60 | [package.metadata.release] 61 | no-dev-version = true 62 | tag-name = "{{version}}" 63 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) Ulrik Sverdrup "bluss" 2015-2023 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | arrayvec 3 | ======== 4 | [![Crates.io: arrayvec](https://img.shields.io/crates/v/arrayvec.svg)](https://crates.io/crates/arrayvec) 5 | [![Documentation](https://docs.rs/arrayvec/badge.svg)](https://docs.rs/arrayvec) 6 | [![Build Status](https://github.com/bluss/arrayvec/workflows/Continuous%20integration/badge.svg?branch=master)](https://github.com/bluss/arrayvec/actions) 7 | 8 | 9 | 10 | 11 | [![License: Apache](https://img.shields.io/badge/License-Apache%202.0-red.svg)](LICENSE-APACHE) 12 | OR 13 | [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) 14 | 15 | A vector with fixed capacity. 16 | 17 | Please read the [`API documentation here`](https://docs.rs/arrayvec) 18 | 19 | # License 20 | 21 | Dual-licensed to be compatible with the Rust project. 22 | 23 | Licensed under the Apache License, Version 2.0 24 | http://www.apache.org/licenses/LICENSE-2.0 or the MIT license 25 | http://opensource.org/licenses/MIT, at your 26 | option. This file may not be copied, modified, or distributed 27 | except according to those terms. 28 | -------------------------------------------------------------------------------- /benches/arraystring.rs: -------------------------------------------------------------------------------- 1 | 2 | extern crate arrayvec; 3 | #[macro_use] extern crate bencher; 4 | 5 | use arrayvec::ArrayString; 6 | 7 | use bencher::Bencher; 8 | 9 | fn try_push_c(b: &mut Bencher) { 10 | let mut v = ArrayString::<512>::new(); 11 | b.iter(|| { 12 | v.clear(); 13 | while v.try_push('c').is_ok() { 14 | } 15 | v.len() 16 | }); 17 | b.bytes = v.capacity() as u64; 18 | } 19 | 20 | fn try_push_alpha(b: &mut Bencher) { 21 | let mut v = ArrayString::<512>::new(); 22 | b.iter(|| { 23 | v.clear(); 24 | while v.try_push('α').is_ok() { 25 | } 26 | v.len() 27 | }); 28 | b.bytes = v.capacity() as u64; 29 | } 30 | 31 | // Yes, pushing a string char-by-char is slow. Use .push_str. 32 | fn try_push_string(b: &mut Bencher) { 33 | let mut v = ArrayString::<512>::new(); 34 | let input = "abcαβγ“”"; 35 | b.iter(|| { 36 | v.clear(); 37 | for ch in input.chars().cycle() { 38 | if !v.try_push(ch).is_ok() { 39 | break; 40 | } 41 | } 42 | v.len() 43 | }); 44 | b.bytes = v.capacity() as u64; 45 | } 46 | 47 | fn push_c(b: &mut Bencher) { 48 | let mut v = ArrayString::<512>::new(); 49 | b.iter(|| { 50 | v.clear(); 51 | while !v.is_full() { 52 | v.push('c'); 53 | } 54 | v.len() 55 | }); 56 | b.bytes = v.capacity() as u64; 57 | } 58 | 59 | fn push_alpha(b: &mut Bencher) { 60 | let mut v = ArrayString::<512>::new(); 61 | b.iter(|| { 62 | v.clear(); 63 | while !v.is_full() { 64 | v.push('α'); 65 | } 66 | v.len() 67 | }); 68 | b.bytes = v.capacity() as u64; 69 | } 70 | 71 | fn push_string(b: &mut Bencher) { 72 | let mut v = ArrayString::<512>::new(); 73 | let input = "abcαβγ“”"; 74 | b.iter(|| { 75 | v.clear(); 76 | for ch in input.chars().cycle() { 77 | if !v.is_full() { 78 | v.push(ch); 79 | } else { 80 | break; 81 | } 82 | } 83 | v.len() 84 | }); 85 | b.bytes = v.capacity() as u64; 86 | } 87 | 88 | benchmark_group!(benches, try_push_c, try_push_alpha, try_push_string, push_c, 89 | push_alpha, push_string); 90 | benchmark_main!(benches); 91 | -------------------------------------------------------------------------------- /benches/extend.rs: -------------------------------------------------------------------------------- 1 | 2 | extern crate arrayvec; 3 | #[macro_use] extern crate bencher; 4 | 5 | use std::io::Write; 6 | 7 | use arrayvec::ArrayVec; 8 | 9 | use bencher::Bencher; 10 | use bencher::black_box; 11 | 12 | fn extend_with_constant(b: &mut Bencher) { 13 | let mut v = ArrayVec::::new(); 14 | let cap = v.capacity(); 15 | b.iter(|| { 16 | v.clear(); 17 | let constant = black_box(1); 18 | v.extend((0..cap).map(move |_| constant)); 19 | v[511] 20 | }); 21 | b.bytes = v.capacity() as u64; 22 | } 23 | 24 | fn extend_with_range(b: &mut Bencher) { 25 | let mut v = ArrayVec::::new(); 26 | let cap = v.capacity(); 27 | b.iter(|| { 28 | v.clear(); 29 | let range = 0..cap; 30 | v.extend(range.map(|x| black_box(x as _))); 31 | v[511] 32 | }); 33 | b.bytes = v.capacity() as u64; 34 | } 35 | 36 | fn extend_with_slice(b: &mut Bencher) { 37 | let mut v = ArrayVec::::new(); 38 | let data = [1; 512]; 39 | b.iter(|| { 40 | v.clear(); 41 | let iter = data.iter().map(|&x| x); 42 | v.extend(iter); 43 | v[511] 44 | }); 45 | b.bytes = v.capacity() as u64; 46 | } 47 | 48 | fn extend_with_write(b: &mut Bencher) { 49 | let mut v = ArrayVec::::new(); 50 | let data = [1; 512]; 51 | b.iter(|| { 52 | v.clear(); 53 | v.write(&data[..]).ok(); 54 | v[511] 55 | }); 56 | b.bytes = v.capacity() as u64; 57 | } 58 | 59 | fn extend_from_slice(b: &mut Bencher) { 60 | let mut v = ArrayVec::::new(); 61 | let data = [1; 512]; 62 | b.iter(|| { 63 | v.clear(); 64 | v.try_extend_from_slice(&data).ok(); 65 | v[511] 66 | }); 67 | b.bytes = v.capacity() as u64; 68 | } 69 | 70 | benchmark_group!(benches, 71 | extend_with_constant, 72 | extend_with_range, 73 | extend_with_slice, 74 | extend_with_write, 75 | extend_from_slice 76 | ); 77 | 78 | benchmark_main!(benches); 79 | -------------------------------------------------------------------------------- /src/array_string.rs: -------------------------------------------------------------------------------- 1 | use std::borrow::{Borrow, BorrowMut}; 2 | use std::cmp; 3 | use std::convert::TryFrom; 4 | use std::fmt; 5 | use std::hash::{Hash, Hasher}; 6 | use std::mem::MaybeUninit; 7 | use std::ops::{Deref, DerefMut}; 8 | #[cfg(feature="std")] 9 | use std::path::Path; 10 | use std::ptr; 11 | use std::slice; 12 | use std::str; 13 | use std::str::FromStr; 14 | use std::str::Utf8Error; 15 | 16 | use crate::CapacityError; 17 | use crate::LenUint; 18 | use crate::char::encode_utf8; 19 | use crate::utils::MakeMaybeUninit; 20 | 21 | #[cfg(feature="serde")] 22 | use serde::{Serialize, Deserialize, Serializer, Deserializer}; 23 | 24 | 25 | /// A string with a fixed capacity. 26 | /// 27 | /// The `ArrayString` is a string backed by a fixed size array. It keeps track 28 | /// of its length, and is parameterized by `CAP` for the maximum capacity. 29 | /// 30 | /// `CAP` is of type `usize` but is range limited to `u32::MAX` (or `u16` on 16-bit targets); 31 | /// attempting to create larger arrayvecs with larger capacity will panic. 32 | /// 33 | /// The string is a contiguous value that you can store directly on the stack 34 | /// if needed. 35 | #[derive(Copy)] 36 | #[repr(C)] 37 | pub struct ArrayString { 38 | // the `len` first elements of the array are initialized 39 | len: LenUint, 40 | xs: [MaybeUninit; CAP], 41 | } 42 | 43 | impl Default for ArrayString 44 | { 45 | /// Return an empty `ArrayString` 46 | fn default() -> ArrayString { 47 | ArrayString::new() 48 | } 49 | } 50 | 51 | impl ArrayString 52 | { 53 | /// Create a new empty `ArrayString`. 54 | /// 55 | /// Capacity is inferred from the type parameter. 56 | /// 57 | /// ``` 58 | /// use arrayvec::ArrayString; 59 | /// 60 | /// let mut string = ArrayString::<16>::new(); 61 | /// string.push_str("foo"); 62 | /// assert_eq!(&string[..], "foo"); 63 | /// assert_eq!(string.capacity(), 16); 64 | /// ``` 65 | pub fn new() -> ArrayString { 66 | assert_capacity_limit!(CAP); 67 | unsafe { 68 | ArrayString { xs: MaybeUninit::uninit().assume_init(), len: 0 } 69 | } 70 | } 71 | 72 | /// Create a new empty `ArrayString` (const fn). 73 | /// 74 | /// Capacity is inferred from the type parameter. 75 | /// 76 | /// ``` 77 | /// use arrayvec::ArrayString; 78 | /// 79 | /// static ARRAY: ArrayString<1024> = ArrayString::new_const(); 80 | /// ``` 81 | pub const fn new_const() -> ArrayString { 82 | assert_capacity_limit_const!(CAP); 83 | ArrayString { xs: MakeMaybeUninit::ARRAY, len: 0 } 84 | } 85 | 86 | /// Return the length of the string. 87 | #[inline] 88 | pub const fn len(&self) -> usize { self.len as usize } 89 | 90 | /// Returns whether the string is empty. 91 | #[inline] 92 | pub const fn is_empty(&self) -> bool { self.len() == 0 } 93 | 94 | /// Create a new `ArrayString` from a `str`. 95 | /// 96 | /// Capacity is inferred from the type parameter. 97 | /// 98 | /// **Errors** if the backing array is not large enough to fit the string. 99 | /// 100 | /// ``` 101 | /// use arrayvec::ArrayString; 102 | /// 103 | /// let mut string = ArrayString::<3>::from("foo").unwrap(); 104 | /// assert_eq!(&string[..], "foo"); 105 | /// assert_eq!(string.len(), 3); 106 | /// assert_eq!(string.capacity(), 3); 107 | /// ``` 108 | pub fn from(s: &str) -> Result> { 109 | let mut arraystr = Self::new(); 110 | arraystr.try_push_str(s)?; 111 | Ok(arraystr) 112 | } 113 | 114 | /// Create a new `ArrayString` from a byte string literal. 115 | /// 116 | /// **Errors** if the byte string literal is not valid UTF-8. 117 | /// 118 | /// ``` 119 | /// use arrayvec::ArrayString; 120 | /// 121 | /// let string = ArrayString::from_byte_string(b"hello world").unwrap(); 122 | /// ``` 123 | pub fn from_byte_string(b: &[u8; CAP]) -> Result { 124 | let len = str::from_utf8(b)?.len(); 125 | debug_assert_eq!(len, CAP); 126 | let mut vec = Self::new(); 127 | unsafe { 128 | (b as *const [u8; CAP] as *const [MaybeUninit; CAP]) 129 | .copy_to_nonoverlapping(&mut vec.xs as *mut [MaybeUninit; CAP], 1); 130 | vec.set_len(CAP); 131 | } 132 | Ok(vec) 133 | } 134 | 135 | /// Create a new `ArrayString` value fully filled with ASCII NULL characters (`\0`). Useful 136 | /// to be used as a buffer to collect external data or as a buffer for intermediate processing. 137 | /// 138 | /// ``` 139 | /// use arrayvec::ArrayString; 140 | /// 141 | /// let string = ArrayString::<16>::zero_filled(); 142 | /// assert_eq!(string.len(), 16); 143 | /// ``` 144 | #[inline] 145 | pub fn zero_filled() -> Self { 146 | assert_capacity_limit!(CAP); 147 | // SAFETY: `assert_capacity_limit` asserts that `len` won't overflow and 148 | // `zeroed` fully fills the array with nulls. 149 | unsafe { 150 | ArrayString { 151 | xs: MaybeUninit::zeroed().assume_init(), 152 | len: CAP as _ 153 | } 154 | } 155 | } 156 | 157 | /// Return the capacity of the `ArrayString`. 158 | /// 159 | /// ``` 160 | /// use arrayvec::ArrayString; 161 | /// 162 | /// let string = ArrayString::<3>::new(); 163 | /// assert_eq!(string.capacity(), 3); 164 | /// ``` 165 | #[inline(always)] 166 | pub const fn capacity(&self) -> usize { CAP } 167 | 168 | /// Return if the `ArrayString` is completely filled. 169 | /// 170 | /// ``` 171 | /// use arrayvec::ArrayString; 172 | /// 173 | /// let mut string = ArrayString::<1>::new(); 174 | /// assert!(!string.is_full()); 175 | /// string.push_str("A"); 176 | /// assert!(string.is_full()); 177 | /// ``` 178 | pub const fn is_full(&self) -> bool { self.len() == self.capacity() } 179 | 180 | /// Returns the capacity left in the `ArrayString`. 181 | /// 182 | /// ``` 183 | /// use arrayvec::ArrayString; 184 | /// 185 | /// let mut string = ArrayString::<3>::from("abc").unwrap(); 186 | /// string.pop(); 187 | /// assert_eq!(string.remaining_capacity(), 1); 188 | /// ``` 189 | pub const fn remaining_capacity(&self) -> usize { 190 | self.capacity() - self.len() 191 | } 192 | 193 | /// Adds the given char to the end of the string. 194 | /// 195 | /// ***Panics*** if the backing array is not large enough to fit the additional char. 196 | /// 197 | /// ``` 198 | /// use arrayvec::ArrayString; 199 | /// 200 | /// let mut string = ArrayString::<2>::new(); 201 | /// 202 | /// string.push('a'); 203 | /// string.push('b'); 204 | /// 205 | /// assert_eq!(&string[..], "ab"); 206 | /// ``` 207 | #[track_caller] 208 | pub fn push(&mut self, c: char) { 209 | self.try_push(c).unwrap(); 210 | } 211 | 212 | /// Adds the given char to the end of the string. 213 | /// 214 | /// Returns `Ok` if the push succeeds. 215 | /// 216 | /// **Errors** if the backing array is not large enough to fit the additional char. 217 | /// 218 | /// ``` 219 | /// use arrayvec::ArrayString; 220 | /// 221 | /// let mut string = ArrayString::<2>::new(); 222 | /// 223 | /// string.try_push('a').unwrap(); 224 | /// string.try_push('b').unwrap(); 225 | /// let overflow = string.try_push('c'); 226 | /// 227 | /// assert_eq!(&string[..], "ab"); 228 | /// assert_eq!(overflow.unwrap_err().element(), 'c'); 229 | /// ``` 230 | pub fn try_push(&mut self, c: char) -> Result<(), CapacityError> { 231 | let len = self.len(); 232 | unsafe { 233 | let ptr = self.as_mut_ptr().add(len); 234 | let remaining_cap = self.capacity() - len; 235 | match encode_utf8(c, ptr, remaining_cap) { 236 | Ok(n) => { 237 | self.set_len(len + n); 238 | Ok(()) 239 | } 240 | Err(_) => Err(CapacityError::new(c)), 241 | } 242 | } 243 | } 244 | 245 | /// Adds the given string slice to the end of the string. 246 | /// 247 | /// ***Panics*** if the backing array is not large enough to fit the string. 248 | /// 249 | /// ``` 250 | /// use arrayvec::ArrayString; 251 | /// 252 | /// let mut string = ArrayString::<2>::new(); 253 | /// 254 | /// string.push_str("a"); 255 | /// string.push_str("d"); 256 | /// 257 | /// assert_eq!(&string[..], "ad"); 258 | /// ``` 259 | #[track_caller] 260 | pub fn push_str(&mut self, s: &str) { 261 | self.try_push_str(s).unwrap() 262 | } 263 | 264 | /// Adds the given string slice to the end of the string. 265 | /// 266 | /// Returns `Ok` if the push succeeds. 267 | /// 268 | /// **Errors** if the backing array is not large enough to fit the string. 269 | /// 270 | /// ``` 271 | /// use arrayvec::ArrayString; 272 | /// 273 | /// let mut string = ArrayString::<2>::new(); 274 | /// 275 | /// string.try_push_str("a").unwrap(); 276 | /// let overflow1 = string.try_push_str("bc"); 277 | /// string.try_push_str("d").unwrap(); 278 | /// let overflow2 = string.try_push_str("ef"); 279 | /// 280 | /// assert_eq!(&string[..], "ad"); 281 | /// assert_eq!(overflow1.unwrap_err().element(), "bc"); 282 | /// assert_eq!(overflow2.unwrap_err().element(), "ef"); 283 | /// ``` 284 | pub fn try_push_str<'a>(&mut self, s: &'a str) -> Result<(), CapacityError<&'a str>> { 285 | if s.len() > self.capacity() - self.len() { 286 | return Err(CapacityError::new(s)); 287 | } 288 | unsafe { 289 | let dst = self.as_mut_ptr().add(self.len()); 290 | let src = s.as_ptr(); 291 | ptr::copy_nonoverlapping(src, dst, s.len()); 292 | let newl = self.len() + s.len(); 293 | self.set_len(newl); 294 | } 295 | Ok(()) 296 | } 297 | 298 | /// Removes the last character from the string and returns it. 299 | /// 300 | /// Returns `None` if this `ArrayString` is empty. 301 | /// 302 | /// ``` 303 | /// use arrayvec::ArrayString; 304 | /// 305 | /// let mut s = ArrayString::<3>::from("foo").unwrap(); 306 | /// 307 | /// assert_eq!(s.pop(), Some('o')); 308 | /// assert_eq!(s.pop(), Some('o')); 309 | /// assert_eq!(s.pop(), Some('f')); 310 | /// 311 | /// assert_eq!(s.pop(), None); 312 | /// ``` 313 | pub fn pop(&mut self) -> Option { 314 | let ch = match self.chars().rev().next() { 315 | Some(ch) => ch, 316 | None => return None, 317 | }; 318 | let new_len = self.len() - ch.len_utf8(); 319 | unsafe { 320 | self.set_len(new_len); 321 | } 322 | Some(ch) 323 | } 324 | 325 | /// Shortens this `ArrayString` to the specified length. 326 | /// 327 | /// If `new_len` is greater than the string’s current length, this has no 328 | /// effect. 329 | /// 330 | /// ***Panics*** if `new_len` does not lie on a `char` boundary. 331 | /// 332 | /// ``` 333 | /// use arrayvec::ArrayString; 334 | /// 335 | /// let mut string = ArrayString::<6>::from("foobar").unwrap(); 336 | /// string.truncate(3); 337 | /// assert_eq!(&string[..], "foo"); 338 | /// string.truncate(4); 339 | /// assert_eq!(&string[..], "foo"); 340 | /// ``` 341 | pub fn truncate(&mut self, new_len: usize) { 342 | if new_len <= self.len() { 343 | assert!(self.is_char_boundary(new_len)); 344 | unsafe { 345 | // In libstd truncate is called on the underlying vector, 346 | // which in turns drops each element. 347 | // As we know we don't have to worry about Drop, 348 | // we can just set the length (a la clear.) 349 | self.set_len(new_len); 350 | } 351 | } 352 | } 353 | 354 | /// Removes a `char` from this `ArrayString` at a byte position and returns it. 355 | /// 356 | /// This is an `O(n)` operation, as it requires copying every element in the 357 | /// array. 358 | /// 359 | /// ***Panics*** if `idx` is larger than or equal to the `ArrayString`’s length, 360 | /// or if it does not lie on a `char` boundary. 361 | /// 362 | /// ``` 363 | /// use arrayvec::ArrayString; 364 | /// 365 | /// let mut s = ArrayString::<3>::from("foo").unwrap(); 366 | /// 367 | /// assert_eq!(s.remove(0), 'f'); 368 | /// assert_eq!(s.remove(1), 'o'); 369 | /// assert_eq!(s.remove(0), 'o'); 370 | /// ``` 371 | pub fn remove(&mut self, idx: usize) -> char { 372 | let ch = match self[idx..].chars().next() { 373 | Some(ch) => ch, 374 | None => panic!("cannot remove a char from the end of a string"), 375 | }; 376 | 377 | let next = idx + ch.len_utf8(); 378 | let len = self.len(); 379 | let ptr = self.as_mut_ptr(); 380 | unsafe { 381 | ptr::copy( 382 | ptr.add(next), 383 | ptr.add(idx), 384 | len - next); 385 | self.set_len(len - (next - idx)); 386 | } 387 | ch 388 | } 389 | 390 | /// Make the string empty. 391 | pub fn clear(&mut self) { 392 | unsafe { 393 | self.set_len(0); 394 | } 395 | } 396 | 397 | /// Set the strings’s length. 398 | /// 399 | /// This function is `unsafe` because it changes the notion of the 400 | /// number of “valid” bytes in the string. Use with care. 401 | /// 402 | /// This method uses *debug assertions* to check the validity of `length` 403 | /// and may use other debug assertions. 404 | pub unsafe fn set_len(&mut self, length: usize) { 405 | // type invariant that capacity always fits in LenUint 406 | debug_assert!(length <= self.capacity()); 407 | self.len = length as LenUint; 408 | } 409 | 410 | /// Return a string slice of the whole `ArrayString`. 411 | pub fn as_str(&self) -> &str { 412 | self 413 | } 414 | 415 | /// Return a mutable string slice of the whole `ArrayString`. 416 | pub fn as_mut_str(&mut self) -> &mut str { 417 | self 418 | } 419 | 420 | /// Return a raw pointer to the string's buffer. 421 | pub fn as_ptr(&self) -> *const u8 { 422 | self.xs.as_ptr() as *const u8 423 | } 424 | 425 | /// Return a raw mutable pointer to the string's buffer. 426 | pub fn as_mut_ptr(&mut self) -> *mut u8 { 427 | self.xs.as_mut_ptr() as *mut u8 428 | } 429 | } 430 | 431 | impl Deref for ArrayString 432 | { 433 | type Target = str; 434 | #[inline] 435 | fn deref(&self) -> &str { 436 | unsafe { 437 | let sl = slice::from_raw_parts(self.as_ptr(), self.len()); 438 | str::from_utf8_unchecked(sl) 439 | } 440 | } 441 | } 442 | 443 | impl DerefMut for ArrayString 444 | { 445 | #[inline] 446 | fn deref_mut(&mut self) -> &mut str { 447 | unsafe { 448 | let len = self.len(); 449 | let sl = slice::from_raw_parts_mut(self.as_mut_ptr(), len); 450 | str::from_utf8_unchecked_mut(sl) 451 | } 452 | } 453 | } 454 | 455 | impl PartialEq for ArrayString 456 | { 457 | fn eq(&self, rhs: &Self) -> bool { 458 | **self == **rhs 459 | } 460 | } 461 | 462 | impl PartialEq for ArrayString 463 | { 464 | fn eq(&self, rhs: &str) -> bool { 465 | &**self == rhs 466 | } 467 | } 468 | 469 | impl PartialEq> for str 470 | { 471 | fn eq(&self, rhs: &ArrayString) -> bool { 472 | self == &**rhs 473 | } 474 | } 475 | 476 | impl Eq for ArrayString 477 | { } 478 | 479 | impl Hash for ArrayString 480 | { 481 | fn hash(&self, h: &mut H) { 482 | (**self).hash(h) 483 | } 484 | } 485 | 486 | impl Borrow for ArrayString 487 | { 488 | fn borrow(&self) -> &str { self } 489 | } 490 | 491 | impl BorrowMut for ArrayString 492 | { 493 | fn borrow_mut(&mut self) -> &mut str { self } 494 | } 495 | 496 | impl AsRef for ArrayString 497 | { 498 | fn as_ref(&self) -> &str { self } 499 | } 500 | 501 | impl fmt::Debug for ArrayString 502 | { 503 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } 504 | } 505 | 506 | #[cfg(feature="std")] 507 | impl AsRef for ArrayString { 508 | fn as_ref(&self) -> &Path { 509 | self.as_str().as_ref() 510 | } 511 | } 512 | 513 | impl fmt::Display for ArrayString 514 | { 515 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } 516 | } 517 | 518 | /// `Write` appends written data to the end of the string. 519 | impl fmt::Write for ArrayString 520 | { 521 | fn write_char(&mut self, c: char) -> fmt::Result { 522 | self.try_push(c).map_err(|_| fmt::Error) 523 | } 524 | 525 | fn write_str(&mut self, s: &str) -> fmt::Result { 526 | self.try_push_str(s).map_err(|_| fmt::Error) 527 | } 528 | } 529 | 530 | impl Clone for ArrayString 531 | { 532 | fn clone(&self) -> ArrayString { 533 | *self 534 | } 535 | fn clone_from(&mut self, rhs: &Self) { 536 | // guaranteed to fit due to types matching. 537 | self.clear(); 538 | self.try_push_str(rhs).ok(); 539 | } 540 | } 541 | 542 | impl PartialOrd for ArrayString 543 | { 544 | fn partial_cmp(&self, rhs: &Self) -> Option { 545 | (**self).partial_cmp(&**rhs) 546 | } 547 | fn lt(&self, rhs: &Self) -> bool { **self < **rhs } 548 | fn le(&self, rhs: &Self) -> bool { **self <= **rhs } 549 | fn gt(&self, rhs: &Self) -> bool { **self > **rhs } 550 | fn ge(&self, rhs: &Self) -> bool { **self >= **rhs } 551 | } 552 | 553 | impl PartialOrd for ArrayString 554 | { 555 | fn partial_cmp(&self, rhs: &str) -> Option { 556 | (**self).partial_cmp(rhs) 557 | } 558 | fn lt(&self, rhs: &str) -> bool { &**self < rhs } 559 | fn le(&self, rhs: &str) -> bool { &**self <= rhs } 560 | fn gt(&self, rhs: &str) -> bool { &**self > rhs } 561 | fn ge(&self, rhs: &str) -> bool { &**self >= rhs } 562 | } 563 | 564 | impl PartialOrd> for str 565 | { 566 | fn partial_cmp(&self, rhs: &ArrayString) -> Option { 567 | self.partial_cmp(&**rhs) 568 | } 569 | fn lt(&self, rhs: &ArrayString) -> bool { self < &**rhs } 570 | fn le(&self, rhs: &ArrayString) -> bool { self <= &**rhs } 571 | fn gt(&self, rhs: &ArrayString) -> bool { self > &**rhs } 572 | fn ge(&self, rhs: &ArrayString) -> bool { self >= &**rhs } 573 | } 574 | 575 | impl Ord for ArrayString 576 | { 577 | fn cmp(&self, rhs: &Self) -> cmp::Ordering { 578 | (**self).cmp(&**rhs) 579 | } 580 | } 581 | 582 | impl FromStr for ArrayString 583 | { 584 | type Err = CapacityError; 585 | 586 | fn from_str(s: &str) -> Result { 587 | Self::from(s).map_err(CapacityError::simplify) 588 | } 589 | } 590 | 591 | #[cfg(feature="serde")] 592 | /// Requires crate feature `"serde"` 593 | impl Serialize for ArrayString 594 | { 595 | fn serialize(&self, serializer: S) -> Result 596 | where S: Serializer 597 | { 598 | serializer.serialize_str(&*self) 599 | } 600 | } 601 | 602 | #[cfg(feature="serde")] 603 | /// Requires crate feature `"serde"` 604 | impl<'de, const CAP: usize> Deserialize<'de> for ArrayString 605 | { 606 | fn deserialize(deserializer: D) -> Result 607 | where D: Deserializer<'de> 608 | { 609 | use serde::de::{self, Visitor}; 610 | use std::marker::PhantomData; 611 | 612 | struct ArrayStringVisitor(PhantomData<[u8; CAP]>); 613 | 614 | impl<'de, const CAP: usize> Visitor<'de> for ArrayStringVisitor { 615 | type Value = ArrayString; 616 | 617 | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 618 | write!(formatter, "a string no more than {} bytes long", CAP) 619 | } 620 | 621 | fn visit_str(self, v: &str) -> Result 622 | where E: de::Error, 623 | { 624 | ArrayString::from(v).map_err(|_| E::invalid_length(v.len(), &self)) 625 | } 626 | 627 | fn visit_bytes(self, v: &[u8]) -> Result 628 | where E: de::Error, 629 | { 630 | let s = str::from_utf8(v).map_err(|_| E::invalid_value(de::Unexpected::Bytes(v), &self))?; 631 | 632 | ArrayString::from(s).map_err(|_| E::invalid_length(s.len(), &self)) 633 | } 634 | } 635 | 636 | deserializer.deserialize_str(ArrayStringVisitor(PhantomData)) 637 | } 638 | } 639 | 640 | #[cfg(feature = "borsh")] 641 | /// Requires crate feature `"borsh"` 642 | impl borsh::BorshSerialize for ArrayString { 643 | fn serialize(&self, writer: &mut W) -> borsh::io::Result<()> { 644 | ::serialize(&*self, writer) 645 | } 646 | } 647 | 648 | #[cfg(feature = "borsh")] 649 | /// Requires crate feature `"borsh"` 650 | impl borsh::BorshDeserialize for ArrayString { 651 | fn deserialize_reader(reader: &mut R) -> borsh::io::Result { 652 | let len = ::deserialize_reader(reader)? as usize; 653 | if len > CAP { 654 | return Err(borsh::io::Error::new( 655 | borsh::io::ErrorKind::InvalidData, 656 | format!("Expected a string no more than {} bytes long", CAP), 657 | )) 658 | } 659 | 660 | let mut buf = [0u8; CAP]; 661 | let buf = &mut buf[..len]; 662 | reader.read_exact(buf)?; 663 | 664 | let s = str::from_utf8(&buf).map_err(|err| { 665 | borsh::io::Error::new(borsh::io::ErrorKind::InvalidData, err.to_string()) 666 | })?; 667 | Ok(Self::from(s).unwrap()) 668 | } 669 | } 670 | 671 | impl<'a, const CAP: usize> TryFrom<&'a str> for ArrayString 672 | { 673 | type Error = CapacityError<&'a str>; 674 | 675 | fn try_from(f: &'a str) -> Result { 676 | let mut v = Self::new(); 677 | v.try_push_str(f)?; 678 | Ok(v) 679 | } 680 | } 681 | 682 | impl<'a, const CAP: usize> TryFrom> for ArrayString 683 | { 684 | type Error = CapacityError; 685 | 686 | fn try_from(f: fmt::Arguments<'a>) -> Result { 687 | use fmt::Write; 688 | let mut v = Self::new(); 689 | v.write_fmt(f).map_err(|e| CapacityError::new(e))?; 690 | Ok(v) 691 | } 692 | } 693 | 694 | #[cfg(feature = "zeroize")] 695 | /// "Best efforts" zeroing of the `ArrayString`'s buffer when the `zeroize` feature is enabled. 696 | /// 697 | /// The length is set to 0, and the buffer is dropped and zeroized. 698 | /// Cannot ensure that previous moves of the `ArrayString` did not leave values on the stack. 699 | /// 700 | /// ``` 701 | /// use arrayvec::ArrayString; 702 | /// use zeroize::Zeroize; 703 | /// let mut string = ArrayString::<6>::from("foobar").unwrap(); 704 | /// string.zeroize(); 705 | /// assert_eq!(string.len(), 0); 706 | /// unsafe { string.set_len(string.capacity()) }; 707 | /// assert_eq!(&*string, "\0\0\0\0\0\0"); 708 | /// ``` 709 | impl zeroize::Zeroize for ArrayString { 710 | fn zeroize(&mut self) { 711 | // There are no elements to drop 712 | self.clear(); 713 | // Zeroize the backing array. 714 | self.xs.zeroize(); 715 | } 716 | } 717 | -------------------------------------------------------------------------------- /src/arrayvec.rs: -------------------------------------------------------------------------------- 1 | 2 | use std::cmp; 3 | use std::iter; 4 | use std::mem; 5 | use std::ops::{Bound, Deref, DerefMut, RangeBounds}; 6 | use std::ptr; 7 | use std::slice; 8 | 9 | // extra traits 10 | use std::borrow::{Borrow, BorrowMut}; 11 | use std::hash::{Hash, Hasher}; 12 | use std::fmt; 13 | 14 | #[cfg(feature="std")] 15 | use std::io; 16 | 17 | use std::mem::ManuallyDrop; 18 | use std::mem::MaybeUninit; 19 | 20 | #[cfg(feature="serde")] 21 | use serde::{Serialize, Deserialize, Serializer, Deserializer}; 22 | 23 | use crate::LenUint; 24 | use crate::errors::CapacityError; 25 | use crate::arrayvec_impl::ArrayVecImpl; 26 | use crate::utils::MakeMaybeUninit; 27 | 28 | /// A vector with a fixed capacity. 29 | /// 30 | /// The `ArrayVec` is a vector backed by a fixed size array. It keeps track of 31 | /// the number of initialized elements. The `ArrayVec` is parameterized 32 | /// by `T` for the element type and `CAP` for the maximum capacity. 33 | /// 34 | /// `CAP` is of type `usize` but is range limited to `u32::MAX` (or `u16::MAX` on 16-bit targets); 35 | /// attempting to create larger arrayvecs with larger capacity will panic. 36 | /// 37 | /// The vector is a contiguous value (storing the elements inline) that you can store directly on 38 | /// the stack if needed. 39 | /// 40 | /// It offers a simple API but also dereferences to a slice, so that the full slice API is 41 | /// available. The ArrayVec can be converted into a by value iterator. 42 | #[repr(C)] 43 | pub struct ArrayVec { 44 | len: LenUint, 45 | // the `len` first elements of the array are initialized 46 | xs: [MaybeUninit; CAP], 47 | } 48 | 49 | impl Drop for ArrayVec { 50 | fn drop(&mut self) { 51 | self.clear(); 52 | 53 | // MaybeUninit inhibits array's drop 54 | } 55 | } 56 | 57 | macro_rules! panic_oob { 58 | ($method_name:expr, $index:expr, $len:expr) => { 59 | panic!(concat!("ArrayVec::", $method_name, ": index {} is out of bounds in vector of length {}"), 60 | $index, $len) 61 | } 62 | } 63 | 64 | impl ArrayVec { 65 | /// Capacity 66 | const CAPACITY: usize = CAP; 67 | 68 | /// Create a new empty `ArrayVec`. 69 | /// 70 | /// The maximum capacity is given by the generic parameter `CAP`. 71 | /// 72 | /// ``` 73 | /// use arrayvec::ArrayVec; 74 | /// 75 | /// let mut array = ArrayVec::<_, 16>::new(); 76 | /// array.push(1); 77 | /// array.push(2); 78 | /// assert_eq!(&array[..], &[1, 2]); 79 | /// assert_eq!(array.capacity(), 16); 80 | /// ``` 81 | #[inline] 82 | #[track_caller] 83 | pub fn new() -> ArrayVec { 84 | assert_capacity_limit!(CAP); 85 | unsafe { 86 | ArrayVec { xs: MaybeUninit::uninit().assume_init(), len: 0 } 87 | } 88 | } 89 | 90 | /// Create a new empty `ArrayVec` (const fn). 91 | /// 92 | /// The maximum capacity is given by the generic parameter `CAP`. 93 | /// 94 | /// ``` 95 | /// use arrayvec::ArrayVec; 96 | /// 97 | /// static ARRAY: ArrayVec = ArrayVec::new_const(); 98 | /// ``` 99 | pub const fn new_const() -> ArrayVec { 100 | assert_capacity_limit_const!(CAP); 101 | ArrayVec { xs: MakeMaybeUninit::ARRAY, len: 0 } 102 | } 103 | 104 | /// Return the number of elements in the `ArrayVec`. 105 | /// 106 | /// ``` 107 | /// use arrayvec::ArrayVec; 108 | /// 109 | /// let mut array = ArrayVec::from([1, 2, 3]); 110 | /// array.pop(); 111 | /// assert_eq!(array.len(), 2); 112 | /// ``` 113 | #[inline(always)] 114 | pub const fn len(&self) -> usize { self.len as usize } 115 | 116 | /// Returns whether the `ArrayVec` is empty. 117 | /// 118 | /// ``` 119 | /// use arrayvec::ArrayVec; 120 | /// 121 | /// let mut array = ArrayVec::from([1]); 122 | /// array.pop(); 123 | /// assert_eq!(array.is_empty(), true); 124 | /// ``` 125 | #[inline] 126 | pub const fn is_empty(&self) -> bool { self.len() == 0 } 127 | 128 | /// Return the capacity of the `ArrayVec`. 129 | /// 130 | /// ``` 131 | /// use arrayvec::ArrayVec; 132 | /// 133 | /// let array = ArrayVec::from([1, 2, 3]); 134 | /// assert_eq!(array.capacity(), 3); 135 | /// ``` 136 | #[inline(always)] 137 | pub const fn capacity(&self) -> usize { CAP } 138 | 139 | /// Return true if the `ArrayVec` is completely filled to its capacity, false otherwise. 140 | /// 141 | /// ``` 142 | /// use arrayvec::ArrayVec; 143 | /// 144 | /// let mut array = ArrayVec::<_, 1>::new(); 145 | /// assert!(!array.is_full()); 146 | /// array.push(1); 147 | /// assert!(array.is_full()); 148 | /// ``` 149 | pub const fn is_full(&self) -> bool { self.len() == self.capacity() } 150 | 151 | /// Returns the capacity left in the `ArrayVec`. 152 | /// 153 | /// ``` 154 | /// use arrayvec::ArrayVec; 155 | /// 156 | /// let mut array = ArrayVec::from([1, 2, 3]); 157 | /// array.pop(); 158 | /// assert_eq!(array.remaining_capacity(), 1); 159 | /// ``` 160 | pub const fn remaining_capacity(&self) -> usize { 161 | self.capacity() - self.len() 162 | } 163 | 164 | /// Push `element` to the end of the vector. 165 | /// 166 | /// ***Panics*** if the vector is already full. 167 | /// 168 | /// ``` 169 | /// use arrayvec::ArrayVec; 170 | /// 171 | /// let mut array = ArrayVec::<_, 2>::new(); 172 | /// 173 | /// array.push(1); 174 | /// array.push(2); 175 | /// 176 | /// assert_eq!(&array[..], &[1, 2]); 177 | /// ``` 178 | #[track_caller] 179 | pub fn push(&mut self, element: T) { 180 | ArrayVecImpl::push(self, element) 181 | } 182 | 183 | /// Push `element` to the end of the vector. 184 | /// 185 | /// Return `Ok` if the push succeeds, or return an error if the vector 186 | /// is already full. 187 | /// 188 | /// ``` 189 | /// use arrayvec::ArrayVec; 190 | /// 191 | /// let mut array = ArrayVec::<_, 2>::new(); 192 | /// 193 | /// let push1 = array.try_push(1); 194 | /// let push2 = array.try_push(2); 195 | /// 196 | /// assert!(push1.is_ok()); 197 | /// assert!(push2.is_ok()); 198 | /// 199 | /// assert_eq!(&array[..], &[1, 2]); 200 | /// 201 | /// let overflow = array.try_push(3); 202 | /// 203 | /// assert!(overflow.is_err()); 204 | /// ``` 205 | pub fn try_push(&mut self, element: T) -> Result<(), CapacityError> { 206 | ArrayVecImpl::try_push(self, element) 207 | } 208 | 209 | /// Push `element` to the end of the vector without checking the capacity. 210 | /// 211 | /// It is up to the caller to ensure the capacity of the vector is 212 | /// sufficiently large. 213 | /// 214 | /// This method uses *debug assertions* to check that the arrayvec is not full. 215 | /// 216 | /// ``` 217 | /// use arrayvec::ArrayVec; 218 | /// 219 | /// let mut array = ArrayVec::<_, 2>::new(); 220 | /// 221 | /// if array.len() + 2 <= array.capacity() { 222 | /// unsafe { 223 | /// array.push_unchecked(1); 224 | /// array.push_unchecked(2); 225 | /// } 226 | /// } 227 | /// 228 | /// assert_eq!(&array[..], &[1, 2]); 229 | /// ``` 230 | pub unsafe fn push_unchecked(&mut self, element: T) { 231 | ArrayVecImpl::push_unchecked(self, element) 232 | } 233 | 234 | /// Shortens the vector, keeping the first `len` elements and dropping 235 | /// the rest. 236 | /// 237 | /// If `len` is greater than the vector’s current length this has no 238 | /// effect. 239 | /// 240 | /// ``` 241 | /// use arrayvec::ArrayVec; 242 | /// 243 | /// let mut array = ArrayVec::from([1, 2, 3, 4, 5]); 244 | /// array.truncate(3); 245 | /// assert_eq!(&array[..], &[1, 2, 3]); 246 | /// array.truncate(4); 247 | /// assert_eq!(&array[..], &[1, 2, 3]); 248 | /// ``` 249 | pub fn truncate(&mut self, new_len: usize) { 250 | ArrayVecImpl::truncate(self, new_len) 251 | } 252 | 253 | /// Remove all elements in the vector. 254 | pub fn clear(&mut self) { 255 | ArrayVecImpl::clear(self) 256 | } 257 | 258 | 259 | /// Get pointer to where element at `index` would be 260 | unsafe fn get_unchecked_ptr(&mut self, index: usize) -> *mut T { 261 | self.as_mut_ptr().add(index) 262 | } 263 | 264 | /// Insert `element` at position `index`. 265 | /// 266 | /// Shift up all elements after `index`. 267 | /// 268 | /// It is an error if the index is greater than the length or if the 269 | /// arrayvec is full. 270 | /// 271 | /// ***Panics*** if the array is full or the `index` is out of bounds. See 272 | /// `try_insert` for fallible version. 273 | /// 274 | /// ``` 275 | /// use arrayvec::ArrayVec; 276 | /// 277 | /// let mut array = ArrayVec::<_, 2>::new(); 278 | /// 279 | /// array.insert(0, "x"); 280 | /// array.insert(0, "y"); 281 | /// assert_eq!(&array[..], &["y", "x"]); 282 | /// 283 | /// ``` 284 | #[track_caller] 285 | pub fn insert(&mut self, index: usize, element: T) { 286 | self.try_insert(index, element).unwrap() 287 | } 288 | 289 | /// Insert `element` at position `index`. 290 | /// 291 | /// Shift up all elements after `index`; the `index` must be less than 292 | /// or equal to the length. 293 | /// 294 | /// Returns an error if vector is already at full capacity. 295 | /// 296 | /// ***Panics*** `index` is out of bounds. 297 | /// 298 | /// ``` 299 | /// use arrayvec::ArrayVec; 300 | /// 301 | /// let mut array = ArrayVec::<_, 2>::new(); 302 | /// 303 | /// assert!(array.try_insert(0, "x").is_ok()); 304 | /// assert!(array.try_insert(0, "y").is_ok()); 305 | /// assert!(array.try_insert(0, "z").is_err()); 306 | /// assert_eq!(&array[..], &["y", "x"]); 307 | /// 308 | /// ``` 309 | pub fn try_insert(&mut self, index: usize, element: T) -> Result<(), CapacityError> { 310 | if index > self.len() { 311 | panic_oob!("try_insert", index, self.len()) 312 | } 313 | if self.len() == self.capacity() { 314 | return Err(CapacityError::new(element)); 315 | } 316 | let len = self.len(); 317 | 318 | // follows is just like Vec 319 | unsafe { // infallible 320 | // The spot to put the new value 321 | { 322 | let p: *mut _ = self.get_unchecked_ptr(index); 323 | // Shift everything over to make space. (Duplicating the 324 | // `index`th element into two consecutive places.) 325 | ptr::copy(p, p.offset(1), len - index); 326 | // Write it in, overwriting the first copy of the `index`th 327 | // element. 328 | ptr::write(p, element); 329 | } 330 | self.set_len(len + 1); 331 | } 332 | Ok(()) 333 | } 334 | 335 | /// Remove the last element in the vector and return it. 336 | /// 337 | /// Return `Some(` *element* `)` if the vector is non-empty, else `None`. 338 | /// 339 | /// ``` 340 | /// use arrayvec::ArrayVec; 341 | /// 342 | /// let mut array = ArrayVec::<_, 2>::new(); 343 | /// 344 | /// array.push(1); 345 | /// 346 | /// assert_eq!(array.pop(), Some(1)); 347 | /// assert_eq!(array.pop(), None); 348 | /// ``` 349 | pub fn pop(&mut self) -> Option { 350 | ArrayVecImpl::pop(self) 351 | } 352 | 353 | /// Remove the element at `index` and swap the last element into its place. 354 | /// 355 | /// This operation is O(1). 356 | /// 357 | /// Return the *element* if the index is in bounds, else panic. 358 | /// 359 | /// ***Panics*** if the `index` is out of bounds. 360 | /// 361 | /// ``` 362 | /// use arrayvec::ArrayVec; 363 | /// 364 | /// let mut array = ArrayVec::from([1, 2, 3]); 365 | /// 366 | /// assert_eq!(array.swap_remove(0), 1); 367 | /// assert_eq!(&array[..], &[3, 2]); 368 | /// 369 | /// assert_eq!(array.swap_remove(1), 2); 370 | /// assert_eq!(&array[..], &[3]); 371 | /// ``` 372 | pub fn swap_remove(&mut self, index: usize) -> T { 373 | self.swap_pop(index) 374 | .unwrap_or_else(|| { 375 | panic_oob!("swap_remove", index, self.len()) 376 | }) 377 | } 378 | 379 | /// Remove the element at `index` and swap the last element into its place. 380 | /// 381 | /// This is a checked version of `.swap_remove`. 382 | /// This operation is O(1). 383 | /// 384 | /// Return `Some(` *element* `)` if the index is in bounds, else `None`. 385 | /// 386 | /// ``` 387 | /// use arrayvec::ArrayVec; 388 | /// 389 | /// let mut array = ArrayVec::from([1, 2, 3]); 390 | /// 391 | /// assert_eq!(array.swap_pop(0), Some(1)); 392 | /// assert_eq!(&array[..], &[3, 2]); 393 | /// 394 | /// assert_eq!(array.swap_pop(10), None); 395 | /// ``` 396 | pub fn swap_pop(&mut self, index: usize) -> Option { 397 | let len = self.len(); 398 | if index >= len { 399 | return None; 400 | } 401 | self.swap(index, len - 1); 402 | self.pop() 403 | } 404 | 405 | /// Remove the element at `index` and shift down the following elements. 406 | /// 407 | /// The `index` must be strictly less than the length of the vector. 408 | /// 409 | /// ***Panics*** if the `index` is out of bounds. 410 | /// 411 | /// ``` 412 | /// use arrayvec::ArrayVec; 413 | /// 414 | /// let mut array = ArrayVec::from([1, 2, 3]); 415 | /// 416 | /// let removed_elt = array.remove(0); 417 | /// assert_eq!(removed_elt, 1); 418 | /// assert_eq!(&array[..], &[2, 3]); 419 | /// ``` 420 | pub fn remove(&mut self, index: usize) -> T { 421 | self.pop_at(index) 422 | .unwrap_or_else(|| { 423 | panic_oob!("remove", index, self.len()) 424 | }) 425 | } 426 | 427 | /// Remove the element at `index` and shift down the following elements. 428 | /// 429 | /// This is a checked version of `.remove(index)`. Returns `None` if there 430 | /// is no element at `index`. Otherwise, return the element inside `Some`. 431 | /// 432 | /// ``` 433 | /// use arrayvec::ArrayVec; 434 | /// 435 | /// let mut array = ArrayVec::from([1, 2, 3]); 436 | /// 437 | /// assert!(array.pop_at(0).is_some()); 438 | /// assert_eq!(&array[..], &[2, 3]); 439 | /// 440 | /// assert!(array.pop_at(2).is_none()); 441 | /// assert!(array.pop_at(10).is_none()); 442 | /// ``` 443 | pub fn pop_at(&mut self, index: usize) -> Option { 444 | if index >= self.len() { 445 | None 446 | } else { 447 | self.drain(index..index + 1).next() 448 | } 449 | } 450 | 451 | /// Retains only the elements specified by the predicate. 452 | /// 453 | /// In other words, remove all elements `e` such that `f(&mut e)` returns false. 454 | /// This method operates in place and preserves the order of the retained 455 | /// elements. 456 | /// 457 | /// ``` 458 | /// use arrayvec::ArrayVec; 459 | /// 460 | /// let mut array = ArrayVec::from([1, 2, 3, 4]); 461 | /// array.retain(|x| *x & 1 != 0 ); 462 | /// assert_eq!(&array[..], &[1, 3]); 463 | /// ``` 464 | pub fn retain(&mut self, mut f: F) 465 | where F: FnMut(&mut T) -> bool 466 | { 467 | // Check the implementation of 468 | // https://doc.rust-lang.org/std/vec/struct.Vec.html#method.retain 469 | // for safety arguments (especially regarding panics in f and when 470 | // dropping elements). Implementation closely mirrored here. 471 | 472 | let original_len = self.len(); 473 | unsafe { self.set_len(0) }; 474 | 475 | struct BackshiftOnDrop<'a, T, const CAP: usize> { 476 | v: &'a mut ArrayVec, 477 | processed_len: usize, 478 | deleted_cnt: usize, 479 | original_len: usize, 480 | } 481 | 482 | impl Drop for BackshiftOnDrop<'_, T, CAP> { 483 | fn drop(&mut self) { 484 | if self.deleted_cnt > 0 { 485 | unsafe { 486 | ptr::copy( 487 | self.v.as_ptr().add(self.processed_len), 488 | self.v.as_mut_ptr().add(self.processed_len - self.deleted_cnt), 489 | self.original_len - self.processed_len 490 | ); 491 | } 492 | } 493 | unsafe { 494 | self.v.set_len(self.original_len - self.deleted_cnt); 495 | } 496 | } 497 | } 498 | 499 | let mut g = BackshiftOnDrop { v: self, processed_len: 0, deleted_cnt: 0, original_len }; 500 | 501 | #[inline(always)] 502 | fn process_one bool, T, const CAP: usize, const DELETED: bool>( 503 | f: &mut F, 504 | g: &mut BackshiftOnDrop<'_, T, CAP> 505 | ) -> bool { 506 | let cur = unsafe { g.v.as_mut_ptr().add(g.processed_len) }; 507 | if !f(unsafe { &mut *cur }) { 508 | g.processed_len += 1; 509 | g.deleted_cnt += 1; 510 | unsafe { ptr::drop_in_place(cur) }; 511 | return false; 512 | } 513 | if DELETED { 514 | unsafe { 515 | let hole_slot = cur.sub(g.deleted_cnt); 516 | ptr::copy_nonoverlapping(cur, hole_slot, 1); 517 | } 518 | } 519 | g.processed_len += 1; 520 | true 521 | } 522 | 523 | // Stage 1: Nothing was deleted. 524 | while g.processed_len != original_len { 525 | if !process_one::(&mut f, &mut g) { 526 | break; 527 | } 528 | } 529 | 530 | // Stage 2: Some elements were deleted. 531 | while g.processed_len != original_len { 532 | process_one::(&mut f, &mut g); 533 | } 534 | 535 | drop(g); 536 | } 537 | 538 | /// Returns the remaining spare capacity of the vector as a slice of 539 | /// `MaybeUninit`. 540 | /// 541 | /// The returned slice can be used to fill the vector with data (e.g. by 542 | /// reading from a file) before marking the data as initialized using the 543 | /// [`set_len`] method. 544 | /// 545 | /// [`set_len`]: ArrayVec::set_len 546 | /// 547 | /// # Examples 548 | /// 549 | /// ``` 550 | /// use arrayvec::ArrayVec; 551 | /// 552 | /// // Allocate vector big enough for 10 elements. 553 | /// let mut v: ArrayVec = ArrayVec::new(); 554 | /// 555 | /// // Fill in the first 3 elements. 556 | /// let uninit = v.spare_capacity_mut(); 557 | /// uninit[0].write(0); 558 | /// uninit[1].write(1); 559 | /// uninit[2].write(2); 560 | /// 561 | /// // Mark the first 3 elements of the vector as being initialized. 562 | /// unsafe { 563 | /// v.set_len(3); 564 | /// } 565 | /// 566 | /// assert_eq!(&v[..], &[0, 1, 2]); 567 | /// ``` 568 | pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit] { 569 | let len = self.len(); 570 | &mut self.xs[len..] 571 | } 572 | 573 | /// Set the vector’s length without dropping or moving out elements 574 | /// 575 | /// This method is `unsafe` because it changes the notion of the 576 | /// number of “valid” elements in the vector. Use with care. 577 | /// 578 | /// This method uses *debug assertions* to check that `length` is 579 | /// not greater than the capacity. 580 | pub unsafe fn set_len(&mut self, length: usize) { 581 | // type invariant that capacity always fits in LenUint 582 | debug_assert!(length <= self.capacity()); 583 | self.len = length as LenUint; 584 | } 585 | 586 | /// Copy all elements from the slice and append to the `ArrayVec`. 587 | /// 588 | /// ``` 589 | /// use arrayvec::ArrayVec; 590 | /// 591 | /// let mut vec: ArrayVec = ArrayVec::new(); 592 | /// vec.push(1); 593 | /// vec.try_extend_from_slice(&[2, 3]).unwrap(); 594 | /// assert_eq!(&vec[..], &[1, 2, 3]); 595 | /// ``` 596 | /// 597 | /// # Errors 598 | /// 599 | /// This method will return an error if the capacity left (see 600 | /// [`remaining_capacity`]) is smaller then the length of the provided 601 | /// slice. 602 | /// 603 | /// [`remaining_capacity`]: #method.remaining_capacity 604 | pub fn try_extend_from_slice(&mut self, other: &[T]) -> Result<(), CapacityError> 605 | where T: Copy, 606 | { 607 | if self.remaining_capacity() < other.len() { 608 | return Err(CapacityError::new(())); 609 | } 610 | 611 | let self_len = self.len(); 612 | let other_len = other.len(); 613 | 614 | unsafe { 615 | let dst = self.get_unchecked_ptr(self_len); 616 | ptr::copy_nonoverlapping(other.as_ptr(), dst, other_len); 617 | self.set_len(self_len + other_len); 618 | } 619 | Ok(()) 620 | } 621 | 622 | /// Create a draining iterator that removes the specified range in the vector 623 | /// and yields the removed items from start to end. The element range is 624 | /// removed even if the iterator is not consumed until the end. 625 | /// 626 | /// Note: It is unspecified how many elements are removed from the vector, 627 | /// if the `Drain` value is leaked. 628 | /// 629 | /// **Panics** if the starting point is greater than the end point or if 630 | /// the end point is greater than the length of the vector. 631 | /// 632 | /// ``` 633 | /// use arrayvec::ArrayVec; 634 | /// 635 | /// let mut v1 = ArrayVec::from([1, 2, 3]); 636 | /// let v2: ArrayVec<_, 3> = v1.drain(0..2).collect(); 637 | /// assert_eq!(&v1[..], &[3]); 638 | /// assert_eq!(&v2[..], &[1, 2]); 639 | /// ``` 640 | pub fn drain(&mut self, range: R) -> Drain 641 | where R: RangeBounds 642 | { 643 | // Memory safety 644 | // 645 | // When the Drain is first created, it shortens the length of 646 | // the source vector to make sure no uninitialized or moved-from elements 647 | // are accessible at all if the Drain's destructor never gets to run. 648 | // 649 | // Drain will ptr::read out the values to remove. 650 | // When finished, remaining tail of the vec is copied back to cover 651 | // the hole, and the vector length is restored to the new length. 652 | // 653 | let len = self.len(); 654 | let start = match range.start_bound() { 655 | Bound::Unbounded => 0, 656 | Bound::Included(&i) => i, 657 | Bound::Excluded(&i) => i.saturating_add(1), 658 | }; 659 | let end = match range.end_bound() { 660 | Bound::Excluded(&j) => j, 661 | Bound::Included(&j) => j.saturating_add(1), 662 | Bound::Unbounded => len, 663 | }; 664 | self.drain_range(start, end) 665 | } 666 | 667 | fn drain_range(&mut self, start: usize, end: usize) -> Drain 668 | { 669 | let len = self.len(); 670 | 671 | // bounds check happens here (before length is changed!) 672 | let range_slice: *const _ = &self[start..end]; 673 | 674 | // Calling `set_len` creates a fresh and thus unique mutable references, making all 675 | // older aliases we created invalid. So we cannot call that function. 676 | self.len = start as LenUint; 677 | 678 | unsafe { 679 | Drain { 680 | tail_start: end, 681 | tail_len: len - end, 682 | iter: (*range_slice).iter(), 683 | vec: self as *mut _, 684 | } 685 | } 686 | } 687 | 688 | /// Return the inner fixed size array, if it is full to its capacity. 689 | /// 690 | /// Return an `Ok` value with the array if length equals capacity, 691 | /// return an `Err` with self otherwise. 692 | pub fn into_inner(self) -> Result<[T; CAP], Self> { 693 | if self.len() < self.capacity() { 694 | Err(self) 695 | } else { 696 | unsafe { Ok(self.into_inner_unchecked()) } 697 | } 698 | } 699 | 700 | /// Return the inner fixed size array. 701 | /// 702 | /// Safety: 703 | /// This operation is safe if and only if length equals capacity. 704 | pub unsafe fn into_inner_unchecked(self) -> [T; CAP] { 705 | debug_assert_eq!(self.len(), self.capacity()); 706 | let self_ = ManuallyDrop::new(self); 707 | let array = ptr::read(self_.as_ptr() as *const [T; CAP]); 708 | array 709 | } 710 | 711 | /// Returns the ArrayVec, replacing the original with a new empty ArrayVec. 712 | /// 713 | /// ``` 714 | /// use arrayvec::ArrayVec; 715 | /// 716 | /// let mut v = ArrayVec::from([0, 1, 2, 3]); 717 | /// assert_eq!([0, 1, 2, 3], v.take().into_inner().unwrap()); 718 | /// assert!(v.is_empty()); 719 | /// ``` 720 | pub fn take(&mut self) -> Self { 721 | mem::replace(self, Self::new()) 722 | } 723 | 724 | /// Return a slice containing all elements of the vector. 725 | pub fn as_slice(&self) -> &[T] { 726 | ArrayVecImpl::as_slice(self) 727 | } 728 | 729 | /// Return a mutable slice containing all elements of the vector. 730 | pub fn as_mut_slice(&mut self) -> &mut [T] { 731 | ArrayVecImpl::as_mut_slice(self) 732 | } 733 | 734 | /// Return a raw pointer to the vector's buffer. 735 | pub fn as_ptr(&self) -> *const T { 736 | ArrayVecImpl::as_ptr(self) 737 | } 738 | 739 | /// Return a raw mutable pointer to the vector's buffer. 740 | pub fn as_mut_ptr(&mut self) -> *mut T { 741 | ArrayVecImpl::as_mut_ptr(self) 742 | } 743 | } 744 | 745 | impl ArrayVecImpl for ArrayVec { 746 | type Item = T; 747 | const CAPACITY: usize = CAP; 748 | 749 | fn len(&self) -> usize { self.len() } 750 | 751 | unsafe fn set_len(&mut self, length: usize) { 752 | debug_assert!(length <= CAP); 753 | self.len = length as LenUint; 754 | } 755 | 756 | fn as_ptr(&self) -> *const Self::Item { 757 | self.xs.as_ptr() as _ 758 | } 759 | 760 | fn as_mut_ptr(&mut self) -> *mut Self::Item { 761 | self.xs.as_mut_ptr() as _ 762 | } 763 | } 764 | 765 | impl Deref for ArrayVec { 766 | type Target = [T]; 767 | #[inline] 768 | fn deref(&self) -> &Self::Target { 769 | self.as_slice() 770 | } 771 | } 772 | 773 | impl DerefMut for ArrayVec { 774 | #[inline] 775 | fn deref_mut(&mut self) -> &mut Self::Target { 776 | self.as_mut_slice() 777 | } 778 | } 779 | 780 | 781 | /// Create an `ArrayVec` from an array. 782 | /// 783 | /// ``` 784 | /// use arrayvec::ArrayVec; 785 | /// 786 | /// let mut array = ArrayVec::from([1, 2, 3]); 787 | /// assert_eq!(array.len(), 3); 788 | /// assert_eq!(array.capacity(), 3); 789 | /// ``` 790 | impl From<[T; CAP]> for ArrayVec { 791 | #[track_caller] 792 | fn from(array: [T; CAP]) -> Self { 793 | let array = ManuallyDrop::new(array); 794 | let mut vec = >::new(); 795 | unsafe { 796 | (&*array as *const [T; CAP] as *const [MaybeUninit; CAP]) 797 | .copy_to_nonoverlapping(&mut vec.xs as *mut [MaybeUninit; CAP], 1); 798 | vec.set_len(CAP); 799 | } 800 | vec 801 | } 802 | } 803 | 804 | 805 | /// Try to create an `ArrayVec` from a slice. This will return an error if the slice was too big to 806 | /// fit. 807 | /// 808 | /// ``` 809 | /// use arrayvec::ArrayVec; 810 | /// use std::convert::TryInto as _; 811 | /// 812 | /// let array: ArrayVec<_, 4> = (&[1, 2, 3] as &[_]).try_into().unwrap(); 813 | /// assert_eq!(array.len(), 3); 814 | /// assert_eq!(array.capacity(), 4); 815 | /// ``` 816 | impl std::convert::TryFrom<&[T]> for ArrayVec 817 | where T: Clone, 818 | { 819 | type Error = CapacityError; 820 | 821 | fn try_from(slice: &[T]) -> Result { 822 | if Self::CAPACITY < slice.len() { 823 | Err(CapacityError::new(())) 824 | } else { 825 | let mut array = Self::new(); 826 | array.extend_from_slice(slice); 827 | Ok(array) 828 | } 829 | } 830 | } 831 | 832 | 833 | /// Iterate the `ArrayVec` with references to each element. 834 | /// 835 | /// ``` 836 | /// use arrayvec::ArrayVec; 837 | /// 838 | /// let array = ArrayVec::from([1, 2, 3]); 839 | /// 840 | /// for elt in &array { 841 | /// // ... 842 | /// } 843 | /// ``` 844 | impl<'a, T: 'a, const CAP: usize> IntoIterator for &'a ArrayVec { 845 | type Item = &'a T; 846 | type IntoIter = slice::Iter<'a, T>; 847 | fn into_iter(self) -> Self::IntoIter { self.iter() } 848 | } 849 | 850 | /// Iterate the `ArrayVec` with mutable references to each element. 851 | /// 852 | /// ``` 853 | /// use arrayvec::ArrayVec; 854 | /// 855 | /// let mut array = ArrayVec::from([1, 2, 3]); 856 | /// 857 | /// for elt in &mut array { 858 | /// // ... 859 | /// } 860 | /// ``` 861 | impl<'a, T: 'a, const CAP: usize> IntoIterator for &'a mut ArrayVec { 862 | type Item = &'a mut T; 863 | type IntoIter = slice::IterMut<'a, T>; 864 | fn into_iter(self) -> Self::IntoIter { self.iter_mut() } 865 | } 866 | 867 | /// Iterate the `ArrayVec` with each element by value. 868 | /// 869 | /// The vector is consumed by this operation. 870 | /// 871 | /// ``` 872 | /// use arrayvec::ArrayVec; 873 | /// 874 | /// for elt in ArrayVec::from([1, 2, 3]) { 875 | /// // ... 876 | /// } 877 | /// ``` 878 | impl IntoIterator for ArrayVec { 879 | type Item = T; 880 | type IntoIter = IntoIter; 881 | fn into_iter(self) -> IntoIter { 882 | IntoIter { index: 0, v: self, } 883 | } 884 | } 885 | 886 | 887 | #[cfg(feature = "zeroize")] 888 | /// "Best efforts" zeroing of the `ArrayVec`'s buffer when the `zeroize` feature is enabled. 889 | /// 890 | /// The length is set to 0, and the buffer is dropped and zeroized. 891 | /// Cannot ensure that previous moves of the `ArrayVec` did not leave values on the stack. 892 | /// 893 | /// ``` 894 | /// use arrayvec::ArrayVec; 895 | /// use zeroize::Zeroize; 896 | /// let mut array = ArrayVec::from([1, 2, 3]); 897 | /// array.zeroize(); 898 | /// assert_eq!(array.len(), 0); 899 | /// let data = unsafe { core::slice::from_raw_parts(array.as_ptr(), array.capacity()) }; 900 | /// assert_eq!(data, [0, 0, 0]); 901 | /// ``` 902 | impl zeroize::Zeroize for ArrayVec { 903 | fn zeroize(&mut self) { 904 | // Zeroize all the contained elements. 905 | self.iter_mut().zeroize(); 906 | // Drop all the elements and set the length to 0. 907 | self.clear(); 908 | // Zeroize the backing array. 909 | self.xs.zeroize(); 910 | } 911 | } 912 | 913 | /// By-value iterator for `ArrayVec`. 914 | pub struct IntoIter { 915 | index: usize, 916 | v: ArrayVec, 917 | } 918 | impl IntoIter { 919 | /// Returns the remaining items of this iterator as a slice. 920 | pub fn as_slice(&self) -> &[T] { 921 | &self.v[self.index..] 922 | } 923 | 924 | /// Returns the remaining items of this iterator as a mutable slice. 925 | pub fn as_mut_slice(&mut self) -> &mut [T] { 926 | &mut self.v[self.index..] 927 | } 928 | } 929 | 930 | impl Iterator for IntoIter { 931 | type Item = T; 932 | 933 | fn next(&mut self) -> Option { 934 | if self.index == self.v.len() { 935 | None 936 | } else { 937 | unsafe { 938 | let index = self.index; 939 | self.index = index + 1; 940 | Some(ptr::read(self.v.get_unchecked_ptr(index))) 941 | } 942 | } 943 | } 944 | 945 | fn size_hint(&self) -> (usize, Option) { 946 | let len = self.v.len() - self.index; 947 | (len, Some(len)) 948 | } 949 | } 950 | 951 | impl DoubleEndedIterator for IntoIter { 952 | fn next_back(&mut self) -> Option { 953 | if self.index == self.v.len() { 954 | None 955 | } else { 956 | unsafe { 957 | let new_len = self.v.len() - 1; 958 | self.v.set_len(new_len); 959 | Some(ptr::read(self.v.get_unchecked_ptr(new_len))) 960 | } 961 | } 962 | } 963 | } 964 | 965 | impl ExactSizeIterator for IntoIter { } 966 | 967 | impl Drop for IntoIter { 968 | fn drop(&mut self) { 969 | // panic safety: Set length to 0 before dropping elements. 970 | let index = self.index; 971 | let len = self.v.len(); 972 | unsafe { 973 | self.v.set_len(0); 974 | let elements = slice::from_raw_parts_mut( 975 | self.v.get_unchecked_ptr(index), 976 | len - index); 977 | ptr::drop_in_place(elements); 978 | } 979 | } 980 | } 981 | 982 | impl Clone for IntoIter 983 | where T: Clone, 984 | { 985 | fn clone(&self) -> IntoIter { 986 | let mut v = ArrayVec::new(); 987 | v.extend_from_slice(&self.v[self.index..]); 988 | v.into_iter() 989 | } 990 | } 991 | 992 | impl fmt::Debug for IntoIter 993 | where 994 | T: fmt::Debug, 995 | { 996 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 997 | f.debug_list() 998 | .entries(&self.v[self.index..]) 999 | .finish() 1000 | } 1001 | } 1002 | 1003 | /// A draining iterator for `ArrayVec`. 1004 | pub struct Drain<'a, T: 'a, const CAP: usize> { 1005 | /// Index of tail to preserve 1006 | tail_start: usize, 1007 | /// Length of tail 1008 | tail_len: usize, 1009 | /// Current remaining range to remove 1010 | iter: slice::Iter<'a, T>, 1011 | vec: *mut ArrayVec, 1012 | } 1013 | 1014 | unsafe impl<'a, T: Sync, const CAP: usize> Sync for Drain<'a, T, CAP> {} 1015 | unsafe impl<'a, T: Send, const CAP: usize> Send for Drain<'a, T, CAP> {} 1016 | 1017 | impl<'a, T: 'a, const CAP: usize> Iterator for Drain<'a, T, CAP> { 1018 | type Item = T; 1019 | 1020 | fn next(&mut self) -> Option { 1021 | self.iter.next().map(|elt| 1022 | unsafe { 1023 | ptr::read(elt as *const _) 1024 | } 1025 | ) 1026 | } 1027 | 1028 | fn size_hint(&self) -> (usize, Option) { 1029 | self.iter.size_hint() 1030 | } 1031 | } 1032 | 1033 | impl<'a, T: 'a, const CAP: usize> DoubleEndedIterator for Drain<'a, T, CAP> 1034 | { 1035 | fn next_back(&mut self) -> Option { 1036 | self.iter.next_back().map(|elt| 1037 | unsafe { 1038 | ptr::read(elt as *const _) 1039 | } 1040 | ) 1041 | } 1042 | } 1043 | 1044 | impl<'a, T: 'a, const CAP: usize> ExactSizeIterator for Drain<'a, T, CAP> {} 1045 | 1046 | impl<'a, T: 'a, const CAP: usize> Drop for Drain<'a, T, CAP> { 1047 | fn drop(&mut self) { 1048 | // len is currently 0 so panicking while dropping will not cause a double drop. 1049 | 1050 | // exhaust self first 1051 | while let Some(_) = self.next() { } 1052 | 1053 | if self.tail_len > 0 { 1054 | unsafe { 1055 | let source_vec = &mut *self.vec; 1056 | // memmove back untouched tail, update to new length 1057 | let start = source_vec.len(); 1058 | let tail = self.tail_start; 1059 | let ptr = source_vec.as_mut_ptr(); 1060 | ptr::copy(ptr.add(tail), ptr.add(start), self.tail_len); 1061 | source_vec.set_len(start + self.tail_len); 1062 | } 1063 | } 1064 | } 1065 | } 1066 | 1067 | struct ScopeExitGuard 1068 | where F: FnMut(&Data, &mut T) 1069 | { 1070 | value: T, 1071 | data: Data, 1072 | f: F, 1073 | } 1074 | 1075 | impl Drop for ScopeExitGuard 1076 | where F: FnMut(&Data, &mut T) 1077 | { 1078 | fn drop(&mut self) { 1079 | (self.f)(&self.data, &mut self.value) 1080 | } 1081 | } 1082 | 1083 | 1084 | 1085 | /// Extend the `ArrayVec` with an iterator. 1086 | /// 1087 | /// ***Panics*** if extending the vector exceeds its capacity. 1088 | impl Extend for ArrayVec { 1089 | /// Extend the `ArrayVec` with an iterator. 1090 | /// 1091 | /// ***Panics*** if extending the vector exceeds its capacity. 1092 | #[track_caller] 1093 | fn extend>(&mut self, iter: I) { 1094 | unsafe { 1095 | self.extend_from_iter::<_, true>(iter) 1096 | } 1097 | } 1098 | } 1099 | 1100 | #[inline(never)] 1101 | #[cold] 1102 | #[track_caller] 1103 | fn extend_panic() { 1104 | panic!("ArrayVec: capacity exceeded in extend/from_iter"); 1105 | } 1106 | 1107 | impl ArrayVec { 1108 | /// Extend the arrayvec from the iterable. 1109 | /// 1110 | /// ## Safety 1111 | /// 1112 | /// Unsafe because if CHECK is false, the length of the input is not checked. 1113 | /// The caller must ensure the length of the input fits in the capacity. 1114 | #[track_caller] 1115 | pub(crate) unsafe fn extend_from_iter(&mut self, iterable: I) 1116 | where I: IntoIterator 1117 | { 1118 | let take = self.capacity() - self.len(); 1119 | let len = self.len(); 1120 | let mut ptr = raw_ptr_add(self.as_mut_ptr(), len); 1121 | let end_ptr = raw_ptr_add(ptr, take); 1122 | // Keep the length in a separate variable, write it back on scope 1123 | // exit. To help the compiler with alias analysis and stuff. 1124 | // We update the length to handle panic in the iteration of the 1125 | // user's iterator, without dropping any elements on the floor. 1126 | let mut guard = ScopeExitGuard { 1127 | value: &mut self.len, 1128 | data: len, 1129 | f: move |&len, self_len| { 1130 | **self_len = len as LenUint; 1131 | } 1132 | }; 1133 | let mut iter = iterable.into_iter(); 1134 | loop { 1135 | if let Some(elt) = iter.next() { 1136 | if ptr == end_ptr && CHECK { extend_panic(); } 1137 | debug_assert_ne!(ptr, end_ptr); 1138 | if mem::size_of::() != 0 { 1139 | ptr.write(elt); 1140 | } 1141 | ptr = raw_ptr_add(ptr, 1); 1142 | guard.data += 1; 1143 | } else { 1144 | return; // success 1145 | } 1146 | } 1147 | } 1148 | 1149 | /// Extend the ArrayVec with clones of elements from the slice; 1150 | /// the length of the slice must be <= the remaining capacity in the arrayvec. 1151 | pub(crate) fn extend_from_slice(&mut self, slice: &[T]) 1152 | where T: Clone 1153 | { 1154 | let take = self.capacity() - self.len(); 1155 | debug_assert!(slice.len() <= take); 1156 | unsafe { 1157 | let slice = if take < slice.len() { &slice[..take] } else { slice }; 1158 | self.extend_from_iter::<_, false>(slice.iter().cloned()); 1159 | } 1160 | } 1161 | } 1162 | 1163 | /// Rawptr add but uses arithmetic distance for ZST 1164 | unsafe fn raw_ptr_add(ptr: *mut T, offset: usize) -> *mut T { 1165 | if mem::size_of::() == 0 { 1166 | // Special case for ZST 1167 | ptr.cast::().wrapping_add(offset).cast::() 1168 | } else { 1169 | ptr.add(offset) 1170 | } 1171 | } 1172 | 1173 | /// Create an `ArrayVec` from an iterator. 1174 | /// 1175 | /// ***Panics*** if the number of elements in the iterator exceeds the arrayvec's capacity. 1176 | impl iter::FromIterator for ArrayVec { 1177 | /// Create an `ArrayVec` from an iterator. 1178 | /// 1179 | /// ***Panics*** if the number of elements in the iterator exceeds the arrayvec's capacity. 1180 | fn from_iter>(iter: I) -> Self { 1181 | let mut array = ArrayVec::new(); 1182 | array.extend(iter); 1183 | array 1184 | } 1185 | } 1186 | 1187 | impl Clone for ArrayVec 1188 | where T: Clone 1189 | { 1190 | fn clone(&self) -> Self { 1191 | self.iter().cloned().collect() 1192 | } 1193 | 1194 | fn clone_from(&mut self, rhs: &Self) { 1195 | // recursive case for the common prefix 1196 | let prefix = cmp::min(self.len(), rhs.len()); 1197 | self[..prefix].clone_from_slice(&rhs[..prefix]); 1198 | 1199 | if prefix < self.len() { 1200 | // rhs was shorter 1201 | self.truncate(prefix); 1202 | } else { 1203 | let rhs_elems = &rhs[self.len()..]; 1204 | self.extend_from_slice(rhs_elems); 1205 | } 1206 | } 1207 | } 1208 | 1209 | impl Hash for ArrayVec 1210 | where T: Hash 1211 | { 1212 | fn hash(&self, state: &mut H) { 1213 | Hash::hash(&**self, state) 1214 | } 1215 | } 1216 | 1217 | impl PartialEq for ArrayVec 1218 | where T: PartialEq 1219 | { 1220 | fn eq(&self, other: &Self) -> bool { 1221 | **self == **other 1222 | } 1223 | } 1224 | 1225 | impl PartialEq<[T]> for ArrayVec 1226 | where T: PartialEq 1227 | { 1228 | fn eq(&self, other: &[T]) -> bool { 1229 | **self == *other 1230 | } 1231 | } 1232 | 1233 | impl Eq for ArrayVec where T: Eq { } 1234 | 1235 | impl Borrow<[T]> for ArrayVec { 1236 | fn borrow(&self) -> &[T] { self } 1237 | } 1238 | 1239 | impl BorrowMut<[T]> for ArrayVec { 1240 | fn borrow_mut(&mut self) -> &mut [T] { self } 1241 | } 1242 | 1243 | impl AsRef<[T]> for ArrayVec { 1244 | fn as_ref(&self) -> &[T] { self } 1245 | } 1246 | 1247 | impl AsMut<[T]> for ArrayVec { 1248 | fn as_mut(&mut self) -> &mut [T] { self } 1249 | } 1250 | 1251 | impl fmt::Debug for ArrayVec where T: fmt::Debug { 1252 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } 1253 | } 1254 | 1255 | impl Default for ArrayVec { 1256 | /// Return an empty array 1257 | fn default() -> ArrayVec { 1258 | ArrayVec::new() 1259 | } 1260 | } 1261 | 1262 | impl PartialOrd for ArrayVec where T: PartialOrd { 1263 | fn partial_cmp(&self, other: &Self) -> Option { 1264 | (**self).partial_cmp(other) 1265 | } 1266 | 1267 | fn lt(&self, other: &Self) -> bool { 1268 | (**self).lt(other) 1269 | } 1270 | 1271 | fn le(&self, other: &Self) -> bool { 1272 | (**self).le(other) 1273 | } 1274 | 1275 | fn ge(&self, other: &Self) -> bool { 1276 | (**self).ge(other) 1277 | } 1278 | 1279 | fn gt(&self, other: &Self) -> bool { 1280 | (**self).gt(other) 1281 | } 1282 | } 1283 | 1284 | impl Ord for ArrayVec where T: Ord { 1285 | fn cmp(&self, other: &Self) -> cmp::Ordering { 1286 | (**self).cmp(other) 1287 | } 1288 | } 1289 | 1290 | #[cfg(feature="std")] 1291 | /// `Write` appends written data to the end of the vector. 1292 | /// 1293 | /// Requires `features="std"`. 1294 | impl io::Write for ArrayVec { 1295 | fn write(&mut self, data: &[u8]) -> io::Result { 1296 | let len = cmp::min(self.remaining_capacity(), data.len()); 1297 | let _result = self.try_extend_from_slice(&data[..len]); 1298 | debug_assert!(_result.is_ok()); 1299 | Ok(len) 1300 | } 1301 | fn flush(&mut self) -> io::Result<()> { Ok(()) } 1302 | } 1303 | 1304 | #[cfg(feature="serde")] 1305 | /// Requires crate feature `"serde"` 1306 | impl Serialize for ArrayVec { 1307 | fn serialize(&self, serializer: S) -> Result 1308 | where S: Serializer 1309 | { 1310 | serializer.collect_seq(self) 1311 | } 1312 | } 1313 | 1314 | #[cfg(feature="serde")] 1315 | /// Requires crate feature `"serde"` 1316 | impl<'de, T: Deserialize<'de>, const CAP: usize> Deserialize<'de> for ArrayVec { 1317 | fn deserialize(deserializer: D) -> Result 1318 | where D: Deserializer<'de> 1319 | { 1320 | use serde::de::{Visitor, SeqAccess, Error}; 1321 | use std::marker::PhantomData; 1322 | 1323 | struct ArrayVecVisitor<'de, T: Deserialize<'de>, const CAP: usize>(PhantomData<(&'de (), [T; CAP])>); 1324 | 1325 | impl<'de, T: Deserialize<'de>, const CAP: usize> Visitor<'de> for ArrayVecVisitor<'de, T, CAP> { 1326 | type Value = ArrayVec; 1327 | 1328 | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 1329 | write!(formatter, "an array with no more than {} items", CAP) 1330 | } 1331 | 1332 | fn visit_seq(self, mut seq: SA) -> Result 1333 | where SA: SeqAccess<'de>, 1334 | { 1335 | let mut values = ArrayVec::::new(); 1336 | 1337 | while let Some(value) = seq.next_element()? { 1338 | if let Err(_) = values.try_push(value) { 1339 | return Err(SA::Error::invalid_length(CAP + 1, &self)); 1340 | } 1341 | } 1342 | 1343 | Ok(values) 1344 | } 1345 | } 1346 | 1347 | deserializer.deserialize_seq(ArrayVecVisitor::(PhantomData)) 1348 | } 1349 | } 1350 | 1351 | #[cfg(feature = "borsh")] 1352 | /// Requires crate feature `"borsh"` 1353 | impl borsh::BorshSerialize for ArrayVec 1354 | where 1355 | T: borsh::BorshSerialize, 1356 | { 1357 | fn serialize(&self, writer: &mut W) -> borsh::io::Result<()> { 1358 | <[T] as borsh::BorshSerialize>::serialize(self.as_slice(), writer) 1359 | } 1360 | } 1361 | 1362 | #[cfg(feature = "borsh")] 1363 | /// Requires crate feature `"borsh"` 1364 | impl borsh::BorshDeserialize for ArrayVec 1365 | where 1366 | T: borsh::BorshDeserialize, 1367 | { 1368 | fn deserialize_reader(reader: &mut R) -> borsh::io::Result { 1369 | let mut values = Self::new(); 1370 | let len = ::deserialize_reader(reader)?; 1371 | for _ in 0..len { 1372 | let elem = ::deserialize_reader(reader)?; 1373 | if let Err(_) = values.try_push(elem) { 1374 | return Err(borsh::io::Error::new( 1375 | borsh::io::ErrorKind::InvalidData, 1376 | format!("Expected an array with no more than {} items", CAP), 1377 | )); 1378 | } 1379 | } 1380 | 1381 | Ok(values) 1382 | } 1383 | } 1384 | -------------------------------------------------------------------------------- /src/arrayvec_impl.rs: -------------------------------------------------------------------------------- 1 | use std::ptr; 2 | use std::slice; 3 | 4 | use crate::CapacityError; 5 | 6 | /// Implements basic arrayvec methods - based on a few required methods 7 | /// for length and element access. 8 | pub(crate) trait ArrayVecImpl { 9 | type Item; 10 | const CAPACITY: usize; 11 | 12 | fn len(&self) -> usize; 13 | 14 | unsafe fn set_len(&mut self, new_len: usize); 15 | 16 | /// Return a slice containing all elements of the vector. 17 | fn as_slice(&self) -> &[Self::Item] { 18 | let len = self.len(); 19 | unsafe { 20 | slice::from_raw_parts(self.as_ptr(), len) 21 | } 22 | } 23 | 24 | /// Return a mutable slice containing all elements of the vector. 25 | fn as_mut_slice(&mut self) -> &mut [Self::Item] { 26 | let len = self.len(); 27 | unsafe { 28 | std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) 29 | } 30 | } 31 | 32 | /// Return a raw pointer to the vector's buffer. 33 | fn as_ptr(&self) -> *const Self::Item; 34 | 35 | /// Return a raw mutable pointer to the vector's buffer. 36 | fn as_mut_ptr(&mut self) -> *mut Self::Item; 37 | 38 | #[track_caller] 39 | fn push(&mut self, element: Self::Item) { 40 | self.try_push(element).unwrap() 41 | } 42 | 43 | fn try_push(&mut self, element: Self::Item) -> Result<(), CapacityError> { 44 | if self.len() < Self::CAPACITY { 45 | unsafe { 46 | self.push_unchecked(element); 47 | } 48 | Ok(()) 49 | } else { 50 | Err(CapacityError::new(element)) 51 | } 52 | } 53 | 54 | unsafe fn push_unchecked(&mut self, element: Self::Item) { 55 | let len = self.len(); 56 | debug_assert!(len < Self::CAPACITY); 57 | ptr::write(self.as_mut_ptr().add(len), element); 58 | self.set_len(len + 1); 59 | } 60 | 61 | fn pop(&mut self) -> Option { 62 | if self.len() == 0 { 63 | return None; 64 | } 65 | unsafe { 66 | let new_len = self.len() - 1; 67 | self.set_len(new_len); 68 | Some(ptr::read(self.as_ptr().add(new_len))) 69 | } 70 | } 71 | 72 | fn clear(&mut self) { 73 | self.truncate(0) 74 | } 75 | 76 | fn truncate(&mut self, new_len: usize) { 77 | unsafe { 78 | let len = self.len(); 79 | if new_len < len { 80 | self.set_len(new_len); 81 | let tail = slice::from_raw_parts_mut(self.as_mut_ptr().add(new_len), len - new_len); 82 | ptr::drop_in_place(tail); 83 | } 84 | } 85 | } 86 | } 87 | 88 | -------------------------------------------------------------------------------- /src/char.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution and at 3 | // http://rust-lang.org/COPYRIGHT. 4 | // 5 | // Licensed under the Apache License, Version 2.0 or the MIT license 7 | // , at your 8 | // option. This file may not be copied, modified, or distributed 9 | // except according to those terms. 10 | // 11 | // Original authors: alexchrichton, bluss 12 | 13 | // UTF-8 ranges and tags for encoding characters 14 | const TAG_CONT: u8 = 0b1000_0000; 15 | const TAG_TWO_B: u8 = 0b1100_0000; 16 | const TAG_THREE_B: u8 = 0b1110_0000; 17 | const TAG_FOUR_B: u8 = 0b1111_0000; 18 | const MAX_ONE_B: u32 = 0x80; 19 | const MAX_TWO_B: u32 = 0x800; 20 | const MAX_THREE_B: u32 = 0x10000; 21 | 22 | /// Placeholder 23 | pub struct EncodeUtf8Error; 24 | 25 | /// Encode a char into buf using UTF-8. 26 | /// 27 | /// On success, return the byte length of the encoding (1, 2, 3 or 4).
28 | /// On error, return `EncodeUtf8Error` if the buffer was too short for the char. 29 | /// 30 | /// Safety: `ptr` must be writable for `len` bytes. 31 | #[inline] 32 | pub unsafe fn encode_utf8(ch: char, ptr: *mut u8, len: usize) -> Result 33 | { 34 | let code = ch as u32; 35 | if code < MAX_ONE_B && len >= 1 { 36 | ptr.add(0).write(code as u8); 37 | return Ok(1); 38 | } else if code < MAX_TWO_B && len >= 2 { 39 | ptr.add(0).write((code >> 6 & 0x1F) as u8 | TAG_TWO_B); 40 | ptr.add(1).write((code & 0x3F) as u8 | TAG_CONT); 41 | return Ok(2); 42 | } else if code < MAX_THREE_B && len >= 3 { 43 | ptr.add(0).write((code >> 12 & 0x0F) as u8 | TAG_THREE_B); 44 | ptr.add(1).write((code >> 6 & 0x3F) as u8 | TAG_CONT); 45 | ptr.add(2).write((code & 0x3F) as u8 | TAG_CONT); 46 | return Ok(3); 47 | } else if len >= 4 { 48 | ptr.add(0).write((code >> 18 & 0x07) as u8 | TAG_FOUR_B); 49 | ptr.add(1).write((code >> 12 & 0x3F) as u8 | TAG_CONT); 50 | ptr.add(2).write((code >> 6 & 0x3F) as u8 | TAG_CONT); 51 | ptr.add(3).write((code & 0x3F) as u8 | TAG_CONT); 52 | return Ok(4); 53 | }; 54 | Err(EncodeUtf8Error) 55 | } 56 | 57 | 58 | #[test] 59 | #[cfg_attr(miri, ignore)] // Miri is too slow 60 | fn test_encode_utf8() { 61 | // Test that all codepoints are encoded correctly 62 | let mut data = [0u8; 16]; 63 | for codepoint in 0..=(std::char::MAX as u32) { 64 | if let Some(ch) = std::char::from_u32(codepoint) { 65 | for elt in &mut data { *elt = 0; } 66 | let ptr = data.as_mut_ptr(); 67 | let len = data.len(); 68 | unsafe { 69 | let res = encode_utf8(ch, ptr, len).ok().unwrap(); 70 | assert_eq!(res, ch.len_utf8()); 71 | } 72 | let string = std::str::from_utf8(&data).unwrap(); 73 | assert_eq!(string.chars().next(), Some(ch)); 74 | } 75 | } 76 | } 77 | 78 | #[test] 79 | fn test_encode_utf8_oob() { 80 | // test that we report oob if the buffer is too short 81 | let mut data = [0u8; 16]; 82 | let chars = ['a', 'α', '�', '𐍈']; 83 | for (len, &ch) in (1..=4).zip(&chars) { 84 | assert_eq!(len, ch.len_utf8(), "Len of ch={}", ch); 85 | let ptr = data.as_mut_ptr(); 86 | unsafe { 87 | assert!(matches::matches!(encode_utf8(ch, ptr, len - 1), Err(_))); 88 | assert!(matches::matches!(encode_utf8(ch, ptr, len), Ok(_))); 89 | } 90 | } 91 | } 92 | 93 | -------------------------------------------------------------------------------- /src/errors.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | #[cfg(feature="std")] 3 | use std::any::Any; 4 | #[cfg(feature="std")] 5 | use std::error::Error; 6 | 7 | /// Error value indicating insufficient capacity 8 | #[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)] 9 | pub struct CapacityError { 10 | element: T, 11 | } 12 | 13 | impl CapacityError { 14 | /// Create a new `CapacityError` from `element`. 15 | pub const fn new(element: T) -> CapacityError { 16 | CapacityError { 17 | element: element, 18 | } 19 | } 20 | 21 | /// Extract the overflowing element 22 | pub fn element(self) -> T { 23 | self.element 24 | } 25 | 26 | /// Convert into a `CapacityError` that does not carry an element. 27 | pub fn simplify(self) -> CapacityError { 28 | CapacityError { element: () } 29 | } 30 | } 31 | 32 | const CAPERROR: &'static str = "insufficient capacity"; 33 | 34 | #[cfg(feature="std")] 35 | /// Requires `features="std"`. 36 | impl Error for CapacityError {} 37 | 38 | impl fmt::Display for CapacityError { 39 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 40 | write!(f, "{}", CAPERROR) 41 | } 42 | } 43 | 44 | impl fmt::Debug for CapacityError { 45 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 46 | write!(f, "{}: {}", "CapacityError", CAPERROR) 47 | } 48 | } 49 | 50 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! **arrayvec** provides the types [`ArrayVec`] and [`ArrayString`]: 2 | //! array-backed vector and string types, which store their contents inline. 3 | //! 4 | //! The arrayvec package has the following cargo features: 5 | //! 6 | //! - `std` 7 | //! - Optional, enabled by default 8 | //! - Use libstd; disable to use `no_std` instead. 9 | //! 10 | //! - `serde` 11 | //! - Optional 12 | //! - Enable serialization for ArrayVec and ArrayString using serde 1.x 13 | //! 14 | //! - `zeroize` 15 | //! - Optional 16 | //! - Implement `Zeroize` for ArrayVec and ArrayString 17 | //! 18 | //! ## Rust Version 19 | //! 20 | //! This version of arrayvec requires Rust 1.51 or later. 21 | //! 22 | #![doc(html_root_url="https://docs.rs/arrayvec/0.7/")] 23 | #![cfg_attr(not(feature="std"), no_std)] 24 | 25 | #[cfg(feature="serde")] 26 | extern crate serde; 27 | 28 | #[cfg(not(feature="std"))] 29 | extern crate core as std; 30 | 31 | #[cfg(not(target_pointer_width = "16"))] 32 | pub(crate) type LenUint = u32; 33 | 34 | #[cfg(target_pointer_width = "16")] 35 | pub(crate) type LenUint = u16; 36 | 37 | macro_rules! assert_capacity_limit { 38 | ($cap:expr) => { 39 | if std::mem::size_of::() > std::mem::size_of::() { 40 | if $cap > LenUint::MAX as usize { 41 | #[cfg(not(target_pointer_width = "16"))] 42 | panic!("ArrayVec: largest supported capacity is u32::MAX"); 43 | #[cfg(target_pointer_width = "16")] 44 | panic!("ArrayVec: largest supported capacity is u16::MAX"); 45 | } 46 | } 47 | } 48 | } 49 | 50 | macro_rules! assert_capacity_limit_const { 51 | ($cap:expr) => { 52 | if std::mem::size_of::() > std::mem::size_of::() { 53 | if $cap > LenUint::MAX as usize { 54 | [/*ArrayVec: largest supported capacity is u32::MAX*/][$cap] 55 | } 56 | } 57 | } 58 | } 59 | 60 | mod arrayvec_impl; 61 | mod arrayvec; 62 | mod array_string; 63 | mod char; 64 | mod errors; 65 | mod utils; 66 | 67 | pub use crate::array_string::ArrayString; 68 | pub use crate::errors::CapacityError; 69 | 70 | pub use crate::arrayvec::{ArrayVec, IntoIter, Drain}; 71 | -------------------------------------------------------------------------------- /src/utils.rs: -------------------------------------------------------------------------------- 1 | use std::marker::PhantomData; 2 | use std::mem::MaybeUninit; 3 | 4 | pub(crate) struct MakeMaybeUninit(PhantomData T>); 5 | 6 | impl MakeMaybeUninit { 7 | pub(crate) const VALUE: MaybeUninit = MaybeUninit::uninit(); 8 | 9 | pub(crate) const ARRAY: [MaybeUninit; N] = [Self::VALUE; N]; 10 | } 11 | 12 | -------------------------------------------------------------------------------- /tests/borsh.rs: -------------------------------------------------------------------------------- 1 | #![cfg(feature = "borsh")] 2 | use std::fmt; 3 | extern crate arrayvec; 4 | extern crate borsh; 5 | 6 | fn assert_ser(v: &T, expected_bytes: &[u8]) { 7 | let mut actual_bytes = Vec::new(); 8 | v.serialize(&mut actual_bytes).unwrap(); 9 | assert_eq!(actual_bytes, expected_bytes); 10 | } 11 | 12 | fn assert_roundtrip(v: &T) { 13 | let mut bytes = Vec::new(); 14 | v.serialize(&mut bytes).unwrap(); 15 | let v_de = T::try_from_slice(&bytes).unwrap(); 16 | assert_eq!(*v, v_de); 17 | } 18 | 19 | mod array_vec { 20 | use arrayvec::ArrayVec; 21 | use super::{assert_ser, assert_roundtrip}; 22 | 23 | #[test] 24 | fn test_empty() { 25 | let vec = ArrayVec::::new(); 26 | assert_ser(&vec, b"\0\0\0\0"); 27 | assert_roundtrip(&vec); 28 | } 29 | 30 | #[test] 31 | fn test_full() { 32 | let mut vec = ArrayVec::::new(); 33 | vec.push(0xdeadbeef); 34 | vec.push(0x123); 35 | vec.push(0x456); 36 | assert_ser(&vec, b"\x03\0\0\0\xef\xbe\xad\xde\x23\x01\0\0\x56\x04\0\0"); 37 | assert_roundtrip(&vec); 38 | } 39 | 40 | #[test] 41 | fn test_with_free_capacity() { 42 | let mut vec = ArrayVec::::new(); 43 | vec.push(0xdeadbeef); 44 | assert_ser(&vec, b"\x01\0\0\0\xef\xbe\xad\xde"); 45 | assert_roundtrip(&vec); 46 | } 47 | } 48 | 49 | mod array_string { 50 | use arrayvec::ArrayString; 51 | use super::{assert_ser, assert_roundtrip}; 52 | 53 | #[test] 54 | fn test_empty() { 55 | let string = ArrayString::<0>::new(); 56 | assert_ser(&string, b"\0\0\0\0"); 57 | assert_roundtrip(&string); 58 | } 59 | 60 | #[test] 61 | fn test_full() { 62 | let string = ArrayString::from_byte_string(b"hello world").unwrap(); 63 | assert_ser(&string, b"\x0b\0\0\0hello world"); 64 | assert_roundtrip(&string); 65 | } 66 | 67 | #[test] 68 | fn test_with_free_capacity() { 69 | let string = ArrayString::<16>::from("hello world").unwrap(); 70 | assert_ser(&string, b"\x0b\0\0\0hello world"); 71 | assert_roundtrip(&string); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /tests/serde.rs: -------------------------------------------------------------------------------- 1 | #![cfg(feature = "serde")] 2 | extern crate arrayvec; 3 | extern crate serde_test; 4 | 5 | mod array_vec { 6 | use arrayvec::ArrayVec; 7 | 8 | use serde_test::{Token, assert_tokens, assert_de_tokens_error}; 9 | 10 | #[test] 11 | fn test_ser_de_empty() { 12 | let vec = ArrayVec::::new(); 13 | 14 | assert_tokens(&vec, &[ 15 | Token::Seq { len: Some(0) }, 16 | Token::SeqEnd, 17 | ]); 18 | } 19 | 20 | 21 | #[test] 22 | fn test_ser_de() { 23 | let mut vec = ArrayVec::::new(); 24 | vec.push(20); 25 | vec.push(55); 26 | vec.push(123); 27 | 28 | assert_tokens(&vec, &[ 29 | Token::Seq { len: Some(3) }, 30 | Token::U32(20), 31 | Token::U32(55), 32 | Token::U32(123), 33 | Token::SeqEnd, 34 | ]); 35 | } 36 | 37 | #[test] 38 | fn test_de_too_large() { 39 | assert_de_tokens_error::>(&[ 40 | Token::Seq { len: Some(3) }, 41 | Token::U32(13), 42 | Token::U32(42), 43 | Token::U32(68), 44 | ], "invalid length 3, expected an array with no more than 2 items"); 45 | } 46 | } 47 | 48 | mod array_string { 49 | use arrayvec::ArrayString; 50 | 51 | use serde_test::{Token, assert_tokens, assert_de_tokens_error}; 52 | 53 | #[test] 54 | fn test_ser_de_empty() { 55 | let string = ArrayString::<0>::new(); 56 | 57 | assert_tokens(&string, &[ 58 | Token::Str(""), 59 | ]); 60 | } 61 | 62 | 63 | #[test] 64 | fn test_ser_de() { 65 | let string = ArrayString::<9>::from("1234 abcd") 66 | .expect("expected exact specified capacity to be enough"); 67 | 68 | assert_tokens(&string, &[ 69 | Token::Str("1234 abcd"), 70 | ]); 71 | } 72 | 73 | #[test] 74 | fn test_de_too_large() { 75 | assert_de_tokens_error::>(&[ 76 | Token::Str("afd") 77 | ], "invalid length 3, expected a string no more than 2 bytes long"); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /tests/tests.rs: -------------------------------------------------------------------------------- 1 | extern crate arrayvec; 2 | #[macro_use] extern crate matches; 3 | 4 | use arrayvec::ArrayVec; 5 | use arrayvec::ArrayString; 6 | use std::mem; 7 | use arrayvec::CapacityError; 8 | 9 | use std::collections::HashMap; 10 | 11 | 12 | #[test] 13 | fn test_simple() { 14 | use std::ops::Add; 15 | 16 | let mut vec: ArrayVec, 3> = ArrayVec::new(); 17 | 18 | vec.push(vec![1, 2, 3, 4]); 19 | vec.push(vec![10]); 20 | vec.push(vec![-1, 13, -2]); 21 | 22 | for elt in &vec { 23 | assert_eq!(elt.iter().fold(0, Add::add), 10); 24 | } 25 | 26 | let sum_len = vec.into_iter().map(|x| x.len()).fold(0, Add::add); 27 | assert_eq!(sum_len, 8); 28 | } 29 | 30 | #[test] 31 | fn test_capacity_left() { 32 | let mut vec: ArrayVec = ArrayVec::new(); 33 | assert_eq!(vec.remaining_capacity(), 4); 34 | vec.push(1); 35 | assert_eq!(vec.remaining_capacity(), 3); 36 | vec.push(2); 37 | assert_eq!(vec.remaining_capacity(), 2); 38 | vec.push(3); 39 | assert_eq!(vec.remaining_capacity(), 1); 40 | vec.push(4); 41 | assert_eq!(vec.remaining_capacity(), 0); 42 | } 43 | 44 | #[test] 45 | fn test_extend_from_slice() { 46 | let mut vec: ArrayVec = ArrayVec::new(); 47 | 48 | vec.try_extend_from_slice(&[1, 2, 3]).unwrap(); 49 | assert_eq!(vec.len(), 3); 50 | assert_eq!(&vec[..], &[1, 2, 3]); 51 | assert_eq!(vec.pop(), Some(3)); 52 | assert_eq!(&vec[..], &[1, 2]); 53 | } 54 | 55 | #[test] 56 | fn test_extend_from_slice_error() { 57 | let mut vec: ArrayVec = ArrayVec::new(); 58 | 59 | vec.try_extend_from_slice(&[1, 2, 3]).unwrap(); 60 | let res = vec.try_extend_from_slice(&[0; 8]); 61 | assert_matches!(res, Err(_)); 62 | 63 | let mut vec: ArrayVec = ArrayVec::new(); 64 | let res = vec.try_extend_from_slice(&[0; 1]); 65 | assert_matches!(res, Err(_)); 66 | } 67 | 68 | #[test] 69 | fn test_try_from_slice_error() { 70 | use arrayvec::ArrayVec; 71 | use std::convert::TryInto as _; 72 | 73 | let res: Result, _> = (&[1, 2, 3] as &[_]).try_into(); 74 | assert_matches!(res, Err(_)); 75 | } 76 | 77 | #[test] 78 | fn test_u16_index() { 79 | const N: usize = 4096; 80 | let mut vec: ArrayVec<_, N> = ArrayVec::new(); 81 | for _ in 0..N { 82 | assert!(vec.try_push(1u8).is_ok()); 83 | } 84 | assert!(vec.try_push(0).is_err()); 85 | assert_eq!(vec.len(), N); 86 | } 87 | 88 | #[test] 89 | fn test_iter() { 90 | let mut iter = ArrayVec::from([1, 2, 3]).into_iter(); 91 | assert_eq!(iter.size_hint(), (3, Some(3))); 92 | assert_eq!(iter.next_back(), Some(3)); 93 | assert_eq!(iter.next(), Some(1)); 94 | assert_eq!(iter.next_back(), Some(2)); 95 | assert_eq!(iter.size_hint(), (0, Some(0))); 96 | assert_eq!(iter.next_back(), None); 97 | } 98 | 99 | #[test] 100 | fn test_drop() { 101 | use std::cell::Cell; 102 | 103 | let flag = &Cell::new(0); 104 | 105 | #[derive(Clone)] 106 | struct Bump<'a>(&'a Cell); 107 | 108 | impl<'a> Drop for Bump<'a> { 109 | fn drop(&mut self) { 110 | let n = self.0.get(); 111 | self.0.set(n + 1); 112 | } 113 | } 114 | 115 | { 116 | let mut array = ArrayVec::::new(); 117 | array.push(Bump(flag)); 118 | array.push(Bump(flag)); 119 | } 120 | assert_eq!(flag.get(), 2); 121 | 122 | // test something with the nullable pointer optimization 123 | flag.set(0); 124 | 125 | { 126 | let mut array = ArrayVec::<_, 3>::new(); 127 | array.push(vec![Bump(flag)]); 128 | array.push(vec![Bump(flag), Bump(flag)]); 129 | array.push(vec![]); 130 | let push4 = array.try_push(vec![Bump(flag)]); 131 | assert_eq!(flag.get(), 0); 132 | drop(push4); 133 | assert_eq!(flag.get(), 1); 134 | drop(array.pop()); 135 | assert_eq!(flag.get(), 1); 136 | drop(array.pop()); 137 | assert_eq!(flag.get(), 3); 138 | } 139 | 140 | assert_eq!(flag.get(), 4); 141 | 142 | // test into_inner 143 | flag.set(0); 144 | { 145 | let mut array = ArrayVec::<_, 3>::new(); 146 | array.push(Bump(flag)); 147 | array.push(Bump(flag)); 148 | array.push(Bump(flag)); 149 | let inner = array.into_inner(); 150 | assert!(inner.is_ok()); 151 | assert_eq!(flag.get(), 0); 152 | drop(inner); 153 | assert_eq!(flag.get(), 3); 154 | } 155 | 156 | // test take 157 | flag.set(0); 158 | { 159 | let mut array1 = ArrayVec::<_, 3>::new(); 160 | array1.push(Bump(flag)); 161 | array1.push(Bump(flag)); 162 | array1.push(Bump(flag)); 163 | let array2 = array1.take(); 164 | assert_eq!(flag.get(), 0); 165 | drop(array1); 166 | assert_eq!(flag.get(), 0); 167 | drop(array2); 168 | assert_eq!(flag.get(), 3); 169 | } 170 | 171 | // test cloning into_iter 172 | flag.set(0); 173 | { 174 | let mut array = ArrayVec::<_, 3>::new(); 175 | array.push(Bump(flag)); 176 | array.push(Bump(flag)); 177 | array.push(Bump(flag)); 178 | let mut iter = array.into_iter(); 179 | assert_eq!(flag.get(), 0); 180 | iter.next(); 181 | assert_eq!(flag.get(), 1); 182 | let clone = iter.clone(); 183 | assert_eq!(flag.get(), 1); 184 | drop(clone); 185 | assert_eq!(flag.get(), 3); 186 | drop(iter); 187 | assert_eq!(flag.get(), 5); 188 | } 189 | } 190 | 191 | #[test] 192 | fn test_drop_panics() { 193 | use std::cell::Cell; 194 | use std::panic::catch_unwind; 195 | use std::panic::AssertUnwindSafe; 196 | 197 | let flag = &Cell::new(0); 198 | 199 | struct Bump<'a>(&'a Cell); 200 | 201 | // Panic in the first drop 202 | impl<'a> Drop for Bump<'a> { 203 | fn drop(&mut self) { 204 | let n = self.0.get(); 205 | self.0.set(n + 1); 206 | if n == 0 { 207 | panic!("Panic in Bump's drop"); 208 | } 209 | } 210 | } 211 | // check if rust is new enough 212 | flag.set(0); 213 | { 214 | let array = vec![Bump(flag), Bump(flag)]; 215 | let res = catch_unwind(AssertUnwindSafe(|| { 216 | drop(array); 217 | })); 218 | assert!(res.is_err()); 219 | } 220 | 221 | if flag.get() != 2 { 222 | println!("test_drop_panics: skip, this version of Rust doesn't continue in drop_in_place"); 223 | return; 224 | } 225 | 226 | flag.set(0); 227 | { 228 | let mut array = ArrayVec::::new(); 229 | array.push(Bump(flag)); 230 | array.push(Bump(flag)); 231 | array.push(Bump(flag)); 232 | 233 | let res = catch_unwind(AssertUnwindSafe(|| { 234 | drop(array); 235 | })); 236 | assert!(res.is_err()); 237 | } 238 | // Check that all the elements drop, even if the first drop panics. 239 | assert_eq!(flag.get(), 3); 240 | 241 | 242 | flag.set(0); 243 | { 244 | let mut array = ArrayVec::::new(); 245 | array.push(Bump(flag)); 246 | array.push(Bump(flag)); 247 | array.push(Bump(flag)); 248 | array.push(Bump(flag)); 249 | array.push(Bump(flag)); 250 | 251 | let i = 2; 252 | let tail_len = array.len() - i; 253 | 254 | let res = catch_unwind(AssertUnwindSafe(|| { 255 | array.truncate(i); 256 | })); 257 | assert!(res.is_err()); 258 | // Check that all the tail elements drop, even if the first drop panics. 259 | assert_eq!(flag.get(), tail_len as i32); 260 | } 261 | 262 | 263 | } 264 | 265 | #[test] 266 | fn test_extend() { 267 | let mut range = 0..10; 268 | 269 | let mut array: ArrayVec<_, 5> = range.by_ref().take(5).collect(); 270 | assert_eq!(&array[..], &[0, 1, 2, 3, 4]); 271 | assert_eq!(range.next(), Some(5)); 272 | 273 | array.extend(range.by_ref().take(0)); 274 | assert_eq!(range.next(), Some(6)); 275 | 276 | let mut array: ArrayVec<_, 10> = (0..3).collect(); 277 | assert_eq!(&array[..], &[0, 1, 2]); 278 | array.extend(3..5); 279 | assert_eq!(&array[..], &[0, 1, 2, 3, 4]); 280 | } 281 | 282 | #[should_panic] 283 | #[test] 284 | fn test_extend_capacity_panic_1() { 285 | let mut range = 0..10; 286 | 287 | let _: ArrayVec<_, 5> = range.by_ref().collect(); 288 | } 289 | 290 | #[should_panic] 291 | #[test] 292 | fn test_extend_capacity_panic_2() { 293 | let mut range = 0..10; 294 | 295 | let mut array: ArrayVec<_, 5> = range.by_ref().take(5).collect(); 296 | assert_eq!(&array[..], &[0, 1, 2, 3, 4]); 297 | assert_eq!(range.next(), Some(5)); 298 | array.extend(range.by_ref().take(1)); 299 | } 300 | 301 | #[test] 302 | fn test_is_send_sync() { 303 | let data = ArrayVec::, 5>::new(); 304 | &data as &dyn Send; 305 | &data as &dyn Sync; 306 | } 307 | 308 | #[test] 309 | fn test_compact_size() { 310 | // 4 bytes + padding + length 311 | type ByteArray = ArrayVec; 312 | println!("{}", mem::size_of::()); 313 | assert!(mem::size_of::() <= 2 * mem::size_of::()); 314 | 315 | // just length 316 | type EmptyArray = ArrayVec; 317 | println!("{}", mem::size_of::()); 318 | assert!(mem::size_of::() <= mem::size_of::()); 319 | 320 | // 3 elements + padding + length 321 | type QuadArray = ArrayVec; 322 | println!("{}", mem::size_of::()); 323 | assert!(mem::size_of::() <= 4 * 4 + mem::size_of::()); 324 | } 325 | 326 | #[test] 327 | fn test_still_works_with_option_arrayvec() { 328 | type RefArray = ArrayVec<&'static i32, 2>; 329 | let array = Some(RefArray::new()); 330 | assert!(array.is_some()); 331 | println!("{:?}", array); 332 | } 333 | 334 | #[test] 335 | fn test_drain() { 336 | let mut v = ArrayVec::from([0; 8]); 337 | v.pop(); 338 | v.drain(0..7); 339 | assert_eq!(&v[..], &[]); 340 | 341 | v.extend(0..8); 342 | v.drain(1..4); 343 | assert_eq!(&v[..], &[0, 4, 5, 6, 7]); 344 | let u: ArrayVec<_, 3> = v.drain(1..4).rev().collect(); 345 | assert_eq!(&u[..], &[6, 5, 4]); 346 | assert_eq!(&v[..], &[0, 7]); 347 | v.drain(..); 348 | assert_eq!(&v[..], &[]); 349 | } 350 | 351 | #[test] 352 | fn test_drain_range_inclusive() { 353 | let mut v = ArrayVec::from([0; 8]); 354 | v.drain(0..=7); 355 | assert_eq!(&v[..], &[]); 356 | 357 | v.extend(0..8); 358 | v.drain(1..=4); 359 | assert_eq!(&v[..], &[0, 5, 6, 7]); 360 | let u: ArrayVec<_, 3> = v.drain(1..=2).rev().collect(); 361 | assert_eq!(&u[..], &[6, 5]); 362 | assert_eq!(&v[..], &[0, 7]); 363 | v.drain(..); 364 | assert_eq!(&v[..], &[]); 365 | } 366 | 367 | #[test] 368 | #[should_panic] 369 | fn test_drain_range_inclusive_oob() { 370 | let mut v = ArrayVec::from([0; 0]); 371 | v.drain(0..=0); 372 | } 373 | 374 | #[test] 375 | fn test_retain() { 376 | let mut v = ArrayVec::from([0; 8]); 377 | for (i, elt) in v.iter_mut().enumerate() { 378 | *elt = i; 379 | } 380 | v.retain(|_| true); 381 | assert_eq!(&v[..], &[0, 1, 2, 3, 4, 5, 6, 7]); 382 | v.retain(|elt| { 383 | *elt /= 2; 384 | *elt % 2 == 0 385 | }); 386 | assert_eq!(&v[..], &[0, 0, 2, 2]); 387 | v.retain(|_| false); 388 | assert_eq!(&v[..], &[]); 389 | } 390 | 391 | #[test] 392 | #[should_panic] 393 | fn test_drain_oob() { 394 | let mut v = ArrayVec::from([0; 8]); 395 | v.pop(); 396 | v.drain(0..8); 397 | } 398 | 399 | #[test] 400 | #[should_panic] 401 | fn test_drop_panic() { 402 | struct DropPanic; 403 | 404 | impl Drop for DropPanic { 405 | fn drop(&mut self) { 406 | panic!("drop"); 407 | } 408 | } 409 | 410 | let mut array = ArrayVec::::new(); 411 | array.push(DropPanic); 412 | } 413 | 414 | #[test] 415 | #[should_panic] 416 | fn test_drop_panic_into_iter() { 417 | struct DropPanic; 418 | 419 | impl Drop for DropPanic { 420 | fn drop(&mut self) { 421 | panic!("drop"); 422 | } 423 | } 424 | 425 | let mut array = ArrayVec::::new(); 426 | array.push(DropPanic); 427 | array.into_iter(); 428 | } 429 | 430 | #[test] 431 | fn test_insert() { 432 | let mut v = ArrayVec::from([]); 433 | assert_matches!(v.try_push(1), Err(_)); 434 | 435 | let mut v = ArrayVec::<_, 3>::new(); 436 | v.insert(0, 0); 437 | v.insert(1, 1); 438 | //let ret1 = v.try_insert(3, 3); 439 | //assert_matches!(ret1, Err(InsertError::OutOfBounds(_))); 440 | assert_eq!(&v[..], &[0, 1]); 441 | v.insert(2, 2); 442 | assert_eq!(&v[..], &[0, 1, 2]); 443 | 444 | let ret2 = v.try_insert(1, 9); 445 | assert_eq!(&v[..], &[0, 1, 2]); 446 | assert_matches!(ret2, Err(_)); 447 | 448 | let mut v = ArrayVec::from([2]); 449 | assert_matches!(v.try_insert(0, 1), Err(CapacityError { .. })); 450 | assert_matches!(v.try_insert(1, 1), Err(CapacityError { .. })); 451 | //assert_matches!(v.try_insert(2, 1), Err(CapacityError { .. })); 452 | } 453 | 454 | #[test] 455 | fn test_into_inner_1() { 456 | let mut v = ArrayVec::from([1, 2]); 457 | v.pop(); 458 | let u = v.clone(); 459 | assert_eq!(v.into_inner(), Err(u)); 460 | } 461 | 462 | #[test] 463 | fn test_into_inner_2() { 464 | let mut v = ArrayVec::::new(); 465 | v.push("a".into()); 466 | v.push("b".into()); 467 | v.push("c".into()); 468 | v.push("d".into()); 469 | assert_eq!(v.into_inner().unwrap(), ["a", "b", "c", "d"]); 470 | } 471 | 472 | #[test] 473 | fn test_into_inner_3() { 474 | let mut v = ArrayVec::::new(); 475 | v.extend(1..=4); 476 | assert_eq!(v.into_inner().unwrap(), [1, 2, 3, 4]); 477 | } 478 | 479 | #[test] 480 | fn test_take() { 481 | let mut v1 = ArrayVec::::new(); 482 | v1.extend(1..=4); 483 | let v2 = v1.take(); 484 | assert!(v1.into_inner().is_err()); 485 | assert_eq!(v2.into_inner().unwrap(), [1, 2, 3, 4]); 486 | } 487 | 488 | #[cfg(feature="std")] 489 | #[test] 490 | fn test_write() { 491 | use std::io::Write; 492 | let mut v = ArrayVec::<_, 8>::new(); 493 | write!(&mut v, "\x01\x02\x03").unwrap(); 494 | assert_eq!(&v[..], &[1, 2, 3]); 495 | let r = v.write(&[9; 16]).unwrap(); 496 | assert_eq!(r, 5); 497 | assert_eq!(&v[..], &[1, 2, 3, 9, 9, 9, 9, 9]); 498 | } 499 | 500 | #[test] 501 | fn array_clone_from() { 502 | let mut v = ArrayVec::<_, 4>::new(); 503 | v.push(vec![1, 2]); 504 | v.push(vec![3, 4, 5]); 505 | v.push(vec![6]); 506 | let reference = v.to_vec(); 507 | let mut u = ArrayVec::<_, 4>::new(); 508 | u.clone_from(&v); 509 | assert_eq!(&u, &reference[..]); 510 | 511 | let mut t = ArrayVec::<_, 4>::new(); 512 | t.push(vec![97]); 513 | t.push(vec![]); 514 | t.push(vec![5, 6, 2]); 515 | t.push(vec![2]); 516 | t.clone_from(&v); 517 | assert_eq!(&t, &reference[..]); 518 | t.clear(); 519 | t.clone_from(&v); 520 | assert_eq!(&t, &reference[..]); 521 | } 522 | 523 | #[cfg(feature="std")] 524 | #[test] 525 | fn test_string() { 526 | use std::error::Error; 527 | 528 | let text = "hello world"; 529 | let mut s = ArrayString::<16>::new(); 530 | s.try_push_str(text).unwrap(); 531 | assert_eq!(&s, text); 532 | assert_eq!(text, &s); 533 | 534 | // Make sure Hash / Eq / Borrow match up so we can use HashMap 535 | let mut map = HashMap::new(); 536 | map.insert(s, 1); 537 | assert_eq!(map[text], 1); 538 | 539 | let mut t = ArrayString::<2>::new(); 540 | assert!(t.try_push_str(text).is_err()); 541 | assert_eq!(&t, ""); 542 | 543 | t.push_str("ab"); 544 | // DerefMut 545 | let tmut: &mut str = &mut t; 546 | assert_eq!(tmut, "ab"); 547 | 548 | // Test Error trait / try 549 | let t = || -> Result<(), Box> { 550 | let mut t = ArrayString::<2>::new(); 551 | t.try_push_str(text)?; 552 | Ok(()) 553 | }(); 554 | assert!(t.is_err()); 555 | } 556 | 557 | #[test] 558 | fn test_string_from() { 559 | let text = "hello world"; 560 | // Test `from` constructor 561 | let u = ArrayString::<11>::from(text).unwrap(); 562 | assert_eq!(&u, text); 563 | assert_eq!(u.len(), text.len()); 564 | } 565 | 566 | #[test] 567 | fn test_string_parse_from_str() { 568 | let text = "hello world"; 569 | let u: ArrayString<11> = text.parse().unwrap(); 570 | assert_eq!(&u, text); 571 | assert_eq!(u.len(), text.len()); 572 | } 573 | 574 | #[test] 575 | fn test_string_from_bytes() { 576 | let text = "hello world"; 577 | let u = ArrayString::from_byte_string(b"hello world").unwrap(); 578 | assert_eq!(&u, text); 579 | assert_eq!(u.len(), text.len()); 580 | } 581 | 582 | #[test] 583 | fn test_string_clone() { 584 | let text = "hi"; 585 | let mut s = ArrayString::<4>::new(); 586 | s.push_str("abcd"); 587 | let t = ArrayString::<4>::from(text).unwrap(); 588 | s.clone_from(&t); 589 | assert_eq!(&t, &s); 590 | } 591 | 592 | #[test] 593 | fn test_string_push() { 594 | let text = "abcαβγ"; 595 | let mut s = ArrayString::<8>::new(); 596 | for c in text.chars() { 597 | if let Err(_) = s.try_push(c) { 598 | break; 599 | } 600 | } 601 | assert_eq!("abcαβ", &s[..]); 602 | s.push('x'); 603 | assert_eq!("abcαβx", &s[..]); 604 | assert!(s.try_push('x').is_err()); 605 | } 606 | 607 | 608 | #[test] 609 | fn test_insert_at_length() { 610 | let mut v = ArrayVec::<_, 8>::new(); 611 | let result1 = v.try_insert(0, "a"); 612 | let result2 = v.try_insert(1, "b"); 613 | assert!(result1.is_ok() && result2.is_ok()); 614 | assert_eq!(&v[..], &["a", "b"]); 615 | } 616 | 617 | #[should_panic] 618 | #[test] 619 | fn test_insert_out_of_bounds() { 620 | let mut v = ArrayVec::<_, 8>::new(); 621 | let _ = v.try_insert(1, "test"); 622 | } 623 | 624 | /* 625 | * insert that pushes out the last 626 | let mut u = ArrayVec::from([1, 2, 3, 4]); 627 | let ret = u.try_insert(3, 99); 628 | assert_eq!(&u[..], &[1, 2, 3, 99]); 629 | assert_matches!(ret, Err(_)); 630 | let ret = u.try_insert(4, 77); 631 | assert_eq!(&u[..], &[1, 2, 3, 99]); 632 | assert_matches!(ret, Err(_)); 633 | */ 634 | 635 | #[test] 636 | fn test_drop_in_insert() { 637 | use std::cell::Cell; 638 | 639 | let flag = &Cell::new(0); 640 | 641 | struct Bump<'a>(&'a Cell); 642 | 643 | impl<'a> Drop for Bump<'a> { 644 | fn drop(&mut self) { 645 | let n = self.0.get(); 646 | self.0.set(n + 1); 647 | } 648 | } 649 | 650 | flag.set(0); 651 | 652 | { 653 | let mut array = ArrayVec::<_, 2>::new(); 654 | array.push(Bump(flag)); 655 | array.insert(0, Bump(flag)); 656 | assert_eq!(flag.get(), 0); 657 | let ret = array.try_insert(1, Bump(flag)); 658 | assert_eq!(flag.get(), 0); 659 | assert_matches!(ret, Err(_)); 660 | drop(ret); 661 | assert_eq!(flag.get(), 1); 662 | } 663 | assert_eq!(flag.get(), 3); 664 | } 665 | 666 | #[test] 667 | fn test_pop_at() { 668 | let mut v = ArrayVec::::new(); 669 | let s = String::from; 670 | v.push(s("a")); 671 | v.push(s("b")); 672 | v.push(s("c")); 673 | v.push(s("d")); 674 | 675 | assert_eq!(v.pop_at(4), None); 676 | assert_eq!(v.pop_at(1), Some(s("b"))); 677 | assert_eq!(v.pop_at(1), Some(s("c"))); 678 | assert_eq!(v.pop_at(2), None); 679 | assert_eq!(&v[..], &["a", "d"]); 680 | } 681 | 682 | #[test] 683 | #[cfg(not(target_pointer_width = "16"))] 684 | fn test_sizes() { 685 | let v = ArrayVec::from([0u8; 1 << 16]); 686 | assert_eq!(vec![0u8; v.len()], &v[..]); 687 | } 688 | 689 | #[test] 690 | fn test_default() { 691 | use std::net; 692 | let s: ArrayString<4> = Default::default(); 693 | // Something without `Default` implementation. 694 | let v: ArrayVec = Default::default(); 695 | assert_eq!(s.len(), 0); 696 | assert_eq!(v.len(), 0); 697 | } 698 | 699 | #[test] 700 | fn test_extend_zst() { 701 | let mut range = 0..10; 702 | #[derive(Copy, Clone, PartialEq, Debug)] 703 | struct Z; // Zero sized type 704 | 705 | let mut array: ArrayVec<_, 5> = range.by_ref().take(5).map(|_| Z).collect(); 706 | assert_eq!(&array[..], &[Z; 5]); 707 | assert_eq!(range.next(), Some(5)); 708 | 709 | array.extend(range.by_ref().take(0).map(|_| Z)); 710 | assert_eq!(range.next(), Some(6)); 711 | 712 | let mut array: ArrayVec<_, 10> = (0..3).map(|_| Z).collect(); 713 | assert_eq!(&array[..], &[Z; 3]); 714 | array.extend((3..5).map(|_| Z)); 715 | assert_eq!(&array[..], &[Z; 5]); 716 | assert_eq!(array.len(), 5); 717 | } 718 | 719 | #[test] 720 | fn test_try_from_argument() { 721 | use core::convert::TryFrom; 722 | let v = ArrayString::<16>::try_from(format_args!("Hello {}", 123)).unwrap(); 723 | assert_eq!(&v, "Hello 123"); 724 | } 725 | 726 | #[test] 727 | fn allow_max_capacity_arrayvec_type() { 728 | // this type is allowed to be used (but can't be constructed) 729 | let _v: ArrayVec<(), {usize::MAX}>; 730 | } 731 | 732 | #[should_panic(expected="largest supported capacity")] 733 | #[cfg(not(target_pointer_width = "16"))] 734 | #[test] 735 | fn deny_max_capacity_arrayvec_value() { 736 | // this type is allowed to be used (but can't be constructed) 737 | let _v: ArrayVec<(), {usize::MAX}> = ArrayVec::new(); 738 | } 739 | 740 | #[should_panic(expected="index out of bounds")] 741 | #[cfg(not(target_pointer_width = "16"))] 742 | #[test] 743 | fn deny_max_capacity_arrayvec_value_const() { 744 | // this type is allowed to be used (but can't be constructed) 745 | let _v: ArrayVec<(), {usize::MAX}> = ArrayVec::new_const(); 746 | } 747 | 748 | #[test] 749 | fn test_arrayvec_const_constructible() { 750 | const OF_U8: ArrayVec, 10> = ArrayVec::new_const(); 751 | 752 | let mut var = OF_U8; 753 | assert!(var.is_empty()); 754 | assert_eq!(var, ArrayVec::new()); 755 | var.push(vec![3, 5, 8]); 756 | assert_eq!(var[..], [vec![3, 5, 8]]); 757 | } 758 | 759 | #[test] 760 | fn test_arraystring_const_constructible() { 761 | const AS: ArrayString<10> = ArrayString::new_const(); 762 | 763 | let mut var = AS; 764 | assert!(var.is_empty()); 765 | assert_eq!(var, ArrayString::new()); 766 | var.push_str("hello"); 767 | assert_eq!(var, *"hello"); 768 | } 769 | 770 | 771 | #[test] 772 | fn test_arraystring_zero_filled_has_some_sanity_checks() { 773 | let string = ArrayString::<4>::zero_filled(); 774 | assert_eq!(string.as_str(), "\0\0\0\0"); 775 | assert_eq!(string.len(), 4); 776 | } 777 | --------------------------------------------------------------------------------