stackvector-1.0.6/.gitignore010066400017500001750000000000361340241413300142530ustar0000000000000000/target **/*.rs.bk Cargo.lock stackvector-1.0.6/.travis.yml010066400017500001750000000005201340243674400144060ustar0000000000000000language: rust rust: - 1.26.0 - nightly - beta - stable # Bugs in issue 5 on nightly and beta on Travis, not reproducing on a local # machine. matrix: allow_failures: - rust: nightly - rust: beta script: | cargo build && cargo test && ([ $TRAVIS_RUST_VERSION != nightly ] || cargo check --no-default-features) stackvector-1.0.6/Cargo.toml.orig010066400017500001750000000012421350271371200151600ustar0000000000000000[package] authors = ["Alex Huszagh "] autobenches = false categories = ["data-structures"] description = "StackVec: vector-like facade for stack-allocated arrays." documentation = "https://docs.rs/stackvector" keywords = ["vec", "vector", "stack", "no_std"] license = "MIT/Apache-2.0" name = "stackvector" readme = "README.md" repository = "https://github.com/Alexhuszagh/rust-stackvector" version = "1.0.6" build = "build.rs" [badges] travis-ci = { repository = "Alexhuszagh/rust-stackvector" } [features] default = ["std"] # Use the `std` library. std = [] [dependencies] unreachable = "1.0.0" [build-dependencies] rustc_version = "0.2" stackvector-1.0.6/Cargo.toml0000644000000022100000000000000114200ustar00# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g. crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] name = "stackvector" version = "1.0.6" authors = ["Alex Huszagh "] build = "build.rs" description = "StackVec: vector-like facade for stack-allocated arrays." documentation = "https://docs.rs/stackvector" readme = "README.md" keywords = ["vec", "vector", "stack", "no_std"] categories = ["data-structures"] license = "MIT/Apache-2.0" repository = "https://github.com/Alexhuszagh/rust-stackvector" [dependencies.unreachable] version = "1.0.0" [build-dependencies.rustc_version] version = "0.2" [features] default = ["std"] std = [] [badges.travis-ci] repository = "Alexhuszagh/rust-stackvector" stackvector-1.0.6/LICENSE-APACHE010066400017500001750000000251421340241771000142200ustar0000000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. stackvector-1.0.6/LICENSE-MIT010066400017500001750000000017771340241772300137440ustar0000000000000000Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. stackvector-1.0.6/README.md010066400017500001750000000010051350252536200135470ustar0000000000000000rust-stackvector ================ [Documentation](https://docs.rs/stackvector/) [Release notes](https://github.com/Alexhuszagh/rust-stackvector/releases) "StackVec": vector-like facade for stack-allocated arrays. # License StackVector is derived from Servo's [smallvec](https://github.com/servo/rust-smallve), and like smallvec, it is dual licensed under either the MIT or Apache 2.0 license. # Version Support Stackvector has been tested on version of Rustc as low as 1.20.0 (needed for `mem::ManuallyDrop`). stackvector-1.0.6/build.rs010066400017500001750000000010061350252535600137410ustar0000000000000000extern crate rustc_version; fn version_parse(version: &str) -> rustc_version::Version { rustc_version::Version::parse(version).unwrap() } fn main() { println!("cargo:rerun-if-changed=build.rs"); let version = rustc_version::version().unwrap(); // We need at minimum version 1.20.0. assert!(version >= version_parse("1.20.0")); if version >= version_parse("1.26.0") { println!("cargo:rustc-cfg=has_range_inclusive"); println!("cargo:rustc-cfg=has_pointer_methods"); } } stackvector-1.0.6/src/lib.rs010066400017500001750000001321131350271370600142010ustar0000000000000000//! Vector-like class allocated entirely on the stack. //! //! Shallow wrapper around an underlying `Array`, which panics if the //! array bounds are exceeded. //! //! # no_std support //! //! By default, `smallvec` depends on `libstd`. However, it can be configured to use the unstable //! `liballoc` API instead, for use on platforms that have `liballoc` but not `libstd`. This //! configuration is currently unstable and is not guaranteed to work on all versions of Rust. //! //! To depend on `smallvec` without `libstd`, use `default-features = false` in the `smallvec` //! section of Cargo.toml to disable its `"std"` feature. //! //! Adapted from Servo's smallvec: //! https://github.com/servo/rust-smallve //! //! StackVec is distributed under the same terms as the smallvec and //! lexical, that is, it is dual licensed under either the MIT or Apache //! 2.0 license. #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), feature(alloc))] #[cfg(not(feature = "std"))] #[macro_use] extern crate alloc; #[cfg(not(feature = "std"))] use alloc::vec::Vec; extern crate unreachable; use unreachable::UncheckedOptionExt; /// Facade around the core features for name mangling. pub(crate) mod lib { #[cfg(feature = "std")] pub(crate) use std::*; #[cfg(not(feature = "std"))] pub(crate) use core::*; } use lib::borrow::{Borrow, BorrowMut}; use lib::{cmp, fmt, hash, iter, mem, ops, ptr, slice}; #[cfg(feature = "std")] use lib::io; // POINTER METHODS // Certain pointer methods aren't implemented below Rustc versions 1.26. // We implement a dummy version here. trait PointerMethods { // Add to the pointer (use padd to avoid conflict with ptr::add). unsafe fn padd(self, count: usize) -> Self; } impl PointerMethods for *const T { #[inline(always)] unsafe fn padd(self, count: usize) -> Self { #[cfg(has_pointer_methods)] return self.add(count); #[cfg(not(has_pointer_methods))] return self.offset(count as isize); } } impl PointerMethods for *mut T { #[inline(always)] unsafe fn padd(self, count: usize) -> Self { #[cfg(has_pointer_methods)] return self.add(count); #[cfg(not(has_pointer_methods))] return self.offset(count as isize); } } // ARRAY /// Types that can be used as the backing store for a StackVec pub unsafe trait Array { /// The type of the array's elements. type Item; /// Returns the number of items the array can hold. fn size() -> usize; /// Returns a pointer to the first element of the array. fn ptr(&self) -> *const Self::Item; /// Returns a mutable pointer to the first element of the array. fn ptr_mut(&mut self) -> *mut Self::Item; } macro_rules! impl_array( ($($size:expr),+) => { $( unsafe impl Array for [T; $size] { type Item = T; fn size() -> usize { $size } fn ptr(&self) -> *const T { self.as_ptr() } fn ptr_mut(&mut self) -> *mut T { self.as_mut_ptr() } } )+ } ); impl_array! { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 24, 32, 36, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000 } // VEC LIKE /// Common operations implemented by both `Vec` and `StackVec`. /// /// This can be used to write generic code that works with both `Vec` and `StackVec`. /// /// ## Example /// /// ```rust /// use stackvector::{VecLike, StackVec}; /// /// fn initialize>(v: &mut V) { /// for i in 0..5 { /// v.push(i); /// } /// } /// /// let mut vec = Vec::new(); /// initialize(&mut vec); /// /// let mut stack_vec = StackVec::<[u8; 8]>::new(); /// initialize(&mut stack_vec); /// ``` #[deprecated(note = "Use `Extend` and `Deref<[T]>` instead")] pub trait VecLike: ops::Index + ops::IndexMut + ops::Index, Output=[T]> + ops::IndexMut> + ops::Index, Output=[T]> + ops::IndexMut> + ops::Index, Output=[T]> + ops::IndexMut> + ops::Index + ops::IndexMut + ops::DerefMut + Extend { /// Append an element to the vector. fn push(&mut self, value: T); /// Pop an element from the end of the vector. fn pop(&mut self) -> Option; } #[allow(deprecated)] impl VecLike for Vec { #[inline] fn push(&mut self, value: T) { Vec::push(self, value); } #[inline] fn pop(&mut self) -> Option { Vec::pop(self) } } // EXTEND FROM SLICE /// Trait to be implemented by a collection that can be extended from a slice /// /// ## Example /// /// ```rust /// use stackvector::{ExtendFromSlice, StackVec}; /// /// fn initialize>(v: &mut V) { /// v.extend_from_slice(b"Test!"); /// } /// /// let mut vec = Vec::new(); /// initialize(&mut vec); /// assert_eq!(&vec, b"Test!"); /// /// let mut stack_vec = StackVec::<[u8; 8]>::new(); /// initialize(&mut stack_vec); /// assert_eq!(&stack_vec as &[_], b"Test!"); /// ``` pub trait ExtendFromSlice { /// Extends a collection from a slice of its element type fn extend_from_slice(&mut self, other: &[T]); } impl ExtendFromSlice for Vec { fn extend_from_slice(&mut self, other: &[T]) { Vec::extend_from_slice(self, other) } } // DRAIN /// An iterator that removes the items from a `StackVec` and yields them by value. /// /// Returned from [`StackVec::drain`][1]. /// /// [1]: struct.StackVec.html#method.drain pub struct Drain<'a, T: 'a> { iter: slice::IterMut<'a, T>, } impl<'a, T: 'a> Iterator for Drain<'a,T> { type Item = T; #[inline] fn next(&mut self) -> Option { self.iter.next().map(|reference| unsafe { ptr::read(reference) }) } #[inline] fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } impl<'a, T: 'a> DoubleEndedIterator for Drain<'a, T> { #[inline] fn next_back(&mut self) -> Option { self.iter.next_back().map(|reference| unsafe { ptr::read(reference) }) } } impl<'a, T> ExactSizeIterator for Drain<'a, T> { } impl<'a, T: 'a> Drop for Drain<'a,T> { fn drop(&mut self) { // Destroy the remaining elements. for _ in self.by_ref() {} } } // SET LEN ON DROP /// Set the length of the vec when the `SetLenOnDrop` value goes out of scope. /// /// Copied from https://github.com/rust-lang/rust/pull/36355 struct SetLenOnDrop<'a> { len: &'a mut usize, local_len: usize, } impl<'a> SetLenOnDrop<'a> { #[inline] fn new(len: &'a mut usize) -> Self { SetLenOnDrop { local_len: *len, len: len } } #[inline] fn increment_len(&mut self, increment: usize) { self.local_len += increment; } } impl<'a> Drop for SetLenOnDrop<'a> { #[inline] fn drop(&mut self) { *self.len = self.local_len; } } // STACKVEC /// A `Vec`-like container that stores elements on the stack. /// /// The amount of data that a `StackVec` can store inline depends on its backing store. The backing /// store can be any type that implements the `Array` trait; usually it is a small fixed-sized /// array. For example a `StackVec<[u64; 8]>` can hold up to eight 64-bit integers inline. /// /// ## Example /// /// ```rust,should_panic /// use stackvector::StackVec; /// let mut v = StackVec::<[u8; 4]>::new(); // initialize an empty vector /// /// // The vector can hold up to 4 items without spilling onto the heap. /// v.extend(0..4); /// assert_eq!(v.len(), 4); /// /// // Pushing another element will force the buffer to spill and panic: /// v.push(4); /// ``` pub struct StackVec { // The capacity field is used for iteration and other optimizations. // Publicly expose the fields, so they may be used in constant // initialization. pub length: usize, pub data: mem::ManuallyDrop, } impl StackVec { /// Construct an empty vector #[inline] pub fn new() -> StackVec { unsafe { StackVec { length: 0, data: mem::uninitialized(), } } } /// Construct a new `StackVec` from a `Vec`. /// /// Elements will be copied to the inline buffer if vec.len() <= A::size(). /// /// ```rust /// use stackvector::StackVec; /// /// let vec = vec![1, 2, 3, 4, 5]; /// let stack_vec: StackVec<[_; 5]> = StackVec::from_vec(vec); /// /// assert_eq!(&*stack_vec, &[1, 2, 3, 4, 5]); /// ``` #[inline] pub fn from_vec(vec: Vec) -> StackVec { assert!(vec.len() <= A::size()); unsafe { Self::from_vec_unchecked(vec) } } /// Construct a new `StackVec` from a `Vec` without bounds checking. pub unsafe fn from_vec_unchecked(mut vec: Vec) -> StackVec { let mut data: A = mem::uninitialized(); let len = vec.len(); vec.set_len(0); ptr::copy_nonoverlapping(vec.as_ptr(), data.ptr_mut(), len); StackVec { length: len, data: mem::ManuallyDrop::new(data), } } /// Constructs a new `StackVec` on the stack from an `A` without /// copying elements. /// /// ```rust /// use stackvector::StackVec; /// /// let buf = [1, 2, 3, 4, 5]; /// let stack_vec: StackVec<_> = StackVec::from_buf(buf); /// /// assert_eq!(&*stack_vec, &[1, 2, 3, 4, 5]); /// ``` #[inline] pub fn from_buf(buf: A) -> StackVec { StackVec { length: A::size(), data: mem::ManuallyDrop::new(buf), } } /// Constructs a new `StackVec` on the stack from an `A` without /// copying elements. Also sets the length, which must be less or /// equal to the size of `buf`. /// /// ```rust /// use stackvector::StackVec; /// /// let buf = [1, 2, 3, 4, 5, 0, 0, 0]; /// let stack_vec: StackVec<_> = StackVec::from_buf_and_len(buf, 5); /// /// assert_eq!(&*stack_vec, &[1, 2, 3, 4, 5]); /// ``` #[inline] pub fn from_buf_and_len(buf: A, len: usize) -> StackVec { assert!(len <= A::size()); unsafe { StackVec::from_buf_and_len_unchecked(buf, len) } } /// Constructs a new `StackVec` on the stack from an `A` without /// copying elements. Also sets the length. The user is responsible /// for ensuring that `len <= A::size()`. /// /// ```rust /// use stackvector::StackVec; /// /// let buf = [1, 2, 3, 4, 5, 0, 0, 0]; /// let stack_vec: StackVec<_> = unsafe { /// StackVec::from_buf_and_len_unchecked(buf, 5) /// }; /// /// assert_eq!(&*stack_vec, &[1, 2, 3, 4, 5]); /// ``` #[inline] pub unsafe fn from_buf_and_len_unchecked(buf: A, len: usize) -> StackVec { StackVec { length: len, data: mem::ManuallyDrop::new(buf), } } /// Sets the length of a vector. /// /// This will explicitly set the size of the vector, without actually /// modifying its buffers, so it is up to the caller to ensure that the /// vector is actually the specified size. #[inline] pub unsafe fn set_len(&mut self, new_len: usize) { self.length = new_len; } /// The number of elements stored in the vector. #[inline] pub fn len(&self) -> usize { self.length } /// If the vector is empty. #[inline] pub fn is_empty(&self) -> bool { self.len() == 0 } /// The number of items the vector can hold. #[inline] pub fn capacity(&self) -> usize { A::size() } /// Empty the vector and return an iterator over its former contents. pub fn drain(&mut self) -> Drain { unsafe { let slice = slice::from_raw_parts_mut(self.as_mut_ptr(), self.len()); self.set_len(0); Drain { iter: slice.iter_mut(), } } } /// Append an item to the vector. #[inline] pub fn push(&mut self, value: A::Item) { assert!(self.len() < self.capacity()); unsafe { ptr::write(self.as_mut_ptr().padd(self.length), value); self.length += 1; } } /// Remove an item from the end of the vector and return it, or None if empty. #[inline] pub fn pop(&mut self) -> Option { unsafe { if self.len() == 0 { None } else { self.length -=1; Some(ptr::read(self.as_mut_ptr().padd(self.length))) } } } /// Shorten the vector, keeping the first `len` elements and dropping the rest. /// /// If `len` is greater than or equal to the vector's current length, this has no /// effect. /// `shrink_to_fit` after truncating. pub fn truncate(&mut self, len: usize) { unsafe { while len < self.length { self.length -= 1; ptr::drop_in_place(self.as_mut_ptr().padd(self.length)); } } } /// Extracts a slice containing the entire vector. /// /// Equivalent to `&s[..]`. #[inline] pub fn as_slice(&self) -> &[A::Item] { self } /// Extracts a mutable slice of the entire vector. /// /// Equivalent to `&mut s[..]`. #[inline] pub fn as_mut_slice(&mut self) -> &mut [A::Item] { self } /// Remove the element at position `index`, replacing it with the last element. /// /// This does not preserve ordering, but is O(1). /// /// Panics if `index` is out of bounds. #[inline] pub fn swap_remove(&mut self, index: usize) -> A::Item { let len = self.len(); self.swap(len - 1, index); unsafe { self.pop().unchecked_unwrap() } } /// Remove all elements from the vector. #[inline] pub fn clear(&mut self) { self.truncate(0); } /// Remove and return the element at position `index`, shifting all elements after it to the /// left. /// /// Panics if `index` is out of bounds. pub fn remove(&mut self, index: usize) -> A::Item { assert!(index < self.len()); unsafe { self.length -= 1; let ptr = self.as_mut_ptr().padd(index); let item = ptr::read(ptr); ptr::copy(ptr.offset(1), ptr, self.length - index); item } } /// Insert an element at position `index`, shifting all elements after it to the right. /// /// Panics if `index` is out of bounds. pub fn insert(&mut self, index: usize, element: A::Item) { assert!(index < self.len() && self.len() < self.capacity()); unsafe { let ptr = self.as_mut_ptr().padd(index); ptr::copy(ptr, ptr.offset(1), self.length - index); ptr::write(ptr, element); self.length += 1; } } /// Insert multiple elements at position `index`, shifting all following elements toward the /// back. pub fn insert_many>(&mut self, index: usize, iterable: I) { assert!(index <= self.len()); let iter = iterable.into_iter(); let (lower_bound, upper_bound) = iter.size_hint(); let upper_bound = upper_bound.expect("iterable must provide upper bound."); assert!(self.len() + upper_bound <= self.capacity()); if index == self.len() { return self.extend(iter); } unsafe { let old_len = self.len(); let ptr = self.as_mut_ptr().padd(index); // Move the trailing elements. ptr::copy(ptr, ptr.padd(lower_bound), old_len - index); // In case the iterator panics, don't double-drop the items we just copied above. self.set_len(index); let mut num_added = 0; for element in iter { let cur = ptr.padd(num_added); ptr::write(cur, element); num_added += 1; } self.set_len(old_len + num_added); } } /// Convert a StackVec to a Vec. pub fn into_vec(self) -> Vec { self.into_iter().collect() } /// Convert the StackVec into an `A`. pub fn into_inner(self) -> Result { if self.len() != A::size() { Err(self) } else { unsafe { let data = ptr::read(&self.data); mem::forget(self); Ok(mem::ManuallyDrop::into_inner(data)) } } } /// Retains only the elements specified by the predicate. /// /// In other words, remove all elements `e` such that `f(&e)` returns `false`. /// This method operates in place and preserves the order of the retained /// elements. pub fn retain bool>(&mut self, mut f: F) { let mut del = 0; let len = self.len(); for i in 0..len { if !f(&mut self[i]) { del += 1; } else if del > 0 { self.swap(i - del, i); } } self.truncate(len - del); } /// Removes consecutive duplicate elements. pub fn dedup(&mut self) where A::Item: PartialEq { self.dedup_by(|a, b| a == b); } /// Removes consecutive duplicate elements using the given equality relation. pub fn dedup_by(&mut self, mut same_bucket: F) where F: FnMut(&mut A::Item, &mut A::Item) -> bool { // See the implementation of Vec::dedup_by in the // standard library for an explanation of this algorithm. let len = self.len(); if len <= 1 { return; } let ptr = self.as_mut_ptr(); let mut w: usize = 1; unsafe { for r in 1..len { let p_r = ptr.offset(r as isize); let p_wm1 = ptr.offset((w - 1) as isize); if !same_bucket(&mut *p_r, &mut *p_wm1) { if r != w { let p_w = p_wm1.offset(1); mem::swap(&mut *p_r, &mut *p_w); } w += 1; } } } self.truncate(w); } /// Removes consecutive elements that map to the same key. pub fn dedup_by_key(&mut self, mut key: F) where F: FnMut(&mut A::Item) -> K, K: PartialEq { self.dedup_by(|a, b| key(a) == key(b)); } } impl StackVec where A::Item: Copy { /// Copy the elements from a slice into a new `StackVec`. /// /// For slices of `Copy` types, this is more efficient than `StackVec::from(slice)`. pub fn from_slice(slice: &[A::Item]) -> Self { assert!(slice.len() <= A::size()); StackVec { length: slice.len(), data: unsafe { let mut data: A = mem::uninitialized(); ptr::copy_nonoverlapping(slice.as_ptr(), data.ptr_mut(), slice.len()); mem::ManuallyDrop::new(data) } } } /// Copy elements from a slice into the vector at position `index`, shifting any following /// elements toward the back. /// /// For slices of `Copy` types, this is more efficient than `insert`. pub fn insert_from_slice(&mut self, index: usize, slice: &[A::Item]) { assert!(index <= self.len() && self.len() + slice.len() <= self.capacity()); unsafe { let len = self.len(); let slice_ptr = slice.as_ptr(); let ptr = self.as_mut_ptr().padd(index); ptr::copy(ptr, ptr.padd(slice.len()), len - index); ptr::copy_nonoverlapping(slice_ptr, ptr, slice.len()); self.set_len(len + slice.len()); } } /// Copy elements from a slice and append them to the vector. /// /// For slices of `Copy` types, this is more efficient than `extend`. #[inline] pub fn extend_from_slice(&mut self, slice: &[A::Item]) { let len = self.len(); self.insert_from_slice(len, slice); } } impl StackVec where A::Item: Clone { /// Resizes the vector so that its length is equal to `len`. /// /// If `len` is less than the current length, the vector simply truncated. /// /// If `len` is greater than the current length, `value` is appended to the /// vector until its length equals `len`. pub fn resize(&mut self, len: usize, value: A::Item) { assert!(len <= self.capacity()); let old_len = self.len(); if len > old_len { self.extend(iter::repeat(value).take(len - old_len)); } else { self.truncate(len); } } /// Creates a `StackVec` with `n` copies of `elem`. /// ``` /// use stackvector::StackVec; /// /// let v = StackVec::<[char; 128]>::from_elem('d', 2); /// assert_eq!(v, StackVec::from_buf(['d', 'd'])); /// ``` pub fn from_elem(elem: A::Item, n: usize) -> Self { assert!(n <= A::size()); let mut v = StackVec::::new(); unsafe { let ptr = v.as_mut_ptr(); let mut local_len = SetLenOnDrop::new(&mut v.length); for i in 0..n as isize { ptr::write(ptr.offset(i), elem.clone()); local_len.increment_len(1); } } v } } impl ops::Deref for StackVec { type Target = [A::Item]; #[inline] fn deref(&self) -> &[A::Item] { unsafe { slice::from_raw_parts(self.data.ptr(), self.len()) } } } impl ops::DerefMut for StackVec { #[inline] fn deref_mut(&mut self) -> &mut [A::Item] { unsafe { slice::from_raw_parts_mut(self.data.ptr_mut(), self.len()) } } } impl AsRef<[A::Item]> for StackVec { #[inline] fn as_ref(&self) -> &[A::Item] { self } } impl AsMut<[A::Item]> for StackVec { #[inline] fn as_mut(&mut self) -> &mut [A::Item] { self } } impl Borrow<[A::Item]> for StackVec { #[inline] fn borrow(&self) -> &[A::Item] { self } } impl BorrowMut<[A::Item]> for StackVec { #[inline] fn borrow_mut(&mut self) -> &mut [A::Item] { self } } #[cfg(feature = "std")] impl> io::Write for StackVec { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { self.extend_from_slice(buf); Ok(buf.len()) } #[inline] fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { self.extend_from_slice(buf); Ok(()) } #[inline] fn flush(&mut self) -> io::Result<()> { Ok(()) } } impl<'a, A: Array> From<&'a [A::Item]> for StackVec where A::Item: Clone { #[inline] fn from(slice: &'a [A::Item]) -> StackVec { slice.into_iter().cloned().collect() } } impl From> for StackVec { #[inline] fn from(vec: Vec) -> StackVec { StackVec::from_vec(vec) } } impl From for StackVec { #[inline] fn from(array: A) -> StackVec { StackVec::from_buf(array) } } macro_rules! impl_index { ($index_type: ty, $output_type: ty) => { impl ops::Index<$index_type> for StackVec { type Output = $output_type; #[inline] fn index(&self, index: $index_type) -> &$output_type { &(&**self)[index] } } impl ops::IndexMut<$index_type> for StackVec { #[inline] fn index_mut(&mut self, index: $index_type) -> &mut $output_type { &mut (&mut **self)[index] } } } } impl_index!(usize, A::Item); impl_index!(ops::Range, [A::Item]); impl_index!(ops::RangeFrom, [A::Item]); impl_index!(ops::RangeFull, [A::Item]); impl_index!(ops::RangeTo, [A::Item]); #[cfg(has_range_inclusive)] impl_index!(ops::RangeInclusive, [A::Item]); #[cfg(has_range_inclusive)] impl_index!(ops::RangeToInclusive, [A::Item]); impl ExtendFromSlice for StackVec where A::Item: Copy { fn extend_from_slice(&mut self, other: &[A::Item]) { StackVec::extend_from_slice(self, other) } } #[allow(deprecated)] impl VecLike for StackVec { #[inline] fn push(&mut self, value: A::Item) { StackVec::push(self, value); } #[inline] fn pop(&mut self) -> Option { StackVec::pop(self) } } impl iter::FromIterator for StackVec { fn from_iter>(iterable: I) -> StackVec { let mut v = StackVec::new(); v.extend(iterable); v } } impl Extend for StackVec { fn extend>(&mut self, iterable: I) { let mut iter = iterable.into_iter(); let (lower_bound, upper_bound) = iter.size_hint(); let upper_bound = upper_bound.expect("iterable must provide upper bound."); assert!(self.len() + upper_bound <= self.capacity()); unsafe { let len = self.len(); let ptr = self.as_mut_ptr().padd(len); let mut count = 0; while count < lower_bound { if let Some(out) = iter.next() { ptr::write(ptr.padd(count), out); count += 1; } else { break; } } self.set_len(len + count); } for elem in iter { self.push(elem); } } } impl fmt::Debug for StackVec where A::Item: fmt::Debug { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_list().entries(self.iter()).finish() } } impl Default for StackVec { #[inline] fn default() -> StackVec { StackVec::new() } } impl Drop for StackVec { fn drop(&mut self) { unsafe { ptr::drop_in_place(&mut self[..]); } } } impl Clone for StackVec where A::Item: Clone { fn clone(&self) -> StackVec { let mut new_vector = StackVec::new(); for element in self.iter() { new_vector.push(element.clone()) } new_vector } } impl PartialEq> for StackVec where A::Item: PartialEq { #[inline] fn eq(&self, other: &StackVec) -> bool { self[..] == other[..] } #[inline] fn ne(&self, other: &StackVec) -> bool { self[..] != other[..] } } impl Eq for StackVec where A::Item: Eq { } impl PartialOrd for StackVec where A::Item: PartialOrd { #[inline] fn partial_cmp(&self, other: &StackVec) -> Option { PartialOrd::partial_cmp(&**self, &**other) } } impl Ord for StackVec where A::Item: Ord { #[inline] fn cmp(&self, other: &StackVec) -> cmp::Ordering { Ord::cmp(&**self, &**other) } } impl hash::Hash for StackVec where A::Item: hash::Hash { fn hash(&self, state: &mut H) { (**self).hash(state) } } unsafe impl Send for StackVec where A::Item: Send { } /// An iterator that consumes a `StackVec` and yields its items by value. /// /// Returned from [`StackVec::into_iter`][1]. /// /// [1]: struct.StackVec.html#method.into_iter pub struct IntoIter { data: StackVec, current: usize, end: usize, } impl Drop for IntoIter { fn drop(&mut self) { for _ in self { } } } impl Iterator for IntoIter { type Item = A::Item; #[inline] fn next(&mut self) -> Option { if self.current == self.end { None } else { unsafe { let current = self.current; self.current += 1; Some(ptr::read(self.data.as_ptr().padd(current))) } } } #[inline] fn size_hint(&self) -> (usize, Option) { let size = self.end - self.current; (size, Some(size)) } } impl DoubleEndedIterator for IntoIter { #[inline] fn next_back(&mut self) -> Option { if self.current == self.end { None } else { unsafe { self.end -= 1; Some(ptr::read(self.data.as_ptr().padd(self.end))) } } } } impl ExactSizeIterator for IntoIter { } impl IntoIterator for StackVec { type IntoIter = IntoIter; type Item = A::Item; fn into_iter(mut self) -> Self::IntoIter { unsafe { // Set StackVec len to zero as `IntoIter` drop handles dropping of the elements let len = self.len(); self.set_len(0); IntoIter { data: self, current: 0, end: len, } } } } impl<'a, A: Array> IntoIterator for &'a StackVec { type IntoIter = slice::Iter<'a, A::Item>; type Item = &'a A::Item; fn into_iter(self) -> Self::IntoIter { self.iter() } } impl<'a, A: Array> IntoIterator for &'a mut StackVec { type IntoIter = slice::IterMut<'a, A::Item>; type Item = &'a mut A::Item; fn into_iter(self) -> Self::IntoIter { self.iter_mut() } } // STACKVEC MACRO /// Creates a [`StackVec`] containing the arguments. /// /// `stackvec!` allows `StackVec`s to be defined with the same syntax as array expressions. /// There are two forms of this macro: /// /// - Create a [`StackVec`] containing a given list of elements: /// /// ``` /// # #[macro_use] extern crate stackvector; /// # use stackvector::StackVec; /// # fn main() { /// let v: StackVec<[_; 128]> = stackvec![1, 2, 3]; /// assert_eq!(v[0], 1); /// assert_eq!(v[1], 2); /// assert_eq!(v[2], 3); /// # } /// ``` /// /// - Create a [`StackVec`] from a given element and size: /// /// ``` /// # #[macro_use] extern crate stackvector; /// # use stackvector::StackVec; /// # fn main() { /// let v: StackVec<[_; 0x8000]> = stackvec![1; 3]; /// assert_eq!(v, StackVec::from_buf([1, 1, 1])); /// # } /// ``` /// /// Note that unlike array expressions this syntax supports all elements /// which implement [`Clone`] and the number of elements doesn't have to be /// a constant. /// /// This will use `clone` to duplicate an expression, so one should be careful /// using this with types having a nonstandard `Clone` implementation. For /// example, `stackvec![Rc::new(1); 5]` will create a vector of five references /// to the same boxed integer value, not five references pointing to independently /// boxed integers. #[macro_export] macro_rules! stackvec { // count helper: transform any expression into 1 (@one $x:expr) => (1usize); ($elem:expr; $n:expr) => ({ $crate::StackVec::from_elem($elem, $n) }); ($($x:expr),*$(,)*) => ({ // Allow an unused mut variable, since if the sequence is empty, // the vec will never be mutated. #[allow(unused_mut)] { let mut vec = $crate::StackVec::new(); $(vec.push($x);)* vec } }); } // TESTS // ----- #[cfg(test)] mod test { use super::*; use super::lib::iter::FromIterator; use super::lib::rc::Rc; #[test] pub fn test_zero() { let v = StackVec::<[usize; 0]>::new(); assert_eq!(v.len(), 0); } #[test] #[should_panic] pub fn test_panic() { let mut v = StackVec::<[usize; 0]>::new(); v.push(0); } // We heap allocate all these strings so that double frees will show up under valgrind. #[test] pub fn test_inline() { let mut v = StackVec::<[_; 16]>::new(); v.push("hello".to_owned()); v.push("there".to_owned()); assert_eq!(&*v, &[ "hello".to_owned(), "there".to_owned(), ][..]); } #[test] #[should_panic] pub fn test_spill() { let mut v = StackVec::<[_; 2]>::new(); v.push("hello".to_owned()); assert_eq!(v[0], "hello"); v.push("there".to_owned()); v.push("burma".to_owned()); assert_eq!(v[0], "hello"); v.push("shave".to_owned()); assert_eq!(&*v, &[ "hello".to_owned(), "there".to_owned(), "burma".to_owned(), "shave".to_owned(), ][..]); } #[test] #[should_panic] pub fn test_double_spill() { let mut v = StackVec::<[_; 2]>::new(); v.push("hello".to_owned()); v.push("there".to_owned()); v.push("burma".to_owned()); v.push("shave".to_owned()); v.push("hello".to_owned()); v.push("there".to_owned()); v.push("burma".to_owned()); v.push("shave".to_owned()); assert_eq!(&*v, &[ "hello".to_owned(), "there".to_owned(), "burma".to_owned(), "shave".to_owned(), "hello".to_owned(), "there".to_owned(), "burma".to_owned(), "shave".to_owned(), ][..]); } /// https://github.com/servo/rust-smallvec/issues/4 #[test] fn issue_4() { StackVec::<[Box; 2]>::new(); } /// https://github.com/servo/rust-smallvec/issues/5 #[test] fn issue_5() { assert!(Some(StackVec::<[&u32; 2]>::new()).is_some()); } #[test] fn drain_test() { let mut v: StackVec<[u8; 2]> = StackVec::new(); v.push(3); assert_eq!(v.drain().collect::>(), &[3]); } #[test] fn drain_rev_test() { let mut v: StackVec<[u8; 2]> = StackVec::new(); v.push(3); assert_eq!(v.drain().rev().collect::>(), &[3]); } #[test] fn into_iter() { let mut v: StackVec<[u8; 2]> = StackVec::new(); v.push(3); assert_eq!(v.into_iter().collect::>(), &[3]); } #[test] fn into_iter_rev() { let mut v: StackVec<[u8; 2]> = StackVec::new(); v.push(3); assert_eq!(v.into_iter().rev().collect::>(), &[3]); } #[test] fn into_iter_drop() { use lib::cell::Cell; struct DropCounter<'a>(&'a Cell); impl<'a> Drop for DropCounter<'a> { fn drop(&mut self) { self.0.set(self.0.get() + 1); } } { let cell = Cell::new(0); let mut v: StackVec<[DropCounter; 2]> = StackVec::new(); v.push(DropCounter(&cell)); v.into_iter(); assert_eq!(cell.get(), 1); } { let cell = Cell::new(0); let mut v: StackVec<[DropCounter; 2]> = StackVec::new(); v.push(DropCounter(&cell)); v.push(DropCounter(&cell)); assert!(v.into_iter().next().is_some()); assert_eq!(cell.get(), 2); } } #[test] fn test_capacity() { let v: StackVec<[u8; 2]> = StackVec::new(); assert_eq!(v.capacity(), 2); } #[test] fn test_truncate() { let mut v: StackVec<[Box; 8]> = StackVec::new(); for x in 0..8 { v.push(Box::new(x)); } v.truncate(4); assert_eq!(v.len(), 4); assert_eq!(*v.swap_remove(1), 1); assert_eq!(*v.remove(1), 3); v.insert(1, Box::new(3)); assert_eq!(&v.iter().map(|v| **v).collect::>(), &[0, 3, 2]); } #[test] fn test_insert_many() { let mut v: StackVec<[u8; 8]> = StackVec::new(); for x in 0..4 { v.push(x); } assert_eq!(v.len(), 4); v.insert_many(1, [5, 6].iter().cloned()); assert_eq!(&v.iter().map(|v| *v).collect::>(), &[0, 5, 6, 1, 2, 3]); } #[test] fn test_insert_from_slice() { let mut v: StackVec<[u8; 8]> = StackVec::new(); for x in 0..4 { v.push(x); } assert_eq!(v.len(), 4); v.insert_from_slice(1, &[5, 6]); assert_eq!(&v.iter().map(|v| *v).collect::>(), &[0, 5, 6, 1, 2, 3]); } #[test] fn test_extend_from_slice() { let mut v: StackVec<[u8; 8]> = StackVec::new(); for x in 0..4 { v.push(x); } assert_eq!(v.len(), 4); v.extend_from_slice(&[5, 6]); assert_eq!(&v.iter().map(|v| *v).collect::>(), &[0, 1, 2, 3, 5, 6]); } #[test] #[should_panic] fn test_drop_panic_smallvec() { // This test should only panic once, and not double panic, // which would mean a double drop struct DropPanic; impl Drop for DropPanic { fn drop(&mut self) { panic!("drop"); } } let mut v = StackVec::<[_; 1]>::new(); v.push(DropPanic); } #[test] fn test_eq() { let mut a: StackVec<[u32; 2]> = StackVec::new(); let mut b: StackVec<[u32; 2]> = StackVec::new(); let mut c: StackVec<[u32; 2]> = StackVec::new(); // a = [1, 2] a.push(1); a.push(2); // b = [1, 2] b.push(1); b.push(2); // c = [3, 4] c.push(3); c.push(4); assert!(a == b); assert!(a != c); } #[test] fn test_ord() { let mut a: StackVec<[u32; 2]> = StackVec::new(); let mut b: StackVec<[u32; 2]> = StackVec::new(); let mut c: StackVec<[u32; 2]> = StackVec::new(); // a = [1] a.push(1); // b = [1, 1] b.push(1); b.push(1); // c = [1, 2] c.push(1); c.push(2); assert!(a < b); assert!(b > a); assert!(b < c); assert!(c > b); } #[cfg(feature = "std")] #[test] fn test_hash() { use std::hash::Hash; use std::collections::hash_map::DefaultHasher; { let mut a: StackVec<[u32; 2]> = StackVec::new(); let b = [1, 2]; a.extend(b.iter().cloned()); let mut hasher = DefaultHasher::new(); assert_eq!(a.hash(&mut hasher), b.hash(&mut hasher)); } { let mut a: StackVec<[u32; 4]> = StackVec::new(); let b = [1, 2, 11, 12]; a.extend(b.iter().cloned()); let mut hasher = DefaultHasher::new(); assert_eq!(a.hash(&mut hasher), b.hash(&mut hasher)); } } #[test] fn test_as_ref() { let mut a: StackVec<[u32; 3]> = StackVec::new(); a.push(1); assert_eq!(a.as_ref(), [1]); a.push(2); assert_eq!(a.as_ref(), [1, 2]); a.push(3); assert_eq!(a.as_ref(), [1, 2, 3]); } #[test] fn test_as_mut() { let mut a: StackVec<[u32; 3]> = StackVec::new(); a.push(1); assert_eq!(a.as_mut(), [1]); a.push(2); assert_eq!(a.as_mut(), [1, 2]); a.push(3); assert_eq!(a.as_mut(), [1, 2, 3]); a.as_mut()[1] = 4; assert_eq!(a.as_mut(), [1, 4, 3]); } #[test] fn test_borrow() { use std::borrow::Borrow; let mut a: StackVec<[u32; 3]> = StackVec::new(); a.push(1); assert_eq!(a.borrow(), [1]); a.push(2); assert_eq!(a.borrow(), [1, 2]); a.push(3); assert_eq!(a.borrow(), [1, 2, 3]); } #[test] fn test_borrow_mut() { use std::borrow::BorrowMut; let mut a: StackVec<[u32; 3]> = StackVec::new(); a.push(1); assert_eq!(a.borrow_mut(), [1]); a.push(2); assert_eq!(a.borrow_mut(), [1, 2]); a.push(3); assert_eq!(a.borrow_mut(), [1, 2, 3]); BorrowMut::<[u32]>::borrow_mut(&mut a)[1] = 4; assert_eq!(a.borrow_mut(), [1, 4, 3]); } #[test] fn test_from() { assert_eq!(&StackVec::<[u32; 2]>::from(&[1][..])[..], [1]); assert_eq!(&StackVec::<[u32; 3]>::from(&[1, 2, 3][..])[..], [1, 2, 3]); let vec = vec![]; let stack_vec: StackVec<[u8; 3]> = StackVec::from(vec); assert_eq!(&*stack_vec, &[]); drop(stack_vec); let vec = vec![1, 2, 3, 4, 5]; let stack_vec: StackVec<[u8; 5]> = StackVec::from(vec); assert_eq!(&*stack_vec, &[1, 2, 3, 4, 5]); drop(stack_vec); let vec = vec![1, 2, 3, 4, 5]; let stack_vec: StackVec<[u8; 5]> = StackVec::from(vec); assert_eq!(&*stack_vec, &[1, 2, 3, 4, 5]); drop(stack_vec); let array = [1]; let stack_vec: StackVec<[u8; 1]> = StackVec::from(array); assert_eq!(&*stack_vec, &[1]); drop(stack_vec); let array = [99; 128]; let stack_vec: StackVec<[u8; 128]> = StackVec::from(array); assert_eq!(&*stack_vec, vec![99u8; 128].as_slice()); drop(stack_vec); } #[test] fn test_from_slice() { assert_eq!(&StackVec::<[u32; 2]>::from_slice(&[1][..])[..], [1]); assert_eq!(&StackVec::<[u32; 3]>::from_slice(&[1, 2, 3][..])[..], [1, 2, 3]); } #[test] fn test_exact_size_iterator() { let mut vec = StackVec::<[u32; 3]>::from(&[1, 2, 3][..]); assert_eq!(vec.clone().into_iter().len(), 3); assert_eq!(vec.drain().len(), 3); } #[test] #[allow(deprecated)] fn veclike_deref_slice() { use super::VecLike; fn test>(vec: &mut T) { assert!(!vec.is_empty()); assert_eq!(vec.len(), 3); vec.sort(); assert_eq!(&vec[..], [1, 2, 3]); } let mut vec = StackVec::<[i32; 3]>::from(&[3, 1, 2][..]); test(&mut vec); } #[test] fn test_into_vec() { let vec = StackVec::<[u8; 2]>::from_iter(0..2); assert_eq!(vec.into_vec(), vec![0, 1]); let vec = StackVec::<[u8; 3]>::from_iter(0..3); assert_eq!(vec.into_vec(), vec![0, 1, 2]); } #[test] fn test_into_inner() { let vec = StackVec::<[u8; 2]>::from_iter(0..2); assert_eq!(vec.into_inner(), Ok([0, 1])); let vec = StackVec::<[u8; 2]>::from_iter(0..1); assert_eq!(vec.clone().into_inner(), Err(vec)); let vec = StackVec::<[u8; 3]>::from_iter(0..3); assert_eq!(vec.clone().into_inner(), Ok([0, 1, 2])); let vec = StackVec::<[u8; 4]>::from_iter(0..3); assert_eq!(vec.clone().into_inner(), Err(vec)); } #[test] fn test_from_vec() { let vec = vec![]; let stack_vec: StackVec<[u8; 3]> = StackVec::from_vec(vec); assert_eq!(&*stack_vec, &[]); drop(stack_vec); let vec = vec![]; let stack_vec: StackVec<[u8; 1]> = StackVec::from_vec(vec); assert_eq!(&*stack_vec, &[]); drop(stack_vec); let vec = vec![1]; let stack_vec: StackVec<[u8; 3]> = StackVec::from_vec(vec); assert_eq!(&*stack_vec, &[1]); drop(stack_vec); let vec = vec![1, 2, 3]; let stack_vec: StackVec<[u8; 3]> = StackVec::from_vec(vec); assert_eq!(&*stack_vec, &[1, 2, 3]); drop(stack_vec); let vec = vec![1, 2, 3, 4, 5]; let stack_vec: StackVec<[u8; 5]> = StackVec::from_vec(vec); assert_eq!(&*stack_vec, &[1, 2, 3, 4, 5]); drop(stack_vec); } #[test] fn test_retain() { let mut sv: StackVec<[i32; 5]> = StackVec::from_slice(&[1, 2, 3, 3, 4]); sv.retain(|&mut i| i != 3); assert_eq!(sv.pop(), Some(4)); assert_eq!(sv.pop(), Some(2)); assert_eq!(sv.pop(), Some(1)); assert_eq!(sv.pop(), None); // Test that drop implementations are called for inline. let one = Rc::new(1); let mut sv: StackVec<[Rc; 3]> = StackVec::new(); sv.push(Rc::clone(&one)); assert_eq!(Rc::strong_count(&one), 2); sv.retain(|_| false); assert_eq!(Rc::strong_count(&one), 1); } #[test] fn test_dedup() { let mut dupes: StackVec<[i32; 5]> = StackVec::from_slice(&[1, 1, 2, 3, 3]); dupes.dedup(); assert_eq!(&*dupes, &[1, 2, 3]); let mut empty: StackVec<[i32; 5]> = StackVec::new(); empty.dedup(); assert!(empty.is_empty()); let mut all_ones: StackVec<[i32; 5]> = StackVec::from_slice(&[1, 1, 1, 1, 1]); all_ones.dedup(); assert_eq!(all_ones.len(), 1); let mut no_dupes: StackVec<[i32; 5]> = StackVec::from_slice(&[1, 2, 3, 4, 5]); no_dupes.dedup(); assert_eq!(no_dupes.len(), 5); } #[test] fn test_resize() { let mut v: StackVec<[i32; 8]> = StackVec::new(); v.push(1); v.resize(5, 0); assert_eq!(v[..], [1, 0, 0, 0, 0][..]); v.resize(2, -1); assert_eq!(v[..], [1, 0][..]); } #[cfg(feature = "std")] #[test] fn test_write() { use io::Write; let data = [1, 2, 3, 4, 5]; let mut small_vec: StackVec<[u8; 5]> = StackVec::new(); let len = small_vec.write(&data[..]).unwrap(); assert_eq!(len, 5); assert_eq!(small_vec.as_ref(), data.as_ref()); let mut small_vec: StackVec<[u8; 5]> = StackVec::new(); small_vec.write_all(&data[..]).unwrap(); assert_eq!(small_vec.as_ref(), data.as_ref()); } }