diff options
Diffstat (limited to 'vendor/smallvec')
-rw-r--r-- | vendor/smallvec/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | vendor/smallvec/Cargo.toml | 72 | ||||
-rw-r--r-- | vendor/smallvec/LICENSE-APACHE | 201 | ||||
-rw-r--r-- | vendor/smallvec/LICENSE-MIT | 25 | ||||
-rw-r--r-- | vendor/smallvec/README.md | 26 | ||||
-rw-r--r-- | vendor/smallvec/benches/bench.rs | 312 | ||||
-rw-r--r-- | vendor/smallvec/debug_metadata/README.md | 111 | ||||
-rw-r--r-- | vendor/smallvec/debug_metadata/smallvec.natvis | 35 | ||||
-rw-r--r-- | vendor/smallvec/scripts/run_miri.sh | 24 | ||||
-rw-r--r-- | vendor/smallvec/src/arbitrary.rs | 19 | ||||
-rw-r--r-- | vendor/smallvec/src/lib.rs | 2457 | ||||
-rw-r--r-- | vendor/smallvec/src/specialization.rs | 19 | ||||
-rw-r--r-- | vendor/smallvec/src/tests.rs | 1013 | ||||
-rw-r--r-- | vendor/smallvec/tests/debugger_visualizer.rs | 68 | ||||
-rw-r--r-- | vendor/smallvec/tests/macro.rs | 24 |
15 files changed, 0 insertions, 4407 deletions
diff --git a/vendor/smallvec/.cargo-checksum.json b/vendor/smallvec/.cargo-checksum.json deleted file mode 100644 index 563316c..0000000 --- a/vendor/smallvec/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"Cargo.toml":"12129d19d241f8b8041854ed140f6bdfb05ec43742d0f80779e40b1b24365c79","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b28172679e0009b655da42797c03fd163a3379d5cfa67ba1f1655e974a2a1a9","README.md":"a01127c37308457e8d396b176fb790846be0978c173be3f13260b62efcef011b","benches/bench.rs":"d82015eae942ee5cf74ace8c3c260ee2c6b5bcbeeb87254d2c72622c747a708a","debug_metadata/README.md":"4d7f1c1b2c25ce2231ef71864d06e54323867459035b53bc9e00f66a0a44f82e","debug_metadata/smallvec.natvis":"3092ddebd8fffc3486536d7f27f8c5eae3a8a093d45cd8eeb3946ea2b0c35a15","scripts/run_miri.sh":"74a9f9adc43f986e81977b03846f7dd00122a0150bd8ec3fe4842a1a787e0f07","src/arbitrary.rs":"22e55cfbf60374945b30e6d0855129eff67cd8b878cef6fa997e1f4be67b9e3d","src/lib.rs":"fbae23a885178a0a8e1372e81e85fd9d65f4416f53ab489b1bde65854396ff48","src/specialization.rs":"46433586203399251cba496d67b88d34e1be3c2b591986b77463513da1c66471","src/tests.rs":"11c951cb4da40e13de1f7058e023cd29e857216e1e3243111a63ae79e931dbc6","tests/debugger_visualizer.rs":"185456ad253957fc0c9e904ff8a1135397ac991c29fa3c60f75d8d81f7463022","tests/macro.rs":"22ad4f6f104a599fdcba19cad8834105b8656b212fb6c7573a427d447f5db14f"},"package":"4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"}
\ No newline at end of file diff --git a/vendor/smallvec/Cargo.toml b/vendor/smallvec/Cargo.toml deleted file mode 100644 index d85fba7..0000000 --- a/vendor/smallvec/Cargo.toml +++ /dev/null @@ -1,72 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies. -# -# If you are reading this file be aware that the original Cargo.toml -# will likely look very different (and much more reasonable). -# See Cargo.toml.orig for the original contents. - -[package] -edition = "2018" -name = "smallvec" -version = "1.11.2" -authors = ["The Servo Project Developers"] -description = "'Small vector' optimization: store up to a small number of items on the stack" -documentation = "https://docs.rs/smallvec/" -readme = "README.md" -keywords = [ - "small", - "vec", - "vector", - "stack", - "no_std", -] -categories = ["data-structures"] -license = "MIT OR Apache-2.0" -repository = "https://github.com/servo/rust-smallvec" - -[package.metadata.docs.rs] -all-features = true -rustdoc-args = [ - "--cfg", - "docsrs", - "--generate-link-to-definition", -] - -[[test]] -name = "debugger_visualizer" -path = "tests/debugger_visualizer.rs" -test = false -required-features = ["debugger_visualizer"] - -[dependencies.arbitrary] -version = "1" -optional = true - -[dependencies.serde] -version = "1" -optional = true -default-features = false - -[dev-dependencies.bincode] -version = "1.0.1" - -[dev-dependencies.debugger_test] -version = "0.1.0" - -[dev-dependencies.debugger_test_parser] -version = "0.1.0" - -[features] -const_generics = [] -const_new = ["const_generics"] -debugger_visualizer = [] -drain_filter = [] -drain_keep_rest = ["drain_filter"] -may_dangle = [] -specialization = [] -union = [] -write = [] diff --git a/vendor/smallvec/LICENSE-APACHE b/vendor/smallvec/LICENSE-APACHE deleted file mode 100644 index 16fe87b..0000000 --- a/vendor/smallvec/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/vendor/smallvec/LICENSE-MIT b/vendor/smallvec/LICENSE-MIT deleted file mode 100644 index 9729c12..0000000 --- a/vendor/smallvec/LICENSE-MIT +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2018 The Servo Project Developers - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/vendor/smallvec/README.md b/vendor/smallvec/README.md deleted file mode 100644 index 724637c..0000000 --- a/vendor/smallvec/README.md +++ /dev/null @@ -1,26 +0,0 @@ -rust-smallvec -============= - -[Documentation](https://docs.rs/smallvec/) - -[Release notes](https://github.com/servo/rust-smallvec/releases) - -"Small vector" optimization for Rust: store up to a small number of items on the stack - -## Example - -```rust -use smallvec::{SmallVec, smallvec}; - -// This SmallVec can hold up to 4 items on the stack: -let mut v: SmallVec<[i32; 4]> = smallvec![1, 2, 3, 4]; - -// It will automatically move its contents to the heap if -// contains more than four items: -v.push(5); - -// SmallVec points to a slice, so you can use normal slice -// indexing and other methods to access its contents: -v[0] = v[1] + v[2]; -v.sort(); -``` diff --git a/vendor/smallvec/benches/bench.rs b/vendor/smallvec/benches/bench.rs deleted file mode 100644 index b6a8b85..0000000 --- a/vendor/smallvec/benches/bench.rs +++ /dev/null @@ -1,312 +0,0 @@ -#![feature(test)] -#![allow(deprecated)] - -extern crate test; - -use self::test::Bencher; -use smallvec::{ExtendFromSlice, smallvec, SmallVec}; - -const VEC_SIZE: usize = 16; -const SPILLED_SIZE: usize = 100; - -trait Vector<T>: for<'a> From<&'a [T]> + Extend<T> + ExtendFromSlice<T> { - fn new() -> Self; - fn push(&mut self, val: T); - fn pop(&mut self) -> Option<T>; - fn remove(&mut self, p: usize) -> T; - fn insert(&mut self, n: usize, val: T); - fn from_elem(val: T, n: usize) -> Self; - fn from_elems(val: &[T]) -> Self; -} - -impl<T: Copy> Vector<T> for Vec<T> { - fn new() -> Self { - Self::with_capacity(VEC_SIZE) - } - - fn push(&mut self, val: T) { - self.push(val) - } - - fn pop(&mut self) -> Option<T> { - self.pop() - } - - fn remove(&mut self, p: usize) -> T { - self.remove(p) - } - - fn insert(&mut self, n: usize, val: T) { - self.insert(n, val) - } - - fn from_elem(val: T, n: usize) -> Self { - vec![val; n] - } - - fn from_elems(val: &[T]) -> Self { - val.to_owned() - } -} - -impl<T: Copy> Vector<T> for SmallVec<[T; VEC_SIZE]> { - fn new() -> Self { - Self::new() - } - - fn push(&mut self, val: T) { - self.push(val) - } - - fn pop(&mut self) -> Option<T> { - self.pop() - } - - fn remove(&mut self, p: usize) -> T { - self.remove(p) - } - - fn insert(&mut self, n: usize, val: T) { - self.insert(n, val) - } - - fn from_elem(val: T, n: usize) -> Self { - smallvec![val; n] - } - - fn from_elems(val: &[T]) -> Self { - SmallVec::from_slice(val) - } -} - -macro_rules! make_benches { - ($typ:ty { $($b_name:ident => $g_name:ident($($args:expr),*),)* }) => { - $( - #[bench] - fn $b_name(b: &mut Bencher) { - $g_name::<$typ>($($args,)* b) - } - )* - } -} - -make_benches! { - SmallVec<[u64; VEC_SIZE]> { - bench_push => gen_push(SPILLED_SIZE as _), - bench_push_small => gen_push(VEC_SIZE as _), - bench_insert_push => gen_insert_push(SPILLED_SIZE as _), - bench_insert_push_small => gen_insert_push(VEC_SIZE as _), - bench_insert => gen_insert(SPILLED_SIZE as _), - bench_insert_small => gen_insert(VEC_SIZE as _), - bench_remove => gen_remove(SPILLED_SIZE as _), - bench_remove_small => gen_remove(VEC_SIZE as _), - bench_extend => gen_extend(SPILLED_SIZE as _), - bench_extend_small => gen_extend(VEC_SIZE as _), - bench_from_iter => gen_from_iter(SPILLED_SIZE as _), - bench_from_iter_small => gen_from_iter(VEC_SIZE as _), - bench_from_slice => gen_from_slice(SPILLED_SIZE as _), - bench_from_slice_small => gen_from_slice(VEC_SIZE as _), - bench_extend_from_slice => gen_extend_from_slice(SPILLED_SIZE as _), - bench_extend_from_slice_small => gen_extend_from_slice(VEC_SIZE as _), - bench_macro_from_elem => gen_from_elem(SPILLED_SIZE as _), - bench_macro_from_elem_small => gen_from_elem(VEC_SIZE as _), - bench_pushpop => gen_pushpop(), - } -} - -make_benches! { - Vec<u64> { - bench_push_vec => gen_push(SPILLED_SIZE as _), - bench_push_vec_small => gen_push(VEC_SIZE as _), - bench_insert_push_vec => gen_insert_push(SPILLED_SIZE as _), - bench_insert_push_vec_small => gen_insert_push(VEC_SIZE as _), - bench_insert_vec => gen_insert(SPILLED_SIZE as _), - bench_insert_vec_small => gen_insert(VEC_SIZE as _), - bench_remove_vec => gen_remove(SPILLED_SIZE as _), - bench_remove_vec_small => gen_remove(VEC_SIZE as _), - bench_extend_vec => gen_extend(SPILLED_SIZE as _), - bench_extend_vec_small => gen_extend(VEC_SIZE as _), - bench_from_iter_vec => gen_from_iter(SPILLED_SIZE as _), - bench_from_iter_vec_small => gen_from_iter(VEC_SIZE as _), - bench_from_slice_vec => gen_from_slice(SPILLED_SIZE as _), - bench_from_slice_vec_small => gen_from_slice(VEC_SIZE as _), - bench_extend_from_slice_vec => gen_extend_from_slice(SPILLED_SIZE as _), - bench_extend_from_slice_vec_small => gen_extend_from_slice(VEC_SIZE as _), - bench_macro_from_elem_vec => gen_from_elem(SPILLED_SIZE as _), - bench_macro_from_elem_vec_small => gen_from_elem(VEC_SIZE as _), - bench_pushpop_vec => gen_pushpop(), - } -} - -fn gen_push<V: Vector<u64>>(n: u64, b: &mut Bencher) { - #[inline(never)] - fn push_noinline<V: Vector<u64>>(vec: &mut V, x: u64) { - vec.push(x); - } - - b.iter(|| { - let mut vec = V::new(); - for x in 0..n { - push_noinline(&mut vec, x); - } - vec - }); -} - -fn gen_insert_push<V: Vector<u64>>(n: u64, b: &mut Bencher) { - #[inline(never)] - fn insert_push_noinline<V: Vector<u64>>(vec: &mut V, x: u64) { - vec.insert(x as usize, x); - } - - b.iter(|| { - let mut vec = V::new(); - for x in 0..n { - insert_push_noinline(&mut vec, x); - } - vec - }); -} - -fn gen_insert<V: Vector<u64>>(n: u64, b: &mut Bencher) { - #[inline(never)] - fn insert_noinline<V: Vector<u64>>(vec: &mut V, p: usize, x: u64) { - vec.insert(p, x) - } - - b.iter(|| { - let mut vec = V::new(); - // Always insert at position 0 so that we are subject to shifts of - // many different lengths. - vec.push(0); - for x in 0..n { - insert_noinline(&mut vec, 0, x); - } - vec - }); -} - -fn gen_remove<V: Vector<u64>>(n: usize, b: &mut Bencher) { - #[inline(never)] - fn remove_noinline<V: Vector<u64>>(vec: &mut V, p: usize) -> u64 { - vec.remove(p) - } - - b.iter(|| { - let mut vec = V::from_elem(0, n as _); - - for _ in 0..n { - remove_noinline(&mut vec, 0); - } - }); -} - -fn gen_extend<V: Vector<u64>>(n: u64, b: &mut Bencher) { - b.iter(|| { - let mut vec = V::new(); - vec.extend(0..n); - vec - }); -} - -fn gen_from_iter<V: Vector<u64>>(n: u64, b: &mut Bencher) { - let v: Vec<u64> = (0..n).collect(); - b.iter(|| { - let vec = V::from(&v); - vec - }); -} - -fn gen_from_slice<V: Vector<u64>>(n: u64, b: &mut Bencher) { - let v: Vec<u64> = (0..n).collect(); - b.iter(|| { - let vec = V::from_elems(&v); - vec - }); -} - -fn gen_extend_from_slice<V: Vector<u64>>(n: u64, b: &mut Bencher) { - let v: Vec<u64> = (0..n).collect(); - b.iter(|| { - let mut vec = V::new(); - vec.extend_from_slice(&v); - vec - }); -} - -fn gen_pushpop<V: Vector<u64>>(b: &mut Bencher) { - #[inline(never)] - fn pushpop_noinline<V: Vector<u64>>(vec: &mut V, x: u64) -> Option<u64> { - vec.push(x); - vec.pop() - } - - b.iter(|| { - let mut vec = V::new(); - for x in 0..SPILLED_SIZE as _ { - pushpop_noinline(&mut vec, x); - } - vec - }); -} - -fn gen_from_elem<V: Vector<u64>>(n: usize, b: &mut Bencher) { - b.iter(|| { - let vec = V::from_elem(42, n); - vec - }); -} - -#[bench] -fn bench_insert_many(b: &mut Bencher) { - #[inline(never)] - fn insert_many_noinline<I: IntoIterator<Item = u64>>( - vec: &mut SmallVec<[u64; VEC_SIZE]>, - index: usize, - iterable: I, - ) { - vec.insert_many(index, iterable) - } - - b.iter(|| { - let mut vec = SmallVec::<[u64; VEC_SIZE]>::new(); - insert_many_noinline(&mut vec, 0, 0..SPILLED_SIZE as _); - insert_many_noinline(&mut vec, 0, 0..SPILLED_SIZE as _); - vec - }); -} - -#[bench] -fn bench_insert_from_slice(b: &mut Bencher) { - let v: Vec<u64> = (0..SPILLED_SIZE as _).collect(); - b.iter(|| { - let mut vec = SmallVec::<[u64; VEC_SIZE]>::new(); - vec.insert_from_slice(0, &v); - vec.insert_from_slice(0, &v); - vec - }); -} - -#[bench] -fn bench_macro_from_list(b: &mut Bencher) { - b.iter(|| { - let vec: SmallVec<[u64; 16]> = smallvec![ - 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 - }); -} - -#[bench] -fn bench_macro_from_list_vec(b: &mut Bencher) { - b.iter(|| { - let vec: Vec<u64> = vec![ - 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 - }); -} diff --git a/vendor/smallvec/debug_metadata/README.md b/vendor/smallvec/debug_metadata/README.md deleted file mode 100644 index 9a5596b..0000000 --- a/vendor/smallvec/debug_metadata/README.md +++ /dev/null @@ -1,111 +0,0 @@ -## Debugger Visualizers - -Many languages and debuggers enable developers to control how a type is -displayed in a debugger. These are called "debugger visualizations" or "debugger -views". - -The Windows debuggers (WinDbg\CDB) support defining custom debugger visualizations using -the `Natvis` framework. To use Natvis, developers write XML documents using the natvis -schema that describe how debugger types should be displayed with the `.natvis` extension. -(See: https://docs.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects?view=vs-2019) -The Natvis files provide patterns which match type names a description of how to display -those types. - -The Natvis schema can be found either online (See: https://code.visualstudio.com/docs/cpp/natvis#_schema) -or locally at `<VS Installation Folder>\Xml\Schemas\1033\natvis.xsd`. - -The GNU debugger (GDB) supports defining custom debugger views using Pretty Printers. -Pretty printers are written as python scripts that describe how a type should be displayed -when loaded up in GDB/LLDB. (See: https://sourceware.org/gdb/onlinedocs/gdb/Pretty-Printing.html#Pretty-Printing) -The pretty printers provide patterns, which match type names, and for matching -types, describe how to display those types. (For writing a pretty printer, see: https://sourceware.org/gdb/onlinedocs/gdb/Writing-a-Pretty_002dPrinter.html#Writing-a-Pretty_002dPrinter). - -### Embedding Visualizers - -Through the use of the currently unstable `#[debugger_visualizer]` attribute, the `smallvec` -crate can embed debugger visualizers into the crate metadata. - -Currently the two types of visualizers supported are Natvis and Pretty printers. - -For Natvis files, when linking an executable with a crate that includes Natvis files, -the MSVC linker will embed the contents of all Natvis files into the generated `PDB`. - -For pretty printers, the compiler will encode the contents of the pretty printer -in the `.debug_gdb_scripts` section of the `ELF` generated. - -### Testing Visualizers - -The `smallvec` crate supports testing debugger visualizers defined for this crate. The entry point for -these tests are `tests/debugger_visualizer.rs`. These tests are defined using the `debugger_test` and -`debugger_test_parser` crates. The `debugger_test` crate is a proc macro crate which defines a -single proc macro attribute, `#[debugger_test]`. For more detailed information about this crate, -see https://crates.io/crates/debugger_test. The CI pipeline for the `smallvec` crate has been updated -to run the debugger visualizer tests to ensure debugger visualizers do not become broken/stale. - -The `#[debugger_test]` proc macro attribute may only be used on test functions and will run the -function under the debugger specified by the `debugger` meta item. - -This proc macro attribute has 3 required values: - -1. The first required meta item, `debugger`, takes a string value which specifies the debugger to launch. -2. The second required meta item, `commands`, takes a string of new line (`\n`) separated list of debugger -commands to run. -3. The third required meta item, `expected_statements`, takes a string of new line (`\n`) separated list of -statements that must exist in the debugger output. Pattern matching through regular expressions is also -supported by using the `pattern:` prefix for each expected statement. - -#### Example: - -```rust -#[debugger_test( - debugger = "cdb", - commands = "command1\ncommand2\ncommand3", - expected_statements = "statement1\nstatement2\nstatement3")] -fn test() { - -} -``` - -Using a multiline string is also supported, with a single debugger command/expected statement per line: - -```rust -#[debugger_test( - debugger = "cdb", - commands = " -command1 -command2 -command3", - expected_statements = " -statement1 -pattern:statement[0-9]+ -statement3")] -fn test() { - -} -``` - -In the example above, the second expected statement uses pattern matching through a regular expression -by using the `pattern:` prefix. - -#### Testing Locally - -Currently, only Natvis visualizations have been defined for the `smallvec` crate via `debug_metadata/smallvec.natvis`, -which means the `tests/debugger_visualizer.rs` tests need to be run on Windows using the `*-pc-windows-msvc` targets. -To run these tests locally, first ensure the debugging tools for Windows are installed or install them following -the steps listed here, [Debugging Tools for Windows](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/). -Once the debugging tools have been installed, the tests can be run in the same manner as they are in the CI -pipeline. - -#### Note - -When running the debugger visualizer tests, `tests/debugger_visualizer.rs`, they need to be run consecutively -and not in parallel. This can be achieved by passing the flag `--test-threads=1` to rustc. This is due to -how the debugger tests are run. Each test marked with the `#[debugger_test]` attribute launches a debugger -and attaches it to the current test process. If tests are running in parallel, the test will try to attach -a debugger to the current process which may already have a debugger attached causing the test to fail. - -For example: - -``` -cargo test --test debugger_visualizer --features debugger_visualizer -- --test-threads=1 -``` diff --git a/vendor/smallvec/debug_metadata/smallvec.natvis b/vendor/smallvec/debug_metadata/smallvec.natvis deleted file mode 100644 index 8731860..0000000 --- a/vendor/smallvec/debug_metadata/smallvec.natvis +++ /dev/null @@ -1,35 +0,0 @@ -<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010"> - <Type Name="smallvec::SmallVec<array$<*,*>>" Priority="Medium"> - <Intrinsic Name="is_inline" Expression="$T2 >= capacity" /> - <Intrinsic Name="len" Expression="is_inline() ? capacity : data.variant1.value.len" /> - <Intrinsic Name="data_ptr" Expression="is_inline() ? data.variant0.value.__0.value.value : data.variant1.value.ptr.pointer" /> - - <DisplayString>{{ len={len()} is_inline={is_inline()} }}</DisplayString> - <Expand> - <Item Name="[capacity]">is_inline() ? $T2 : capacity</Item> - <Item Name="[len]">len()</Item> - <Item Name="[data_ptr]">data_ptr()</Item> - - <ArrayItems> - <Size>len()</Size> - <ValuePointer>data_ptr()</ValuePointer> - </ArrayItems> - </Expand> - </Type> - - <Type Name="smallvec::SmallVec<array$<*,*>>" Priority="MediumLow"> - <Intrinsic Name="is_inline" Expression="$T2 >= capacity" /> - <Intrinsic Name="len" Expression="is_inline() ? capacity : data.heap.__1" /> - <Intrinsic Name="data_ptr" Expression="is_inline() ? data.inline.value.value.value : data.heap.__0.pointer" /> - <DisplayString>{{ len={len()} is_inline={is_inline()} }}</DisplayString> - <Expand> - <Item Name="[capacity]">is_inline() ? $T2 : capacity</Item> - <Item Name="[len]">len()</Item> - - <ArrayItems> - <Size>len()</Size> - <ValuePointer>data_ptr()</ValuePointer> - </ArrayItems> - </Expand> - </Type> -</AutoVisualizer>
\ No newline at end of file diff --git a/vendor/smallvec/scripts/run_miri.sh b/vendor/smallvec/scripts/run_miri.sh deleted file mode 100644 index 010ceb0..0000000 --- a/vendor/smallvec/scripts/run_miri.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/bash - -set -ex - -# Clean out our target dir, which may have artifacts compiled by a version of -# rust different from the one we're about to download. -cargo clean - -# Install and run the latest version of nightly where miri built successfully. -# Taken from: https://github.com/rust-lang/miri#running-miri-on-ci - -MIRI_NIGHTLY=nightly-$(curl -s https://rust-lang.github.io/rustup-components-history/x86_64-unknown-linux-gnu/miri) -echo "Installing latest nightly with Miri: $MIRI_NIGHTLY" -rustup override unset -rustup default "$MIRI_NIGHTLY" - -rustup component add miri -cargo miri setup - -cargo miri test --verbose -cargo miri test --verbose --features union -cargo miri test --verbose --all-features - -rustup override set nightly diff --git a/vendor/smallvec/src/arbitrary.rs b/vendor/smallvec/src/arbitrary.rs deleted file mode 100644 index cbdfcb0..0000000 --- a/vendor/smallvec/src/arbitrary.rs +++ /dev/null @@ -1,19 +0,0 @@ -use crate::{Array, SmallVec}; -use arbitrary::{Arbitrary, Unstructured}; - -impl<'a, A: Array> Arbitrary<'a> for SmallVec<A> -where - <A as Array>::Item: Arbitrary<'a>, -{ - fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> { - u.arbitrary_iter()?.collect() - } - - fn arbitrary_take_rest(u: Unstructured<'a>) -> arbitrary::Result<Self> { - u.arbitrary_take_rest_iter()?.collect() - } - - fn size_hint(depth: usize) -> (usize, Option<usize>) { - arbitrary::size_hint::and(<usize as Arbitrary>::size_hint(depth), (0, None)) - } -} diff --git a/vendor/smallvec/src/lib.rs b/vendor/smallvec/src/lib.rs deleted file mode 100644 index f9a6c8a..0000000 --- a/vendor/smallvec/src/lib.rs +++ /dev/null @@ -1,2457 +0,0 @@ -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Small vectors in various sizes. These store a certain number of elements inline, and fall back -//! to the heap for larger allocations. This can be a useful optimization for improving cache -//! locality and reducing allocator traffic for workloads that fit within the inline buffer. -//! -//! ## `no_std` support -//! -//! By default, `smallvec` does not depend on `std`. However, the optional -//! `write` feature implements the `std::io::Write` trait for vectors of `u8`. -//! When this feature is enabled, `smallvec` depends on `std`. -//! -//! ## Optional features -//! -//! ### `serde` -//! -//! When this optional dependency is enabled, `SmallVec` implements the `serde::Serialize` and -//! `serde::Deserialize` traits. -//! -//! ### `write` -//! -//! When this feature is enabled, `SmallVec<[u8; _]>` implements the `std::io::Write` trait. -//! This feature is not compatible with `#![no_std]` programs. -//! -//! ### `union` -//! -//! **This feature requires Rust 1.49.** -//! -//! When the `union` feature is enabled `smallvec` will track its state (inline or spilled) -//! without the use of an enum tag, reducing the size of the `smallvec` by one machine word. -//! This means that there is potentially no space overhead compared to `Vec`. -//! Note that `smallvec` can still be larger than `Vec` if the inline buffer is larger than two -//! machine words. -//! -//! To use this feature add `features = ["union"]` in the `smallvec` section of Cargo.toml. -//! Note that this feature requires Rust 1.49. -//! -//! Tracking issue: [rust-lang/rust#55149](https://github.com/rust-lang/rust/issues/55149) -//! -//! ### `const_generics` -//! -//! **This feature requires Rust 1.51.** -//! -//! When this feature is enabled, `SmallVec` works with any arrays of any size, not just a fixed -//! list of sizes. -//! -//! ### `const_new` -//! -//! **This feature requires Rust 1.51.** -//! -//! This feature exposes the functions [`SmallVec::new_const`], [`SmallVec::from_const`], and [`smallvec_inline`] which enables the `SmallVec` to be initialized from a const context. -//! For details, see the -//! [Rust Reference](https://doc.rust-lang.org/reference/const_eval.html#const-functions). -//! -//! ### `drain_filter` -//! -//! **This feature is unstable.** It may change to match the unstable `drain_filter` method in libstd. -//! -//! Enables the `drain_filter` method, which produces an iterator that calls a user-provided -//! closure to determine which elements of the vector to remove and yield from the iterator. -//! -//! ### `drain_keep_rest` -//! -//! **This feature is unstable.** It may change to match the unstable `drain_keep_rest` method in libstd. -//! -//! Enables the `DrainFilter::keep_rest` method. -//! -//! ### `specialization` -//! -//! **This feature is unstable and requires a nightly build of the Rust toolchain.** -//! -//! When this feature is enabled, `SmallVec::from(slice)` has improved performance for slices -//! of `Copy` types. (Without this feature, you can use `SmallVec::from_slice` to get optimal -//! performance for `Copy` types.) -//! -//! Tracking issue: [rust-lang/rust#31844](https://github.com/rust-lang/rust/issues/31844) -//! -//! ### `may_dangle` -//! -//! **This feature is unstable and requires a nightly build of the Rust toolchain.** -//! -//! This feature makes the Rust compiler less strict about use of vectors that contain borrowed -//! references. For details, see the -//! [Rustonomicon](https://doc.rust-lang.org/1.42.0/nomicon/dropck.html#an-escape-hatch). -//! -//! Tracking issue: [rust-lang/rust#34761](https://github.com/rust-lang/rust/issues/34761) - -#![no_std] -#![cfg_attr(docsrs, feature(doc_cfg))] -#![cfg_attr(feature = "specialization", allow(incomplete_features))] -#![cfg_attr(feature = "specialization", feature(specialization))] -#![cfg_attr(feature = "may_dangle", feature(dropck_eyepatch))] -#![cfg_attr( - feature = "debugger_visualizer", - feature(debugger_visualizer), - debugger_visualizer(natvis_file = "../debug_metadata/smallvec.natvis") -)] -#![deny(missing_docs)] - -#[doc(hidden)] -pub extern crate alloc; - -#[cfg(any(test, feature = "write"))] -extern crate std; - -#[cfg(test)] -mod tests; - -#[allow(deprecated)] -use alloc::alloc::{Layout, LayoutErr}; -use alloc::boxed::Box; -use alloc::{vec, vec::Vec}; -use core::borrow::{Borrow, BorrowMut}; -use core::cmp; -use core::fmt; -use core::hash::{Hash, Hasher}; -use core::hint::unreachable_unchecked; -use core::iter::{repeat, FromIterator, FusedIterator, IntoIterator}; -use core::mem; -use core::mem::MaybeUninit; -use core::ops::{self, Range, RangeBounds}; -use core::ptr::{self, NonNull}; -use core::slice::{self, SliceIndex}; - -#[cfg(feature = "serde")] -use serde::{ - de::{Deserialize, Deserializer, SeqAccess, Visitor}, - ser::{Serialize, SerializeSeq, Serializer}, -}; - -#[cfg(feature = "serde")] -use core::marker::PhantomData; - -#[cfg(feature = "write")] -use std::io; - -#[cfg(feature = "drain_keep_rest")] -use core::mem::ManuallyDrop; - -/// Creates a [`SmallVec`] containing the arguments. -/// -/// `smallvec!` allows `SmallVec`s to be defined with the same syntax as array expressions. -/// There are two forms of this macro: -/// -/// - Create a [`SmallVec`] containing a given list of elements: -/// -/// ``` -/// # use smallvec::{smallvec, SmallVec}; -/// # fn main() { -/// let v: SmallVec<[_; 128]> = smallvec![1, 2, 3]; -/// assert_eq!(v[0], 1); -/// assert_eq!(v[1], 2); -/// assert_eq!(v[2], 3); -/// # } -/// ``` -/// -/// - Create a [`SmallVec`] from a given element and size: -/// -/// ``` -/// # use smallvec::{smallvec, SmallVec}; -/// # fn main() { -/// let v: SmallVec<[_; 0x8000]> = smallvec![1; 3]; -/// assert_eq!(v, SmallVec::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, `smallvec![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! smallvec { - // count helper: transform any expression into 1 - (@one $x:expr) => (1usize); - ($elem:expr; $n:expr) => ({ - $crate::SmallVec::from_elem($elem, $n) - }); - ($($x:expr),*$(,)*) => ({ - let count = 0usize $(+ $crate::smallvec!(@one $x))*; - #[allow(unused_mut)] - let mut vec = $crate::SmallVec::new(); - if count <= vec.inline_size() { - $(vec.push($x);)* - vec - } else { - $crate::SmallVec::from_vec($crate::alloc::vec![$($x,)*]) - } - }); -} - -/// Creates an inline [`SmallVec`] containing the arguments. This macro is enabled by the feature `const_new`. -/// -/// `smallvec_inline!` allows `SmallVec`s to be defined with the same syntax as array expressions in `const` contexts. -/// The inline storage `A` will always be an array of the size specified by the arguments. -/// There are two forms of this macro: -/// -/// - Create a [`SmallVec`] containing a given list of elements: -/// -/// ``` -/// # use smallvec::{smallvec_inline, SmallVec}; -/// # fn main() { -/// const V: SmallVec<[i32; 3]> = smallvec_inline![1, 2, 3]; -/// assert_eq!(V[0], 1); -/// assert_eq!(V[1], 2); -/// assert_eq!(V[2], 3); -/// # } -/// ``` -/// -/// - Create a [`SmallVec`] from a given element and size: -/// -/// ``` -/// # use smallvec::{smallvec_inline, SmallVec}; -/// # fn main() { -/// const V: SmallVec<[i32; 3]> = smallvec_inline![1; 3]; -/// assert_eq!(V, SmallVec::from_buf([1, 1, 1])); -/// # } -/// ``` -/// -/// Note that the behavior mimics that of array expressions, in contrast to [`smallvec`]. -#[cfg(feature = "const_new")] -#[cfg_attr(docsrs, doc(cfg(feature = "const_new")))] -#[macro_export] -macro_rules! smallvec_inline { - // count helper: transform any expression into 1 - (@one $x:expr) => (1usize); - ($elem:expr; $n:expr) => ({ - $crate::SmallVec::<[_; $n]>::from_const([$elem; $n]) - }); - ($($x:expr),+ $(,)?) => ({ - const N: usize = 0usize $(+ $crate::smallvec_inline!(@one $x))*; - $crate::SmallVec::<[_; N]>::from_const([$($x,)*]) - }); -} - -/// `panic!()` in debug builds, optimization hint in release. -#[cfg(not(feature = "union"))] -macro_rules! debug_unreachable { - () => { - debug_unreachable!("entered unreachable code") - }; - ($e:expr) => { - if cfg!(debug_assertions) { - panic!($e); - } else { - unreachable_unchecked(); - } - }; -} - -/// Trait to be implemented by a collection that can be extended from a slice -/// -/// ## Example -/// -/// ```rust -/// use smallvec::{ExtendFromSlice, SmallVec}; -/// -/// fn initialize<V: ExtendFromSlice<u8>>(v: &mut V) { -/// v.extend_from_slice(b"Test!"); -/// } -/// -/// let mut vec = Vec::new(); -/// initialize(&mut vec); -/// assert_eq!(&vec, b"Test!"); -/// -/// let mut small_vec = SmallVec::<[u8; 8]>::new(); -/// initialize(&mut small_vec); -/// assert_eq!(&small_vec as &[_], b"Test!"); -/// ``` -#[doc(hidden)] -#[deprecated] -pub trait ExtendFromSlice<T> { - /// Extends a collection from a slice of its element type - fn extend_from_slice(&mut self, other: &[T]); -} - -#[allow(deprecated)] -impl<T: Clone> ExtendFromSlice<T> for Vec<T> { - fn extend_from_slice(&mut self, other: &[T]) { - Vec::extend_from_slice(self, other) - } -} - -/// Error type for APIs with fallible heap allocation -#[derive(Debug)] -pub enum CollectionAllocErr { - /// Overflow `usize::MAX` or other error during size computation - CapacityOverflow, - /// The allocator return an error - AllocErr { - /// The layout that was passed to the allocator - layout: Layout, - }, -} - -impl fmt::Display for CollectionAllocErr { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Allocation error: {:?}", self) - } -} - -#[allow(deprecated)] -impl From<LayoutErr> for CollectionAllocErr { - fn from(_: LayoutErr) -> Self { - CollectionAllocErr::CapacityOverflow - } -} - -fn infallible<T>(result: Result<T, CollectionAllocErr>) -> T { - match result { - Ok(x) => x, - Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"), - Err(CollectionAllocErr::AllocErr { layout }) => alloc::alloc::handle_alloc_error(layout), - } -} - -/// FIXME: use `Layout::array` when we require a Rust version where it’s stable -/// <https://github.com/rust-lang/rust/issues/55724> -fn layout_array<T>(n: usize) -> Result<Layout, CollectionAllocErr> { - let size = mem::size_of::<T>() - .checked_mul(n) - .ok_or(CollectionAllocErr::CapacityOverflow)?; - let align = mem::align_of::<T>(); - Layout::from_size_align(size, align).map_err(|_| CollectionAllocErr::CapacityOverflow) -} - -unsafe fn deallocate<T>(ptr: NonNull<T>, capacity: usize) { - // This unwrap should succeed since the same did when allocating. - let layout = layout_array::<T>(capacity).unwrap(); - alloc::alloc::dealloc(ptr.as_ptr() as *mut u8, layout) -} - -/// An iterator that removes the items from a `SmallVec` and yields them by value. -/// -/// Returned from [`SmallVec::drain`][1]. -/// -/// [1]: struct.SmallVec.html#method.drain -pub struct Drain<'a, T: 'a + Array> { - tail_start: usize, - tail_len: usize, - iter: slice::Iter<'a, T::Item>, - vec: NonNull<SmallVec<T>>, -} - -impl<'a, T: 'a + Array> fmt::Debug for Drain<'a, T> -where - T::Item: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("Drain").field(&self.iter.as_slice()).finish() - } -} - -unsafe impl<'a, T: Sync + Array> Sync for Drain<'a, T> {} -unsafe impl<'a, T: Send + Array> Send for Drain<'a, T> {} - -impl<'a, T: 'a + Array> Iterator for Drain<'a, T> { - type Item = T::Item; - - #[inline] - fn next(&mut self) -> Option<T::Item> { - self.iter - .next() - .map(|reference| unsafe { ptr::read(reference) }) - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - self.iter.size_hint() - } -} - -impl<'a, T: 'a + Array> DoubleEndedIterator for Drain<'a, T> { - #[inline] - fn next_back(&mut self) -> Option<T::Item> { - self.iter - .next_back() - .map(|reference| unsafe { ptr::read(reference) }) - } -} - -impl<'a, T: Array> ExactSizeIterator for Drain<'a, T> { - #[inline] - fn len(&self) -> usize { - self.iter.len() - } -} - -impl<'a, T: Array> FusedIterator for Drain<'a, T> {} - -impl<'a, T: 'a + Array> Drop for Drain<'a, T> { - fn drop(&mut self) { - self.for_each(drop); - - if self.tail_len > 0 { - unsafe { - let source_vec = self.vec.as_mut(); - - // memmove back untouched tail, update to new length - let start = source_vec.len(); - let tail = self.tail_start; - if tail != start { - // as_mut_ptr creates a &mut, invalidating other pointers. - // This pattern avoids calling it with a pointer already present. - let ptr = source_vec.as_mut_ptr(); - let src = ptr.add(tail); - let dst = ptr.add(start); - ptr::copy(src, dst, self.tail_len); - } - source_vec.set_len(start + self.tail_len); - } - } - } -} - -#[cfg(feature = "drain_filter")] -/// An iterator which uses a closure to determine if an element should be removed. -/// -/// Returned from [`SmallVec::drain_filter`][1]. -/// -/// [1]: struct.SmallVec.html#method.drain_filter -pub struct DrainFilter<'a, T, F> -where - F: FnMut(&mut T::Item) -> bool, - T: Array, -{ - vec: &'a mut SmallVec<T>, - /// The index of the item that will be inspected by the next call to `next`. - idx: usize, - /// The number of items that have been drained (removed) thus far. - del: usize, - /// The original length of `vec` prior to draining. - old_len: usize, - /// The filter test predicate. - pred: F, - /// A flag that indicates a panic has occurred in the filter test predicate. - /// This is used as a hint in the drop implementation to prevent consumption - /// of the remainder of the `DrainFilter`. Any unprocessed items will be - /// backshifted in the `vec`, but no further items will be dropped or - /// tested by the filter predicate. - panic_flag: bool, -} - -#[cfg(feature = "drain_filter")] -impl <T, F> fmt::Debug for DrainFilter<'_, T, F> -where - F: FnMut(&mut T::Item) -> bool, - T: Array, - T::Item: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("DrainFilter").field(&self.vec.as_slice()).finish() - } -} - -#[cfg(feature = "drain_filter")] -impl <T, F> Iterator for DrainFilter<'_, T, F> -where - F: FnMut(&mut T::Item) -> bool, - T: Array, -{ - type Item = T::Item; - - fn next(&mut self) -> Option<T::Item> - { - unsafe { - while self.idx < self.old_len { - let i = self.idx; - let v = slice::from_raw_parts_mut(self.vec.as_mut_ptr(), self.old_len); - self.panic_flag = true; - let drained = (self.pred)(&mut v[i]); - self.panic_flag = false; - // Update the index *after* the predicate is called. If the index - // is updated prior and the predicate panics, the element at this - // index would be leaked. - self.idx += 1; - if drained { - self.del += 1; - return Some(ptr::read(&v[i])); - } else if self.del > 0 { - let del = self.del; - let src: *const Self::Item = &v[i]; - let dst: *mut Self::Item = &mut v[i - del]; - ptr::copy_nonoverlapping(src, dst, 1); - } - } - None - } - } - - fn size_hint(&self) -> (usize, Option<usize>) { - (0, Some(self.old_len - self.idx)) - } -} - -#[cfg(feature = "drain_filter")] -impl <T, F> Drop for DrainFilter<'_, T, F> -where - F: FnMut(&mut T::Item) -> bool, - T: Array, -{ - fn drop(&mut self) { - struct BackshiftOnDrop<'a, 'b, T, F> - where - F: FnMut(&mut T::Item) -> bool, - T: Array - { - drain: &'b mut DrainFilter<'a, T, F>, - } - - impl<'a, 'b, T, F> Drop for BackshiftOnDrop<'a, 'b, T, F> - where - F: FnMut(&mut T::Item) -> bool, - T: Array - { - fn drop(&mut self) { - unsafe { - if self.drain.idx < self.drain.old_len && self.drain.del > 0 { - // This is a pretty messed up state, and there isn't really an - // obviously right thing to do. We don't want to keep trying - // to execute `pred`, so we just backshift all the unprocessed - // elements and tell the vec that they still exist. The backshift - // is required to prevent a double-drop of the last successfully - // drained item prior to a panic in the predicate. - let ptr = self.drain.vec.as_mut_ptr(); - let src = ptr.add(self.drain.idx); - let dst = src.sub(self.drain.del); - let tail_len = self.drain.old_len - self.drain.idx; - src.copy_to(dst, tail_len); - } - self.drain.vec.set_len(self.drain.old_len - self.drain.del); - } - } - } - - let backshift = BackshiftOnDrop { drain: self }; - - // Attempt to consume any remaining elements if the filter predicate - // has not yet panicked. We'll backshift any remaining elements - // whether we've already panicked or if the consumption here panics. - if !backshift.drain.panic_flag { - backshift.drain.for_each(drop); - } - } -} - -#[cfg(feature = "drain_keep_rest")] -impl <T, F> DrainFilter<'_, T, F> -where - F: FnMut(&mut T::Item) -> bool, - T: Array -{ - /// Keep unyielded elements in the source `Vec`. - /// - /// # Examples - /// - /// ``` - /// # use smallvec::{smallvec, SmallVec}; - /// - /// let mut vec: SmallVec<[char; 2]> = smallvec!['a', 'b', 'c']; - /// let mut drain = vec.drain_filter(|_| true); - /// - /// assert_eq!(drain.next().unwrap(), 'a'); - /// - /// // This call keeps 'b' and 'c' in the vec. - /// drain.keep_rest(); - /// - /// // If we wouldn't call `keep_rest()`, - /// // `vec` would be empty. - /// assert_eq!(vec, SmallVec::<[char; 2]>::from_slice(&['b', 'c'])); - /// ``` - pub fn keep_rest(self) - { - // At this moment layout looks like this: - // - // _____________________/-- old_len - // / \ - // [kept] [yielded] [tail] - // \_______/ ^-- idx - // \-- del - // - // Normally `Drop` impl would drop [tail] (via .for_each(drop), ie still calling `pred`) - // - // 1. Move [tail] after [kept] - // 2. Update length of the original vec to `old_len - del` - // a. In case of ZST, this is the only thing we want to do - // 3. Do *not* drop self, as everything is put in a consistent state already, there is nothing to do - let mut this = ManuallyDrop::new(self); - - unsafe { - // ZSTs have no identity, so we don't need to move them around. - let needs_move = mem::size_of::<T>() != 0; - - if needs_move && this.idx < this.old_len && this.del > 0 { - let ptr = this.vec.as_mut_ptr(); - let src = ptr.add(this.idx); - let dst = src.sub(this.del); - let tail_len = this.old_len - this.idx; - src.copy_to(dst, tail_len); - } - - let new_len = this.old_len - this.del; - this.vec.set_len(new_len); - } - } -} - -#[cfg(feature = "union")] -union SmallVecData<A: Array> { - inline: core::mem::ManuallyDrop<MaybeUninit<A>>, - heap: (NonNull<A::Item>, usize), -} - -#[cfg(all(feature = "union", feature = "const_new"))] -impl<T, const N: usize> SmallVecData<[T; N]> { - #[cfg_attr(docsrs, doc(cfg(feature = "const_new")))] - #[inline] - const fn from_const(inline: MaybeUninit<[T; N]>) -> Self { - SmallVecData { - inline: core::mem::ManuallyDrop::new(inline), - } - } -} - -#[cfg(feature = "union")] -impl<A: Array> SmallVecData<A> { - #[inline] - unsafe fn inline(&self) -> ConstNonNull<A::Item> { - ConstNonNull::new(self.inline.as_ptr() as *const A::Item).unwrap() - } - #[inline] - unsafe fn inline_mut(&mut self) -> NonNull<A::Item> { - NonNull::new(self.inline.as_mut_ptr() as *mut A::Item).unwrap() - } - #[inline] - fn from_inline(inline: MaybeUninit<A>) -> SmallVecData<A> { - SmallVecData { - inline: core::mem::ManuallyDrop::new(inline), - } - } - #[inline] - unsafe fn into_inline(self) -> MaybeUninit<A> { - core::mem::ManuallyDrop::into_inner(self.inline) - } - #[inline] - unsafe fn heap(&self) -> (ConstNonNull<A::Item>, usize) { - (ConstNonNull(self.heap.0), self.heap.1) - } - #[inline] - unsafe fn heap_mut(&mut self) -> (NonNull<A::Item>, &mut usize) { - let h = &mut self.heap; - (h.0, &mut h.1) - } - #[inline] - fn from_heap(ptr: NonNull<A::Item>, len: usize) -> SmallVecData<A> { - SmallVecData { heap: (ptr, len) } - } -} - -#[cfg(not(feature = "union"))] -enum SmallVecData<A: Array> { - Inline(MaybeUninit<A>), - // Using NonNull and NonZero here allows to reduce size of `SmallVec`. - Heap { - // Since we never allocate on heap - // unless our capacity is bigger than inline capacity - // heap capacity cannot be less than 1. - // Therefore, pointer cannot be null too. - ptr: NonNull<A::Item>, - len: usize, - }, -} - -#[cfg(all(not(feature = "union"), feature = "const_new"))] -impl<T, const N: usize> SmallVecData<[T; N]> { - #[cfg_attr(docsrs, doc(cfg(feature = "const_new")))] - #[inline] - const fn from_const(inline: MaybeUninit<[T; N]>) -> Self { - SmallVecData::Inline(inline) - } -} - -#[cfg(not(feature = "union"))] -impl<A: Array> SmallVecData<A> { - #[inline] - unsafe fn inline(&self) -> ConstNonNull<A::Item> { - match self { - SmallVecData::Inline(a) => ConstNonNull::new(a.as_ptr() as *const A::Item).unwrap(), - _ => debug_unreachable!(), - } - } - #[inline] - unsafe fn inline_mut(&mut self) -> NonNull<A::Item> { - match self { - SmallVecData::Inline(a) => NonNull::new(a.as_mut_ptr() as *mut A::Item).unwrap(), - _ => debug_unreachable!(), - } - } - #[inline] - fn from_inline(inline: MaybeUninit<A>) -> SmallVecData<A> { - SmallVecData::Inline(inline) - } - #[inline] - unsafe fn into_inline(self) -> MaybeUninit<A> { - match self { - SmallVecData::Inline(a) => a, - _ => debug_unreachable!(), - } - } - #[inline] - unsafe fn heap(&self) -> (ConstNonNull<A::Item>, usize) { - match self { - SmallVecData::Heap { ptr, len } => (ConstNonNull(*ptr), *len), - _ => debug_unreachable!(), - } - } - #[inline] - unsafe fn heap_mut(&mut self) -> (NonNull<A::Item>, &mut usize) { - match self { - SmallVecData::Heap { ptr, len } => (*ptr, len), - _ => debug_unreachable!(), - } - } - #[inline] - fn from_heap(ptr: NonNull<A::Item>, len: usize) -> SmallVecData<A> { - SmallVecData::Heap { ptr, len } - } -} - -unsafe impl<A: Array + Send> Send for SmallVecData<A> {} -unsafe impl<A: Array + Sync> Sync for SmallVecData<A> {} - -/// A `Vec`-like container that can store a small number of elements inline. -/// -/// `SmallVec` acts like a vector, but can store a limited amount of data inline within the -/// `SmallVec` struct rather than in a separate allocation. If the data exceeds this limit, the -/// `SmallVec` will "spill" its data onto the heap, allocating a new buffer to hold it. -/// -/// The amount of data that a `SmallVec` 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 `SmallVec<[u64; 8]>` can hold up to eight 64-bit integers inline. -/// -/// ## Example -/// -/// ```rust -/// use smallvec::SmallVec; -/// let mut v = SmallVec::<[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); -/// assert!(!v.spilled()); -/// -/// // Pushing another element will force the buffer to spill: -/// v.push(4); -/// assert_eq!(v.len(), 5); -/// assert!(v.spilled()); -/// ``` -pub struct SmallVec<A: Array> { - // The capacity field is used to determine which of the storage variants is active: - // If capacity <= Self::inline_capacity() then the inline variant is used and capacity holds the current length of the vector (number of elements actually in use). - // If capacity > Self::inline_capacity() then the heap variant is used and capacity holds the size of the memory allocation. - capacity: usize, - data: SmallVecData<A>, -} - -impl<A: Array> SmallVec<A> { - /// Construct an empty vector - #[inline] - pub fn new() -> SmallVec<A> { - // Try to detect invalid custom implementations of `Array`. Hopefully, - // this check should be optimized away entirely for valid ones. - assert!( - mem::size_of::<A>() == A::size() * mem::size_of::<A::Item>() - && mem::align_of::<A>() >= mem::align_of::<A::Item>() - ); - SmallVec { - capacity: 0, - data: SmallVecData::from_inline(MaybeUninit::uninit()), - } - } - - /// Construct an empty vector with enough capacity pre-allocated to store at least `n` - /// elements. - /// - /// Will create a heap allocation only if `n` is larger than the inline capacity. - /// - /// ``` - /// # use smallvec::SmallVec; - /// - /// let v: SmallVec<[u8; 3]> = SmallVec::with_capacity(100); - /// - /// assert!(v.is_empty()); - /// assert!(v.capacity() >= 100); - /// ``` - #[inline] - pub fn with_capacity(n: usize) -> Self { - let mut v = SmallVec::new(); - v.reserve_exact(n); - v - } - - /// Construct a new `SmallVec` from a `Vec<A::Item>`. - /// - /// Elements will be copied to the inline buffer if `vec.capacity() <= Self::inline_capacity()`. - /// - /// ```rust - /// use smallvec::SmallVec; - /// - /// let vec = vec![1, 2, 3, 4, 5]; - /// let small_vec: SmallVec<[_; 3]> = SmallVec::from_vec(vec); - /// - /// assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]); - /// ``` - #[inline] - pub fn from_vec(mut vec: Vec<A::Item>) -> SmallVec<A> { - if vec.capacity() <= Self::inline_capacity() { - // Cannot use Vec with smaller capacity - // because we use value of `Self::capacity` field as indicator. - unsafe { - let mut data = SmallVecData::<A>::from_inline(MaybeUninit::uninit()); - let len = vec.len(); - vec.set_len(0); - ptr::copy_nonoverlapping(vec.as_ptr(), data.inline_mut().as_ptr(), len); - - SmallVec { - capacity: len, - data, - } - } - } else { - let (ptr, cap, len) = (vec.as_mut_ptr(), vec.capacity(), vec.len()); - mem::forget(vec); - let ptr = NonNull::new(ptr) - // See docs: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.as_mut_ptr - .expect("Cannot be null by `Vec` invariant"); - - SmallVec { - capacity: cap, - data: SmallVecData::from_heap(ptr, len), - } - } - } - - /// Constructs a new `SmallVec` on the stack from an `A` without - /// copying elements. - /// - /// ```rust - /// use smallvec::SmallVec; - /// - /// let buf = [1, 2, 3, 4, 5]; - /// let small_vec: SmallVec<_> = SmallVec::from_buf(buf); - /// - /// assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]); - /// ``` - #[inline] - pub fn from_buf(buf: A) -> SmallVec<A> { - SmallVec { - capacity: A::size(), - data: SmallVecData::from_inline(MaybeUninit::new(buf)), - } - } - - /// Constructs a new `SmallVec` 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 smallvec::SmallVec; - /// - /// let buf = [1, 2, 3, 4, 5, 0, 0, 0]; - /// let small_vec: SmallVec<_> = SmallVec::from_buf_and_len(buf, 5); - /// - /// assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]); - /// ``` - #[inline] - pub fn from_buf_and_len(buf: A, len: usize) -> SmallVec<A> { - assert!(len <= A::size()); - unsafe { SmallVec::from_buf_and_len_unchecked(MaybeUninit::new(buf), len) } - } - - /// Constructs a new `SmallVec` 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 smallvec::SmallVec; - /// use std::mem::MaybeUninit; - /// - /// let buf = [1, 2, 3, 4, 5, 0, 0, 0]; - /// let small_vec: SmallVec<_> = unsafe { - /// SmallVec::from_buf_and_len_unchecked(MaybeUninit::new(buf), 5) - /// }; - /// - /// assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]); - /// ``` - #[inline] - pub unsafe fn from_buf_and_len_unchecked(buf: MaybeUninit<A>, len: usize) -> SmallVec<A> { - SmallVec { - capacity: len, - data: SmallVecData::from_inline(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. - pub unsafe fn set_len(&mut self, new_len: usize) { - let (_, len_ptr, _) = self.triple_mut(); - *len_ptr = new_len; - } - - /// The maximum number of elements this vector can hold inline - #[inline] - fn inline_capacity() -> usize { - if mem::size_of::<A::Item>() > 0 { - A::size() - } else { - // For zero-size items code like `ptr.add(offset)` always returns the same pointer. - // Therefore all items are at the same address, - // and any array size has capacity for infinitely many items. - // The capacity is limited by the bit width of the length field. - // - // `Vec` also does this: - // https://github.com/rust-lang/rust/blob/1.44.0/src/liballoc/raw_vec.rs#L186 - // - // In our case, this also ensures that a smallvec of zero-size items never spills, - // and we never try to allocate zero bytes which `std::alloc::alloc` disallows. - core::usize::MAX - } - } - - /// The maximum number of elements this vector can hold inline - #[inline] - pub fn inline_size(&self) -> usize { - Self::inline_capacity() - } - - /// The number of elements stored in the vector - #[inline] - pub fn len(&self) -> usize { - self.triple().1 - } - - /// Returns `true` if the vector is empty - #[inline] - pub fn is_empty(&self) -> bool { - self.len() == 0 - } - - /// The number of items the vector can hold without reallocating - #[inline] - pub fn capacity(&self) -> usize { - self.triple().2 - } - - /// Returns a tuple with (data ptr, len, capacity) - /// Useful to get all `SmallVec` properties with a single check of the current storage variant. - #[inline] - fn triple(&self) -> (ConstNonNull<A::Item>, usize, usize) { - unsafe { - if self.spilled() { - let (ptr, len) = self.data.heap(); - (ptr, len, self.capacity) - } else { - (self.data.inline(), self.capacity, Self::inline_capacity()) - } - } - } - - /// Returns a tuple with (data ptr, len ptr, capacity) - #[inline] - fn triple_mut(&mut self) -> (NonNull<A::Item>, &mut usize, usize) { - unsafe { - if self.spilled() { - let (ptr, len_ptr) = self.data.heap_mut(); - (ptr, len_ptr, self.capacity) - } else { - ( - self.data.inline_mut(), - &mut self.capacity, - Self::inline_capacity(), - ) - } - } - } - - /// Returns `true` if the data has spilled into a separate heap-allocated buffer. - #[inline] - pub fn spilled(&self) -> bool { - self.capacity > Self::inline_capacity() - } - - /// Creates a draining iterator that removes the specified range in the vector - /// and yields the removed items. - /// - /// Note 1: The element range is removed even if the iterator is only - /// partially consumed or not consumed at all. - /// - /// Note 2: It is unspecified how many elements are removed from the vector - /// if the `Drain` value is leaked. - /// - /// # Panics - /// - /// Panics if the starting point is greater than the end point or if - /// the end point is greater than the length of the vector. - pub fn drain<R>(&mut self, range: R) -> Drain<'_, A> - where - R: RangeBounds<usize>, - { - use core::ops::Bound::*; - - let len = self.len(); - let start = match range.start_bound() { - Included(&n) => n, - Excluded(&n) => n.checked_add(1).expect("Range start out of bounds"), - Unbounded => 0, - }; - let end = match range.end_bound() { - Included(&n) => n.checked_add(1).expect("Range end out of bounds"), - Excluded(&n) => n, - Unbounded => len, - }; - - assert!(start <= end); - assert!(end <= len); - - unsafe { - self.set_len(start); - - let range_slice = slice::from_raw_parts(self.as_ptr().add(start), end - start); - - Drain { - tail_start: end, - tail_len: len - end, - iter: range_slice.iter(), - // Since self is a &mut, passing it to a function would invalidate the slice iterator. - vec: NonNull::new_unchecked(self as *mut _), - } - } - } - - #[cfg(feature = "drain_filter")] - /// Creates an iterator which uses a closure to determine if an element should be removed. - /// - /// If the closure returns true, the element is removed and yielded. If the closure returns - /// false, the element will remain in the vector and will not be yielded by the iterator. - /// - /// Using this method is equivalent to the following code: - /// ``` - /// # use smallvec::SmallVec; - /// # let some_predicate = |x: &mut i32| { *x == 2 || *x == 3 || *x == 6 }; - /// # let mut vec: SmallVec<[i32; 8]> = SmallVec::from_slice(&[1i32, 2, 3, 4, 5, 6]); - /// let mut i = 0; - /// while i < vec.len() { - /// if some_predicate(&mut vec[i]) { - /// let val = vec.remove(i); - /// // your code here - /// } else { - /// i += 1; - /// } - /// } - /// - /// # assert_eq!(vec, SmallVec::<[i32; 8]>::from_slice(&[1i32, 4, 5])); - /// ``` - /// /// - /// But `drain_filter` is easier to use. `drain_filter` is also more efficient, - /// because it can backshift the elements of the array in bulk. - /// - /// Note that `drain_filter` also lets you mutate every element in the filter closure, - /// regardless of whether you choose to keep or remove it. - /// - /// # Examples - /// - /// Splitting an array into evens and odds, reusing the original allocation: - /// - /// ``` - /// # use smallvec::SmallVec; - /// let mut numbers: SmallVec<[i32; 16]> = SmallVec::from_slice(&[1i32, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15]); - /// - /// let evens = numbers.drain_filter(|x| *x % 2 == 0).collect::<SmallVec<[i32; 16]>>(); - /// let odds = numbers; - /// - /// assert_eq!(evens, SmallVec::<[i32; 16]>::from_slice(&[2i32, 4, 6, 8, 14])); - /// assert_eq!(odds, SmallVec::<[i32; 16]>::from_slice(&[1i32, 3, 5, 9, 11, 13, 15])); - /// ``` - pub fn drain_filter<F>(&mut self, filter: F) -> DrainFilter<'_, A, F,> - where - F: FnMut(&mut A::Item) -> bool, - { - let old_len = self.len(); - - // Guard against us getting leaked (leak amplification) - unsafe { - self.set_len(0); - } - - DrainFilter { vec: self, idx: 0, del: 0, old_len, pred: filter, panic_flag: false } - } - - /// Append an item to the vector. - #[inline] - pub fn push(&mut self, value: A::Item) { - unsafe { - let (mut ptr, mut len, cap) = self.triple_mut(); - if *len == cap { - self.reserve_one_unchecked(); - let (heap_ptr, heap_len) = self.data.heap_mut(); - ptr = heap_ptr; - len = heap_len; - } - ptr::write(ptr.as_ptr().add(*len), value); - *len += 1; - } - } - - /// Remove an item from the end of the vector and return it, or None if empty. - #[inline] - pub fn pop(&mut self) -> Option<A::Item> { - unsafe { - let (ptr, len_ptr, _) = self.triple_mut(); - let ptr: *const _ = ptr.as_ptr(); - if *len_ptr == 0 { - return None; - } - let last_index = *len_ptr - 1; - *len_ptr = last_index; - Some(ptr::read(ptr.add(last_index))) - } - } - - /// Moves all the elements of `other` into `self`, leaving `other` empty. - /// - /// # Example - /// - /// ``` - /// # use smallvec::{SmallVec, smallvec}; - /// let mut v0: SmallVec<[u8; 16]> = smallvec![1, 2, 3]; - /// let mut v1: SmallVec<[u8; 32]> = smallvec![4, 5, 6]; - /// v0.append(&mut v1); - /// assert_eq!(*v0, [1, 2, 3, 4, 5, 6]); - /// assert_eq!(*v1, []); - /// ``` - pub fn append<B>(&mut self, other: &mut SmallVec<B>) - where - B: Array<Item = A::Item>, - { - self.extend(other.drain(..)) - } - - /// Re-allocate to set the capacity to `max(new_cap, inline_size())`. - /// - /// Panics if `new_cap` is less than the vector's length - /// or if the capacity computation overflows `usize`. - pub fn grow(&mut self, new_cap: usize) { - infallible(self.try_grow(new_cap)) - } - - /// Re-allocate to set the capacity to `max(new_cap, inline_size())`. - /// - /// Panics if `new_cap` is less than the vector's length - pub fn try_grow(&mut self, new_cap: usize) -> Result<(), CollectionAllocErr> { - unsafe { - let unspilled = !self.spilled(); - let (ptr, &mut len, cap) = self.triple_mut(); - assert!(new_cap >= len); - if new_cap <= Self::inline_capacity() { - if unspilled { - return Ok(()); - } - self.data = SmallVecData::from_inline(MaybeUninit::uninit()); - ptr::copy_nonoverlapping(ptr.as_ptr(), self.data.inline_mut().as_ptr(), len); - self.capacity = len; - deallocate(ptr, cap); - } else if new_cap != cap { - let layout = layout_array::<A::Item>(new_cap)?; - debug_assert!(layout.size() > 0); - let new_alloc; - if unspilled { - new_alloc = NonNull::new(alloc::alloc::alloc(layout)) - .ok_or(CollectionAllocErr::AllocErr { layout })? - .cast(); - ptr::copy_nonoverlapping(ptr.as_ptr(), new_alloc.as_ptr(), len); - } else { - // This should never fail since the same succeeded - // when previously allocating `ptr`. - let old_layout = layout_array::<A::Item>(cap)?; - - let new_ptr = - alloc::alloc::realloc(ptr.as_ptr() as *mut u8, old_layout, layout.size()); - new_alloc = NonNull::new(new_ptr) - .ok_or(CollectionAllocErr::AllocErr { layout })? - .cast(); - } - self.data = SmallVecData::from_heap(new_alloc, len); - self.capacity = new_cap; - } - Ok(()) - } - } - - /// Reserve capacity for `additional` more elements to be inserted. - /// - /// May reserve more space to avoid frequent reallocations. - /// - /// Panics if the capacity computation overflows `usize`. - #[inline] - pub fn reserve(&mut self, additional: usize) { - infallible(self.try_reserve(additional)) - } - - /// Internal method used to grow in push() and insert(), where we know already we have to grow. - #[cold] - fn reserve_one_unchecked(&mut self) { - debug_assert_eq!(self.len(), self.capacity()); - let new_cap = self.len() - .checked_add(1) - .and_then(usize::checked_next_power_of_two) - .expect("capacity overflow"); - infallible(self.try_grow(new_cap)) - } - - /// Reserve capacity for `additional` more elements to be inserted. - /// - /// May reserve more space to avoid frequent reallocations. - pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { - // prefer triple_mut() even if triple() would work so that the optimizer removes duplicated - // calls to it from callers. - let (_, &mut len, cap) = self.triple_mut(); - if cap - len >= additional { - return Ok(()); - } - let new_cap = len - .checked_add(additional) - .and_then(usize::checked_next_power_of_two) - .ok_or(CollectionAllocErr::CapacityOverflow)?; - self.try_grow(new_cap) - } - - /// Reserve the minimum capacity for `additional` more elements to be inserted. - /// - /// Panics if the new capacity overflows `usize`. - pub fn reserve_exact(&mut self, additional: usize) { - infallible(self.try_reserve_exact(additional)) - } - - /// Reserve the minimum capacity for `additional` more elements to be inserted. - pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), CollectionAllocErr> { - let (_, &mut len, cap) = self.triple_mut(); - if cap - len >= additional { - return Ok(()); - } - let new_cap = len - .checked_add(additional) - .ok_or(CollectionAllocErr::CapacityOverflow)?; - self.try_grow(new_cap) - } - - /// Shrink the capacity of the vector as much as possible. - /// - /// When possible, this will move data from an external heap buffer to the vector's inline - /// storage. - pub fn shrink_to_fit(&mut self) { - if !self.spilled() { - return; - } - let len = self.len(); - if self.inline_size() >= len { - unsafe { - let (ptr, len) = self.data.heap(); - self.data = SmallVecData::from_inline(MaybeUninit::uninit()); - ptr::copy_nonoverlapping(ptr.as_ptr(), self.data.inline_mut().as_ptr(), len); - deallocate(ptr.0, self.capacity); - self.capacity = len; - } - } else if self.capacity() > len { - self.grow(len); - } - } - - /// 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. - /// - /// This does not re-allocate. If you want the vector's capacity to shrink, call - /// `shrink_to_fit` after truncating. - pub fn truncate(&mut self, len: usize) { - unsafe { - let (ptr, len_ptr, _) = self.triple_mut(); - let ptr = ptr.as_ptr(); - while len < *len_ptr { - let last_index = *len_ptr - 1; - *len_ptr = last_index; - ptr::drop_in_place(ptr.add(last_index)); - } - } - } - - /// Extracts a slice containing the entire vector. - /// - /// Equivalent to `&s[..]`. - pub fn as_slice(&self) -> &[A::Item] { - self - } - - /// Extracts a mutable slice of the entire vector. - /// - /// Equivalent to `&mut s[..]`. - 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); - self.pop() - .unwrap_or_else(|| unsafe { unreachable_unchecked() }) - } - - /// 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 { - unsafe { - let (ptr, len_ptr, _) = self.triple_mut(); - let len = *len_ptr; - assert!(index < len); - *len_ptr = len - 1; - let ptr = ptr.as_ptr().add(index); - let item = ptr::read(ptr); - ptr::copy(ptr.add(1), ptr, len - index - 1); - item - } - } - - /// Insert an element at position `index`, shifting all elements after it to the right. - /// - /// Panics if `index > len`. - pub fn insert(&mut self, index: usize, element: A::Item) { - unsafe { - let (mut ptr, mut len_ptr, cap) = self.triple_mut(); - if *len_ptr == cap { - self.reserve_one_unchecked(); - let (heap_ptr, heap_len_ptr) = self.data.heap_mut(); - ptr = heap_ptr; - len_ptr = heap_len_ptr; - } - let mut ptr = ptr.as_ptr(); - let len = *len_ptr; - ptr = ptr.add(index); - if index < len { - ptr::copy(ptr, ptr.add(1), len - index); - } else if index == len { - // No elements need shifting. - } else { - panic!("index exceeds length"); - } - *len_ptr = len + 1; - ptr::write(ptr, element); - } - } - - /// Insert multiple elements at position `index`, shifting all following elements toward the - /// back. - pub fn insert_many<I: IntoIterator<Item = A::Item>>(&mut self, index: usize, iterable: I) { - let mut iter = iterable.into_iter(); - if index == self.len() { - return self.extend(iter); - } - - let (lower_size_bound, _) = iter.size_hint(); - assert!(lower_size_bound <= core::isize::MAX as usize); // Ensure offset is indexable - assert!(index + lower_size_bound >= index); // Protect against overflow - - let mut num_added = 0; - let old_len = self.len(); - assert!(index <= old_len); - - unsafe { - // Reserve space for `lower_size_bound` elements. - self.reserve(lower_size_bound); - let start = self.as_mut_ptr(); - let ptr = start.add(index); - - // Move the trailing elements. - ptr::copy(ptr, ptr.add(lower_size_bound), old_len - index); - - // In case the iterator panics, don't double-drop the items we just copied above. - self.set_len(0); - let mut guard = DropOnPanic { - start, - skip: index..(index + lower_size_bound), - len: old_len + lower_size_bound, - }; - - // The set_len above invalidates the previous pointers, so we must re-create them. - let start = self.as_mut_ptr(); - let ptr = start.add(index); - - while num_added < lower_size_bound { - let element = match iter.next() { - Some(x) => x, - None => break, - }; - let cur = ptr.add(num_added); - ptr::write(cur, element); - guard.skip.start += 1; - num_added += 1; - } - - if num_added < lower_size_bound { - // Iterator provided fewer elements than the hint. Move the tail backward. - ptr::copy( - ptr.add(lower_size_bound), - ptr.add(num_added), - old_len - index, - ); - } - // There are no more duplicate or uninitialized slots, so the guard is not needed. - self.set_len(old_len + num_added); - mem::forget(guard); - } - - // Insert any remaining elements one-by-one. - for element in iter { - self.insert(index + num_added, element); - num_added += 1; - } - - struct DropOnPanic<T> { - start: *mut T, - skip: Range<usize>, // Space we copied-out-of, but haven't written-to yet. - len: usize, - } - - impl<T> Drop for DropOnPanic<T> { - fn drop(&mut self) { - for i in 0..self.len { - if !self.skip.contains(&i) { - unsafe { - ptr::drop_in_place(self.start.add(i)); - } - } - } - } - } - } - - /// Convert a `SmallVec` to a `Vec`, without reallocating if the `SmallVec` has already spilled onto - /// the heap. - pub fn into_vec(mut self) -> Vec<A::Item> { - if self.spilled() { - unsafe { - let (ptr, &mut len) = self.data.heap_mut(); - let v = Vec::from_raw_parts(ptr.as_ptr(), len, self.capacity); - mem::forget(self); - v - } - } else { - self.into_iter().collect() - } - } - - /// Converts a `SmallVec` into a `Box<[T]>` without reallocating if the `SmallVec` has already spilled - /// onto the heap. - /// - /// Note that this will drop any excess capacity. - pub fn into_boxed_slice(self) -> Box<[A::Item]> { - self.into_vec().into_boxed_slice() - } - - /// Convert the `SmallVec` into an `A` if possible. Otherwise return `Err(Self)`. - /// - /// This method returns `Err(Self)` if the `SmallVec` is too short (and the `A` contains uninitialized elements), - /// or if the `SmallVec` is too long (and all the elements were spilled to the heap). - pub fn into_inner(self) -> Result<A, Self> { - if self.spilled() || self.len() != A::size() { - // Note: A::size, not Self::inline_capacity - Err(self) - } else { - unsafe { - let data = ptr::read(&self.data); - mem::forget(self); - Ok(data.into_inline().assume_init()) - } - } - } - - /// 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<F: FnMut(&mut A::Item) -> 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); - } - - /// Retains only the elements specified by the predicate. - /// - /// This method is identical in behaviour to [`retain`]; it is included only - /// to maintain api-compatability with `std::Vec`, where the methods are - /// separate for historical reasons. - pub fn retain_mut<F: FnMut(&mut A::Item) -> bool>(&mut self, f: F) { - self.retain(f) - } - - /// Removes consecutive duplicate elements. - pub fn dedup(&mut self) - where - A::Item: PartialEq<A::Item>, - { - self.dedup_by(|a, b| a == b); - } - - /// Removes consecutive duplicate elements using the given equality relation. - pub fn dedup_by<F>(&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.add(r); - let p_wm1 = ptr.add(w - 1); - if !same_bucket(&mut *p_r, &mut *p_wm1) { - if r != w { - let p_w = p_wm1.add(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<F, K>(&mut self, mut key: F) - where - F: FnMut(&mut A::Item) -> K, - K: PartialEq<K>, - { - self.dedup_by(|a, b| key(a) == key(b)); - } - - /// Resizes the `SmallVec` in-place so that `len` is equal to `new_len`. - /// - /// If `new_len` is greater than `len`, the `SmallVec` is extended by the difference, with each - /// additional slot filled with the result of calling the closure `f`. The return values from `f` - /// will end up in the `SmallVec` in the order they have been generated. - /// - /// If `new_len` is less than `len`, the `SmallVec` is simply truncated. - /// - /// This method uses a closure to create new values on every push. If you'd rather `Clone` a given - /// value, use `resize`. If you want to use the `Default` trait to generate values, you can pass - /// `Default::default()` as the second argument. - /// - /// Added for `std::vec::Vec` compatibility (added in Rust 1.33.0) - /// - /// ``` - /// # use smallvec::{smallvec, SmallVec}; - /// let mut vec : SmallVec<[_; 4]> = smallvec![1, 2, 3]; - /// vec.resize_with(5, Default::default); - /// assert_eq!(&*vec, &[1, 2, 3, 0, 0]); - /// - /// let mut vec : SmallVec<[_; 4]> = smallvec![]; - /// let mut p = 1; - /// vec.resize_with(4, || { p *= 2; p }); - /// assert_eq!(&*vec, &[2, 4, 8, 16]); - /// ``` - pub fn resize_with<F>(&mut self, new_len: usize, f: F) - where - F: FnMut() -> A::Item, - { - let old_len = self.len(); - if old_len < new_len { - let mut f = f; - let additional = new_len - old_len; - self.reserve(additional); - for _ in 0..additional { - self.push(f()); - } - } else if old_len > new_len { - self.truncate(new_len); - } - } - - /// Creates a `SmallVec` directly from the raw components of another - /// `SmallVec`. - /// - /// # Safety - /// - /// This is highly unsafe, due to the number of invariants that aren't - /// checked: - /// - /// * `ptr` needs to have been previously allocated via `SmallVec` for its - /// spilled storage (at least, it's highly likely to be incorrect if it - /// wasn't). - /// * `ptr`'s `A::Item` type needs to be the same size and alignment that - /// it was allocated with - /// * `length` needs to be less than or equal to `capacity`. - /// * `capacity` needs to be the capacity that the pointer was allocated - /// with. - /// - /// Violating these may cause problems like corrupting the allocator's - /// internal data structures. - /// - /// Additionally, `capacity` must be greater than the amount of inline - /// storage `A` has; that is, the new `SmallVec` must need to spill over - /// into heap allocated storage. This condition is asserted against. - /// - /// The ownership of `ptr` is effectively transferred to the - /// `SmallVec` which may then deallocate, reallocate or change the - /// contents of memory pointed to by the pointer at will. Ensure - /// that nothing else uses the pointer after calling this - /// function. - /// - /// # Examples - /// - /// ``` - /// # use smallvec::{smallvec, SmallVec}; - /// use std::mem; - /// use std::ptr; - /// - /// fn main() { - /// let mut v: SmallVec<[_; 1]> = smallvec![1, 2, 3]; - /// - /// // Pull out the important parts of `v`. - /// let p = v.as_mut_ptr(); - /// let len = v.len(); - /// let cap = v.capacity(); - /// let spilled = v.spilled(); - /// - /// unsafe { - /// // Forget all about `v`. The heap allocation that stored the - /// // three values won't be deallocated. - /// mem::forget(v); - /// - /// // Overwrite memory with [4, 5, 6]. - /// // - /// // This is only safe if `spilled` is true! Otherwise, we are - /// // writing into the old `SmallVec`'s inline storage on the - /// // stack. - /// assert!(spilled); - /// for i in 0..len { - /// ptr::write(p.add(i), 4 + i); - /// } - /// - /// // Put everything back together into a SmallVec with a different - /// // amount of inline storage, but which is still less than `cap`. - /// let rebuilt = SmallVec::<[_; 2]>::from_raw_parts(p, len, cap); - /// assert_eq!(&*rebuilt, &[4, 5, 6]); - /// } - /// } - #[inline] - pub unsafe fn from_raw_parts(ptr: *mut A::Item, length: usize, capacity: usize) -> SmallVec<A> { - // SAFETY: We require caller to provide same ptr as we alloc - // and we never alloc null pointer. - let ptr = unsafe { - debug_assert!(!ptr.is_null(), "Called `from_raw_parts` with null pointer."); - NonNull::new_unchecked(ptr) - }; - assert!(capacity > Self::inline_capacity()); - SmallVec { - capacity, - data: SmallVecData::from_heap(ptr, length), - } - } - - /// Returns a raw pointer to the vector's buffer. - pub fn as_ptr(&self) -> *const A::Item { - // We shadow the slice method of the same name to avoid going through - // `deref`, which creates an intermediate reference that may place - // additional safety constraints on the contents of the slice. - self.triple().0.as_ptr() - } - - /// Returns a raw mutable pointer to the vector's buffer. - pub fn as_mut_ptr(&mut self) -> *mut A::Item { - // We shadow the slice method of the same name to avoid going through - // `deref_mut`, which creates an intermediate reference that may place - // additional safety constraints on the contents of the slice. - self.triple_mut().0.as_ptr() - } -} - -impl<A: Array> SmallVec<A> -where - A::Item: Copy, -{ - /// Copy the elements from a slice into a new `SmallVec`. - /// - /// For slices of `Copy` types, this is more efficient than `SmallVec::from(slice)`. - pub fn from_slice(slice: &[A::Item]) -> Self { - let len = slice.len(); - if len <= Self::inline_capacity() { - SmallVec { - capacity: len, - data: SmallVecData::from_inline(unsafe { - let mut data: MaybeUninit<A> = MaybeUninit::uninit(); - ptr::copy_nonoverlapping( - slice.as_ptr(), - data.as_mut_ptr() as *mut A::Item, - len, - ); - data - }), - } - } else { - let mut b = slice.to_vec(); - let cap = b.capacity(); - let ptr = NonNull::new(b.as_mut_ptr()).expect("Vec always contain non null pointers."); - mem::forget(b); - SmallVec { - capacity: cap, - data: SmallVecData::from_heap(ptr, len), - } - } - } - - /// 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`. - #[inline] - pub fn insert_from_slice(&mut self, index: usize, slice: &[A::Item]) { - self.reserve(slice.len()); - - let len = self.len(); - assert!(index <= len); - - unsafe { - let slice_ptr = slice.as_ptr(); - let ptr = self.as_mut_ptr().add(index); - ptr::copy(ptr, ptr.add(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<A: Array> SmallVec<A> -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) { - let old_len = self.len(); - - if len > old_len { - self.extend(repeat(value).take(len - old_len)); - } else { - self.truncate(len); - } - } - - /// Creates a `SmallVec` with `n` copies of `elem`. - /// ``` - /// use smallvec::SmallVec; - /// - /// let v = SmallVec::<[char; 128]>::from_elem('d', 2); - /// assert_eq!(v, SmallVec::from_buf(['d', 'd'])); - /// ``` - pub fn from_elem(elem: A::Item, n: usize) -> Self { - if n > Self::inline_capacity() { - vec![elem; n].into() - } else { - let mut v = SmallVec::<A>::new(); - unsafe { - let (ptr, len_ptr, _) = v.triple_mut(); - let ptr = ptr.as_ptr(); - let mut local_len = SetLenOnDrop::new(len_ptr); - - for i in 0..n { - ::core::ptr::write(ptr.add(i), elem.clone()); - local_len.increment_len(1); - } - } - v - } - } -} - -impl<A: Array> ops::Deref for SmallVec<A> { - type Target = [A::Item]; - #[inline] - fn deref(&self) -> &[A::Item] { - unsafe { - let (ptr, len, _) = self.triple(); - slice::from_raw_parts(ptr.as_ptr(), len) - } - } -} - -impl<A: Array> ops::DerefMut for SmallVec<A> { - #[inline] - fn deref_mut(&mut self) -> &mut [A::Item] { - unsafe { - let (ptr, &mut len, _) = self.triple_mut(); - slice::from_raw_parts_mut(ptr.as_ptr(), len) - } - } -} - -impl<A: Array> AsRef<[A::Item]> for SmallVec<A> { - #[inline] - fn as_ref(&self) -> &[A::Item] { - self - } -} - -impl<A: Array> AsMut<[A::Item]> for SmallVec<A> { - #[inline] - fn as_mut(&mut self) -> &mut [A::Item] { - self - } -} - -impl<A: Array> Borrow<[A::Item]> for SmallVec<A> { - #[inline] - fn borrow(&self) -> &[A::Item] { - self - } -} - -impl<A: Array> BorrowMut<[A::Item]> for SmallVec<A> { - #[inline] - fn borrow_mut(&mut self) -> &mut [A::Item] { - self - } -} - -#[cfg(feature = "write")] -#[cfg_attr(docsrs, doc(cfg(feature = "write")))] -impl<A: Array<Item = u8>> io::Write for SmallVec<A> { - #[inline] - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - 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(()) - } -} - -#[cfg(feature = "serde")] -#[cfg_attr(docsrs, doc(cfg(feature = "serde")))] -impl<A: Array> Serialize for SmallVec<A> -where - A::Item: Serialize, -{ - fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { - let mut state = serializer.serialize_seq(Some(self.len()))?; - for item in self { - state.serialize_element(&item)?; - } - state.end() - } -} - -#[cfg(feature = "serde")] -#[cfg_attr(docsrs, doc(cfg(feature = "serde")))] -impl<'de, A: Array> Deserialize<'de> for SmallVec<A> -where - A::Item: Deserialize<'de>, -{ - fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { - deserializer.deserialize_seq(SmallVecVisitor { - phantom: PhantomData, - }) - } -} - -#[cfg(feature = "serde")] -struct SmallVecVisitor<A> { - phantom: PhantomData<A>, -} - -#[cfg(feature = "serde")] -impl<'de, A: Array> Visitor<'de> for SmallVecVisitor<A> -where - A::Item: Deserialize<'de>, -{ - type Value = SmallVec<A>; - - fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - formatter.write_str("a sequence") - } - - fn visit_seq<B>(self, mut seq: B) -> Result<Self::Value, B::Error> - where - B: SeqAccess<'de>, - { - use serde::de::Error; - let len = seq.size_hint().unwrap_or(0); - let mut values = SmallVec::new(); - values.try_reserve(len).map_err(B::Error::custom)?; - - while let Some(value) = seq.next_element()? { - values.push(value); - } - - Ok(values) - } -} - -#[cfg(feature = "specialization")] -trait SpecFrom<A: Array, S> { - fn spec_from(slice: S) -> SmallVec<A>; -} - -#[cfg(feature = "specialization")] -mod specialization; - -#[cfg(feature = "arbitrary")] -mod arbitrary; - -#[cfg(feature = "specialization")] -impl<'a, A: Array> SpecFrom<A, &'a [A::Item]> for SmallVec<A> -where - A::Item: Copy, -{ - #[inline] - fn spec_from(slice: &'a [A::Item]) -> SmallVec<A> { - SmallVec::from_slice(slice) - } -} - -impl<'a, A: Array> From<&'a [A::Item]> for SmallVec<A> -where - A::Item: Clone, -{ - #[cfg(not(feature = "specialization"))] - #[inline] - fn from(slice: &'a [A::Item]) -> SmallVec<A> { - slice.iter().cloned().collect() - } - - #[cfg(feature = "specialization")] - #[inline] - fn from(slice: &'a [A::Item]) -> SmallVec<A> { - SmallVec::spec_from(slice) - } -} - -impl<A: Array> From<Vec<A::Item>> for SmallVec<A> { - #[inline] - fn from(vec: Vec<A::Item>) -> SmallVec<A> { - SmallVec::from_vec(vec) - } -} - -impl<A: Array> From<A> for SmallVec<A> { - #[inline] - fn from(array: A) -> SmallVec<A> { - SmallVec::from_buf(array) - } -} - -impl<A: Array, I: SliceIndex<[A::Item]>> ops::Index<I> for SmallVec<A> { - type Output = I::Output; - - fn index(&self, index: I) -> &I::Output { - &(**self)[index] - } -} - -impl<A: Array, I: SliceIndex<[A::Item]>> ops::IndexMut<I> for SmallVec<A> { - fn index_mut(&mut self, index: I) -> &mut I::Output { - &mut (&mut **self)[index] - } -} - -#[allow(deprecated)] -impl<A: Array> ExtendFromSlice<A::Item> for SmallVec<A> -where - A::Item: Copy, -{ - fn extend_from_slice(&mut self, other: &[A::Item]) { - SmallVec::extend_from_slice(self, other) - } -} - -impl<A: Array> FromIterator<A::Item> for SmallVec<A> { - #[inline] - fn from_iter<I: IntoIterator<Item = A::Item>>(iterable: I) -> SmallVec<A> { - let mut v = SmallVec::new(); - v.extend(iterable); - v - } -} - -impl<A: Array> Extend<A::Item> for SmallVec<A> { - fn extend<I: IntoIterator<Item = A::Item>>(&mut self, iterable: I) { - let mut iter = iterable.into_iter(); - let (lower_size_bound, _) = iter.size_hint(); - self.reserve(lower_size_bound); - - unsafe { - let (ptr, len_ptr, cap) = self.triple_mut(); - let ptr = ptr.as_ptr(); - let mut len = SetLenOnDrop::new(len_ptr); - while len.get() < cap { - if let Some(out) = iter.next() { - ptr::write(ptr.add(len.get()), out); - len.increment_len(1); - } else { - return; - } - } - } - - for elem in iter { - self.push(elem); - } - } -} - -impl<A: Array> fmt::Debug for SmallVec<A> -where - A::Item: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(self.iter()).finish() - } -} - -impl<A: Array> Default for SmallVec<A> { - #[inline] - fn default() -> SmallVec<A> { - SmallVec::new() - } -} - -#[cfg(feature = "may_dangle")] -unsafe impl<#[may_dangle] A: Array> Drop for SmallVec<A> { - fn drop(&mut self) { - unsafe { - if self.spilled() { - let (ptr, &mut len) = self.data.heap_mut(); - Vec::from_raw_parts(ptr.as_ptr(), len, self.capacity); - } else { - ptr::drop_in_place(&mut self[..]); - } - } - } -} - -#[cfg(not(feature = "may_dangle"))] -impl<A: Array> Drop for SmallVec<A> { - fn drop(&mut self) { - unsafe { - if self.spilled() { - let (ptr, &mut len) = self.data.heap_mut(); - drop(Vec::from_raw_parts(ptr.as_ptr(), len, self.capacity)); - } else { - ptr::drop_in_place(&mut self[..]); - } - } - } -} - -impl<A: Array> Clone for SmallVec<A> -where - A::Item: Clone, -{ - #[inline] - fn clone(&self) -> SmallVec<A> { - SmallVec::from(self.as_slice()) - } - - fn clone_from(&mut self, source: &Self) { - // Inspired from `impl Clone for Vec`. - - // drop anything that will not be overwritten - self.truncate(source.len()); - - // self.len <= other.len due to the truncate above, so the - // slices here are always in-bounds. - let (init, tail) = source.split_at(self.len()); - - // reuse the contained values' allocations/resources. - self.clone_from_slice(init); - self.extend(tail.iter().cloned()); - } -} - -impl<A: Array, B: Array> PartialEq<SmallVec<B>> for SmallVec<A> -where - A::Item: PartialEq<B::Item>, -{ - #[inline] - fn eq(&self, other: &SmallVec<B>) -> bool { - self[..] == other[..] - } -} - -impl<A: Array> Eq for SmallVec<A> where A::Item: Eq {} - -impl<A: Array> PartialOrd for SmallVec<A> -where - A::Item: PartialOrd, -{ - #[inline] - fn partial_cmp(&self, other: &SmallVec<A>) -> Option<cmp::Ordering> { - PartialOrd::partial_cmp(&**self, &**other) - } -} - -impl<A: Array> Ord for SmallVec<A> -where - A::Item: Ord, -{ - #[inline] - fn cmp(&self, other: &SmallVec<A>) -> cmp::Ordering { - Ord::cmp(&**self, &**other) - } -} - -impl<A: Array> Hash for SmallVec<A> -where - A::Item: Hash, -{ - fn hash<H: Hasher>(&self, state: &mut H) { - (**self).hash(state) - } -} - -unsafe impl<A: Array> Send for SmallVec<A> where A::Item: Send {} - -/// An iterator that consumes a `SmallVec` and yields its items by value. -/// -/// Returned from [`SmallVec::into_iter`][1]. -/// -/// [1]: struct.SmallVec.html#method.into_iter -pub struct IntoIter<A: Array> { - data: SmallVec<A>, - current: usize, - end: usize, -} - -impl<A: Array> fmt::Debug for IntoIter<A> -where - A::Item: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("IntoIter").field(&self.as_slice()).finish() - } -} - -impl<A: Array + Clone> Clone for IntoIter<A> -where - A::Item: Clone, -{ - fn clone(&self) -> IntoIter<A> { - SmallVec::from(self.as_slice()).into_iter() - } -} - -impl<A: Array> Drop for IntoIter<A> { - fn drop(&mut self) { - for _ in self {} - } -} - -impl<A: Array> Iterator for IntoIter<A> { - type Item = A::Item; - - #[inline] - fn next(&mut self) -> Option<A::Item> { - if self.current == self.end { - None - } else { - unsafe { - let current = self.current; - self.current += 1; - Some(ptr::read(self.data.as_ptr().add(current))) - } - } - } - - #[inline] - fn size_hint(&self) -> (usize, Option<usize>) { - let size = self.end - self.current; - (size, Some(size)) - } -} - -impl<A: Array> DoubleEndedIterator for IntoIter<A> { - #[inline] - fn next_back(&mut self) -> Option<A::Item> { - if self.current == self.end { - None - } else { - unsafe { - self.end -= 1; - Some(ptr::read(self.data.as_ptr().add(self.end))) - } - } - } -} - -impl<A: Array> ExactSizeIterator for IntoIter<A> {} -impl<A: Array> FusedIterator for IntoIter<A> {} - -impl<A: Array> IntoIter<A> { - /// Returns the remaining items of this iterator as a slice. - pub fn as_slice(&self) -> &[A::Item] { - let len = self.end - self.current; - unsafe { core::slice::from_raw_parts(self.data.as_ptr().add(self.current), len) } - } - - /// Returns the remaining items of this iterator as a mutable slice. - pub fn as_mut_slice(&mut self) -> &mut [A::Item] { - let len = self.end - self.current; - unsafe { core::slice::from_raw_parts_mut(self.data.as_mut_ptr().add(self.current), len) } - } -} - -impl<A: Array> IntoIterator for SmallVec<A> { - type IntoIter = IntoIter<A>; - type Item = A::Item; - fn into_iter(mut self) -> Self::IntoIter { - unsafe { - // Set SmallVec 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 SmallVec<A> { - 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 SmallVec<A> { - type IntoIter = slice::IterMut<'a, A::Item>; - type Item = &'a mut A::Item; - fn into_iter(self) -> Self::IntoIter { - self.iter_mut() - } -} - -/// Types that can be used as the backing store for a [`SmallVec`]. -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; -} - -/// 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, - } - } - - #[inline] - fn get(&self) -> usize { - self.local_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; - } -} - -#[cfg(feature = "const_new")] -impl<T, const N: usize> SmallVec<[T; N]> { - /// Construct an empty vector. - /// - /// This is a `const` version of [`SmallVec::new`] that is enabled by the feature `const_new`, with the limitation that it only works for arrays. - #[cfg_attr(docsrs, doc(cfg(feature = "const_new")))] - #[inline] - pub const fn new_const() -> Self { - SmallVec { - capacity: 0, - data: SmallVecData::from_const(MaybeUninit::uninit()), - } - } - - /// The array passed as an argument is moved to be an inline version of `SmallVec`. - /// - /// This is a `const` version of [`SmallVec::from_buf`] that is enabled by the feature `const_new`, with the limitation that it only works for arrays. - #[cfg_attr(docsrs, doc(cfg(feature = "const_new")))] - #[inline] - pub const fn from_const(items: [T; N]) -> Self { - SmallVec { - capacity: N, - data: SmallVecData::from_const(MaybeUninit::new(items)), - } - } -} - -#[cfg(feature = "const_generics")] -#[cfg_attr(docsrs, doc(cfg(feature = "const_generics")))] -unsafe impl<T, const N: usize> Array for [T; N] { - type Item = T; - #[inline] - fn size() -> usize { - N - } -} - -#[cfg(not(feature = "const_generics"))] -macro_rules! impl_array( - ($($size:expr),+) => { - $( - unsafe impl<T> Array for [T; $size] { - type Item = T; - #[inline] - fn size() -> usize { $size } - } - )+ - } -); - -#[cfg(not(feature = "const_generics"))] -impl_array!( - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 36, 0x40, 0x60, 0x80, 0x100, 0x200, 0x400, 0x600, 0x800, 0x1000, - 0x2000, 0x4000, 0x6000, 0x8000, 0x10000, 0x20000, 0x40000, 0x60000, 0x80000, 0x10_0000 -); - -/// Convenience trait for constructing a `SmallVec` -pub trait ToSmallVec<A: Array> { - /// Construct a new `SmallVec` from a slice. - fn to_smallvec(&self) -> SmallVec<A>; -} - -impl<A: Array> ToSmallVec<A> for [A::Item] -where - A::Item: Copy, -{ - #[inline] - fn to_smallvec(&self) -> SmallVec<A> { - SmallVec::from_slice(self) - } -} - -// Immutable counterpart for `NonNull<T>`. -#[repr(transparent)] -struct ConstNonNull<T>(NonNull<T>); - -impl<T> ConstNonNull<T> { - #[inline] - fn new(ptr: *const T) -> Option<Self> { - NonNull::new(ptr as *mut T).map(Self) - } - #[inline] - fn as_ptr(self) -> *const T { - self.0.as_ptr() - } -} - -impl<T> Clone for ConstNonNull<T> { - #[inline] - fn clone(&self) -> Self { - *self - } -} - -impl<T> Copy for ConstNonNull<T> {} diff --git a/vendor/smallvec/src/specialization.rs b/vendor/smallvec/src/specialization.rs deleted file mode 100644 index 658fa77..0000000 --- a/vendor/smallvec/src/specialization.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Implementations that require `default fn`. - -use super::{Array, SmallVec, SpecFrom}; - -impl<'a, A: Array> SpecFrom<A, &'a [A::Item]> for SmallVec<A> -where - A::Item: Clone, -{ - #[inline] - default fn spec_from(slice: &'a [A::Item]) -> SmallVec<A> { - slice.into_iter().cloned().collect() - } -} diff --git a/vendor/smallvec/src/tests.rs b/vendor/smallvec/src/tests.rs deleted file mode 100644 index 936ad6f..0000000 --- a/vendor/smallvec/src/tests.rs +++ /dev/null @@ -1,1013 +0,0 @@ -use crate::{smallvec, SmallVec}; - -use std::iter::FromIterator; - -use alloc::borrow::ToOwned; -use alloc::boxed::Box; -use alloc::rc::Rc; -use alloc::{vec, vec::Vec}; - -#[test] -pub fn test_zero() { - let mut v = SmallVec::<[_; 0]>::new(); - assert!(!v.spilled()); - v.push(0usize); - assert!(v.spilled()); - assert_eq!(&*v, &[0]); -} - -// We heap allocate all these strings so that double frees will show up under valgrind. - -#[test] -pub fn test_inline() { - let mut v = SmallVec::<[_; 16]>::new(); - v.push("hello".to_owned()); - v.push("there".to_owned()); - assert_eq!(&*v, &["hello".to_owned(), "there".to_owned(),][..]); -} - -#[test] -pub fn test_spill() { - let mut v = SmallVec::<[_; 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] -pub fn test_double_spill() { - let mut v = SmallVec::<[_; 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() { - SmallVec::<[Box<u32>; 2]>::new(); -} - -// https://github.com/servo/rust-smallvec/issues/5 -#[test] -fn issue_5() { - assert!(Some(SmallVec::<[&u32; 2]>::new()).is_some()); -} - -#[test] -fn test_with_capacity() { - let v: SmallVec<[u8; 3]> = SmallVec::with_capacity(1); - assert!(v.is_empty()); - assert!(!v.spilled()); - assert_eq!(v.capacity(), 3); - - let v: SmallVec<[u8; 3]> = SmallVec::with_capacity(10); - assert!(v.is_empty()); - assert!(v.spilled()); - assert_eq!(v.capacity(), 10); -} - -#[test] -fn drain() { - let mut v: SmallVec<[u8; 2]> = SmallVec::new(); - v.push(3); - assert_eq!(v.drain(..).collect::<Vec<_>>(), &[3]); - - // spilling the vec - v.push(3); - v.push(4); - v.push(5); - let old_capacity = v.capacity(); - assert_eq!(v.drain(1..).collect::<Vec<_>>(), &[4, 5]); - // drain should not change the capacity - assert_eq!(v.capacity(), old_capacity); - - // Exercise the tail-shifting code when in the inline state - // This has the potential to produce UB due to aliasing - let mut v: SmallVec<[u8; 2]> = SmallVec::new(); - v.push(1); - v.push(2); - assert_eq!(v.drain(..1).collect::<Vec<_>>(), &[1]); -} - -#[test] -fn drain_rev() { - let mut v: SmallVec<[u8; 2]> = SmallVec::new(); - v.push(3); - assert_eq!(v.drain(..).rev().collect::<Vec<_>>(), &[3]); - - // spilling the vec - v.push(3); - v.push(4); - v.push(5); - assert_eq!(v.drain(..).rev().collect::<Vec<_>>(), &[5, 4, 3]); -} - -#[test] -fn drain_forget() { - let mut v: SmallVec<[u8; 1]> = smallvec![0, 1, 2, 3, 4, 5, 6, 7]; - std::mem::forget(v.drain(2..5)); - assert_eq!(v.len(), 2); -} - -#[test] -fn into_iter() { - let mut v: SmallVec<[u8; 2]> = SmallVec::new(); - v.push(3); - assert_eq!(v.into_iter().collect::<Vec<_>>(), &[3]); - - // spilling the vec - let mut v: SmallVec<[u8; 2]> = SmallVec::new(); - v.push(3); - v.push(4); - v.push(5); - assert_eq!(v.into_iter().collect::<Vec<_>>(), &[3, 4, 5]); -} - -#[test] -fn into_iter_rev() { - let mut v: SmallVec<[u8; 2]> = SmallVec::new(); - v.push(3); - assert_eq!(v.into_iter().rev().collect::<Vec<_>>(), &[3]); - - // spilling the vec - let mut v: SmallVec<[u8; 2]> = SmallVec::new(); - v.push(3); - v.push(4); - v.push(5); - assert_eq!(v.into_iter().rev().collect::<Vec<_>>(), &[5, 4, 3]); -} - -#[test] -fn into_iter_drop() { - use std::cell::Cell; - - struct DropCounter<'a>(&'a Cell<i32>); - - 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: SmallVec<[DropCounter<'_>; 2]> = SmallVec::new(); - v.push(DropCounter(&cell)); - v.into_iter(); - assert_eq!(cell.get(), 1); - } - - { - let cell = Cell::new(0); - let mut v: SmallVec<[DropCounter<'_>; 2]> = SmallVec::new(); - v.push(DropCounter(&cell)); - v.push(DropCounter(&cell)); - assert!(v.into_iter().next().is_some()); - assert_eq!(cell.get(), 2); - } - - { - let cell = Cell::new(0); - let mut v: SmallVec<[DropCounter<'_>; 2]> = SmallVec::new(); - v.push(DropCounter(&cell)); - v.push(DropCounter(&cell)); - v.push(DropCounter(&cell)); - assert!(v.into_iter().next().is_some()); - assert_eq!(cell.get(), 3); - } - { - let cell = Cell::new(0); - let mut v: SmallVec<[DropCounter<'_>; 2]> = SmallVec::new(); - v.push(DropCounter(&cell)); - v.push(DropCounter(&cell)); - v.push(DropCounter(&cell)); - { - let mut it = v.into_iter(); - assert!(it.next().is_some()); - assert!(it.next_back().is_some()); - } - assert_eq!(cell.get(), 3); - } -} - -#[test] -fn test_capacity() { - let mut v: SmallVec<[u8; 2]> = SmallVec::new(); - v.reserve(1); - assert_eq!(v.capacity(), 2); - assert!(!v.spilled()); - - v.reserve_exact(0x100); - assert!(v.capacity() >= 0x100); - - v.push(0); - v.push(1); - v.push(2); - v.push(3); - - v.shrink_to_fit(); - assert!(v.capacity() < 0x100); -} - -#[test] -fn test_truncate() { - let mut v: SmallVec<[Box<u8>; 8]> = SmallVec::new(); - - for x in 0..8 { - v.push(Box::new(x)); - } - v.truncate(4); - - assert_eq!(v.len(), 4); - assert!(!v.spilled()); - - 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::<Vec<_>>(), &[0, 3, 2]); -} - -#[test] -fn test_insert_many() { - let mut v: SmallVec<[u8; 8]> = SmallVec::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::<Vec<_>>(), - &[0, 5, 6, 1, 2, 3] - ); -} - -struct MockHintIter<T: Iterator> { - x: T, - hint: usize, -} -impl<T: Iterator> Iterator for MockHintIter<T> { - type Item = T::Item; - fn next(&mut self) -> Option<Self::Item> { - self.x.next() - } - fn size_hint(&self) -> (usize, Option<usize>) { - (self.hint, None) - } -} - -#[test] -fn test_insert_many_short_hint() { - let mut v: SmallVec<[u8; 8]> = SmallVec::new(); - for x in 0..4 { - v.push(x); - } - assert_eq!(v.len(), 4); - v.insert_many( - 1, - MockHintIter { - x: [5, 6].iter().cloned(), - hint: 5, - }, - ); - assert_eq!( - &v.iter().map(|v| *v).collect::<Vec<_>>(), - &[0, 5, 6, 1, 2, 3] - ); -} - -#[test] -fn test_insert_many_long_hint() { - let mut v: SmallVec<[u8; 8]> = SmallVec::new(); - for x in 0..4 { - v.push(x); - } - assert_eq!(v.len(), 4); - v.insert_many( - 1, - MockHintIter { - x: [5, 6].iter().cloned(), - hint: 1, - }, - ); - assert_eq!( - &v.iter().map(|v| *v).collect::<Vec<_>>(), - &[0, 5, 6, 1, 2, 3] - ); -} - -// https://github.com/servo/rust-smallvec/issues/96 -mod insert_many_panic { - use crate::{smallvec, SmallVec}; - use alloc::boxed::Box; - - struct PanicOnDoubleDrop { - dropped: Box<bool>, - } - - impl PanicOnDoubleDrop { - fn new() -> Self { - Self { - dropped: Box::new(false), - } - } - } - - impl Drop for PanicOnDoubleDrop { - fn drop(&mut self) { - assert!(!*self.dropped, "already dropped"); - *self.dropped = true; - } - } - - /// Claims to yield `hint` items, but actually yields `count`, then panics. - struct BadIter { - hint: usize, - count: usize, - } - - impl Iterator for BadIter { - type Item = PanicOnDoubleDrop; - fn size_hint(&self) -> (usize, Option<usize>) { - (self.hint, None) - } - fn next(&mut self) -> Option<Self::Item> { - if self.count == 0 { - panic!() - } - self.count -= 1; - Some(PanicOnDoubleDrop::new()) - } - } - - #[test] - fn panic_early_at_start() { - let mut vec: SmallVec<[PanicOnDoubleDrop; 0]> = - smallvec![PanicOnDoubleDrop::new(), PanicOnDoubleDrop::new(),]; - let result = ::std::panic::catch_unwind(move || { - vec.insert_many(0, BadIter { hint: 1, count: 0 }); - }); - assert!(result.is_err()); - } - - #[test] - fn panic_early_in_middle() { - let mut vec: SmallVec<[PanicOnDoubleDrop; 0]> = - smallvec![PanicOnDoubleDrop::new(), PanicOnDoubleDrop::new(),]; - let result = ::std::panic::catch_unwind(move || { - vec.insert_many(1, BadIter { hint: 4, count: 2 }); - }); - assert!(result.is_err()); - } - - #[test] - fn panic_early_at_end() { - let mut vec: SmallVec<[PanicOnDoubleDrop; 0]> = - smallvec![PanicOnDoubleDrop::new(), PanicOnDoubleDrop::new(),]; - let result = ::std::panic::catch_unwind(move || { - vec.insert_many(2, BadIter { hint: 3, count: 1 }); - }); - assert!(result.is_err()); - } - - #[test] - fn panic_late_at_start() { - let mut vec: SmallVec<[PanicOnDoubleDrop; 0]> = - smallvec![PanicOnDoubleDrop::new(), PanicOnDoubleDrop::new(),]; - let result = ::std::panic::catch_unwind(move || { - vec.insert_many(0, BadIter { hint: 3, count: 5 }); - }); - assert!(result.is_err()); - } - - #[test] - fn panic_late_at_end() { - let mut vec: SmallVec<[PanicOnDoubleDrop; 0]> = - smallvec![PanicOnDoubleDrop::new(), PanicOnDoubleDrop::new(),]; - let result = ::std::panic::catch_unwind(move || { - vec.insert_many(2, BadIter { hint: 3, count: 5 }); - }); - assert!(result.is_err()); - } -} - -#[test] -#[should_panic] -fn test_invalid_grow() { - let mut v: SmallVec<[u8; 8]> = SmallVec::new(); - v.extend(0..8); - v.grow(5); -} - -#[test] -#[should_panic] -fn drain_overflow() { - let mut v: SmallVec<[u8; 8]> = smallvec![0]; - v.drain(..=std::usize::MAX); -} - -#[test] -fn test_insert_from_slice() { - let mut v: SmallVec<[u8; 8]> = SmallVec::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::<Vec<_>>(), - &[0, 5, 6, 1, 2, 3] - ); -} - -#[test] -fn test_extend_from_slice() { - let mut v: SmallVec<[u8; 8]> = SmallVec::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::<Vec<_>>(), - &[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 = SmallVec::<[_; 1]>::new(); - v.push(DropPanic); -} - -#[test] -fn test_eq() { - let mut a: SmallVec<[u32; 2]> = SmallVec::new(); - let mut b: SmallVec<[u32; 2]> = SmallVec::new(); - let mut c: SmallVec<[u32; 2]> = SmallVec::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: SmallVec<[u32; 2]> = SmallVec::new(); - let mut b: SmallVec<[u32; 2]> = SmallVec::new(); - let mut c: SmallVec<[u32; 2]> = SmallVec::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); -} - -#[test] -fn test_hash() { - use std::collections::hash_map::DefaultHasher; - use std::hash::Hash; - - { - let mut a: SmallVec<[u32; 2]> = SmallVec::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: SmallVec<[u32; 2]> = SmallVec::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: SmallVec<[u32; 2]> = SmallVec::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: SmallVec<[u32; 2]> = SmallVec::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: SmallVec<[u32; 2]> = SmallVec::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: SmallVec<[u32; 2]> = SmallVec::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!(&SmallVec::<[u32; 2]>::from(&[1][..])[..], [1]); - assert_eq!(&SmallVec::<[u32; 2]>::from(&[1, 2, 3][..])[..], [1, 2, 3]); - - let vec = vec![]; - let small_vec: SmallVec<[u8; 3]> = SmallVec::from(vec); - assert_eq!(&*small_vec, &[]); - drop(small_vec); - - let vec = vec![1, 2, 3, 4, 5]; - let small_vec: SmallVec<[u8; 3]> = SmallVec::from(vec); - assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]); - drop(small_vec); - - let vec = vec![1, 2, 3, 4, 5]; - let small_vec: SmallVec<[u8; 1]> = SmallVec::from(vec); - assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]); - drop(small_vec); - - let array = [1]; - let small_vec: SmallVec<[u8; 1]> = SmallVec::from(array); - assert_eq!(&*small_vec, &[1]); - drop(small_vec); - - let array = [99; 128]; - let small_vec: SmallVec<[u8; 128]> = SmallVec::from(array); - assert_eq!(&*small_vec, vec![99u8; 128].as_slice()); - drop(small_vec); -} - -#[test] -fn test_from_slice() { - assert_eq!(&SmallVec::<[u32; 2]>::from_slice(&[1][..])[..], [1]); - assert_eq!( - &SmallVec::<[u32; 2]>::from_slice(&[1, 2, 3][..])[..], - [1, 2, 3] - ); -} - -#[test] -fn test_exact_size_iterator() { - let mut vec = SmallVec::<[u32; 2]>::from(&[1, 2, 3][..]); - assert_eq!(vec.clone().into_iter().len(), 3); - assert_eq!(vec.drain(..2).len(), 2); - assert_eq!(vec.into_iter().len(), 1); -} - -#[test] -fn test_into_iter_as_slice() { - let vec = SmallVec::<[u32; 2]>::from(&[1, 2, 3][..]); - let mut iter = vec.clone().into_iter(); - assert_eq!(iter.as_slice(), &[1, 2, 3]); - assert_eq!(iter.as_mut_slice(), &[1, 2, 3]); - iter.next(); - assert_eq!(iter.as_slice(), &[2, 3]); - assert_eq!(iter.as_mut_slice(), &[2, 3]); - iter.next_back(); - assert_eq!(iter.as_slice(), &[2]); - assert_eq!(iter.as_mut_slice(), &[2]); -} - -#[test] -fn test_into_iter_clone() { - // Test that the cloned iterator yields identical elements and that it owns its own copy - // (i.e. no use after move errors). - let mut iter = SmallVec::<[u8; 2]>::from_iter(0..3).into_iter(); - let mut clone_iter = iter.clone(); - while let Some(x) = iter.next() { - assert_eq!(x, clone_iter.next().unwrap()); - } - assert_eq!(clone_iter.next(), None); -} - -#[test] -fn test_into_iter_clone_partially_consumed_iterator() { - // Test that the cloned iterator only contains the remaining elements of the original iterator. - let mut iter = SmallVec::<[u8; 2]>::from_iter(0..3).into_iter().skip(1); - let mut clone_iter = iter.clone(); - while let Some(x) = iter.next() { - assert_eq!(x, clone_iter.next().unwrap()); - } - assert_eq!(clone_iter.next(), None); -} - -#[test] -fn test_into_iter_clone_empty_smallvec() { - let mut iter = SmallVec::<[u8; 2]>::new().into_iter(); - let mut clone_iter = iter.clone(); - assert_eq!(iter.next(), None); - assert_eq!(clone_iter.next(), None); -} - -#[test] -fn shrink_to_fit_unspill() { - let mut vec = SmallVec::<[u8; 2]>::from_iter(0..3); - vec.pop(); - assert!(vec.spilled()); - vec.shrink_to_fit(); - assert!(!vec.spilled(), "shrink_to_fit will un-spill if possible"); -} - -#[test] -fn test_into_vec() { - let vec = SmallVec::<[u8; 2]>::from_iter(0..2); - assert_eq!(vec.into_vec(), vec![0, 1]); - - let vec = SmallVec::<[u8; 2]>::from_iter(0..3); - assert_eq!(vec.into_vec(), vec![0, 1, 2]); -} - -#[test] -fn test_into_inner() { - let vec = SmallVec::<[u8; 2]>::from_iter(0..2); - assert_eq!(vec.into_inner(), Ok([0, 1])); - - let vec = SmallVec::<[u8; 2]>::from_iter(0..1); - assert_eq!(vec.clone().into_inner(), Err(vec)); - - let vec = SmallVec::<[u8; 2]>::from_iter(0..3); - assert_eq!(vec.clone().into_inner(), Err(vec)); -} - -#[test] -fn test_from_vec() { - let vec = vec![]; - let small_vec: SmallVec<[u8; 3]> = SmallVec::from_vec(vec); - assert_eq!(&*small_vec, &[]); - drop(small_vec); - - let vec = vec![]; - let small_vec: SmallVec<[u8; 1]> = SmallVec::from_vec(vec); - assert_eq!(&*small_vec, &[]); - drop(small_vec); - - let vec = vec![1]; - let small_vec: SmallVec<[u8; 3]> = SmallVec::from_vec(vec); - assert_eq!(&*small_vec, &[1]); - drop(small_vec); - - let vec = vec![1, 2, 3]; - let small_vec: SmallVec<[u8; 3]> = SmallVec::from_vec(vec); - assert_eq!(&*small_vec, &[1, 2, 3]); - drop(small_vec); - - let vec = vec![1, 2, 3, 4, 5]; - let small_vec: SmallVec<[u8; 3]> = SmallVec::from_vec(vec); - assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]); - drop(small_vec); - - let vec = vec![1, 2, 3, 4, 5]; - let small_vec: SmallVec<[u8; 1]> = SmallVec::from_vec(vec); - assert_eq!(&*small_vec, &[1, 2, 3, 4, 5]); - drop(small_vec); -} - -#[test] -fn test_retain() { - // Test inline data storate - let mut sv: SmallVec<[i32; 5]> = SmallVec::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 spilled data storage - let mut sv: SmallVec<[i32; 3]> = SmallVec::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: SmallVec<[Rc<i32>; 3]> = SmallVec::new(); - sv.push(Rc::clone(&one)); - assert_eq!(Rc::strong_count(&one), 2); - sv.retain(|_| false); - assert_eq!(Rc::strong_count(&one), 1); - - // Test that drop implementations are called for spilled data. - let mut sv: SmallVec<[Rc<i32>; 1]> = SmallVec::new(); - sv.push(Rc::clone(&one)); - sv.push(Rc::new(2)); - assert_eq!(Rc::strong_count(&one), 2); - sv.retain(|_| false); - assert_eq!(Rc::strong_count(&one), 1); -} - -#[test] -fn test_dedup() { - let mut dupes: SmallVec<[i32; 5]> = SmallVec::from_slice(&[1, 1, 2, 3, 3]); - dupes.dedup(); - assert_eq!(&*dupes, &[1, 2, 3]); - - let mut empty: SmallVec<[i32; 5]> = SmallVec::new(); - empty.dedup(); - assert!(empty.is_empty()); - - let mut all_ones: SmallVec<[i32; 5]> = SmallVec::from_slice(&[1, 1, 1, 1, 1]); - all_ones.dedup(); - assert_eq!(all_ones.len(), 1); - - let mut no_dupes: SmallVec<[i32; 5]> = SmallVec::from_slice(&[1, 2, 3, 4, 5]); - no_dupes.dedup(); - assert_eq!(no_dupes.len(), 5); -} - -#[test] -fn test_resize() { - let mut v: SmallVec<[i32; 8]> = SmallVec::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 = "write")] -#[test] -fn test_write() { - use std::io::Write; - - let data = [1, 2, 3, 4, 5]; - - let mut small_vec: SmallVec<[u8; 2]> = SmallVec::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: SmallVec<[u8; 2]> = SmallVec::new(); - small_vec.write_all(&data[..]).unwrap(); - assert_eq!(small_vec.as_ref(), data.as_ref()); -} - -#[cfg(feature = "serde")] -#[test] -fn test_serde() { - use bincode::{config, deserialize}; - let mut small_vec: SmallVec<[i32; 2]> = SmallVec::new(); - small_vec.push(1); - let encoded = config().limit(100).serialize(&small_vec).unwrap(); - let decoded: SmallVec<[i32; 2]> = deserialize(&encoded).unwrap(); - assert_eq!(small_vec, decoded); - small_vec.push(2); - // Spill the vec - small_vec.push(3); - small_vec.push(4); - // Check again after spilling. - let encoded = config().limit(100).serialize(&small_vec).unwrap(); - let decoded: SmallVec<[i32; 2]> = deserialize(&encoded).unwrap(); - assert_eq!(small_vec, decoded); -} - -#[test] -fn grow_to_shrink() { - let mut v: SmallVec<[u8; 2]> = SmallVec::new(); - v.push(1); - v.push(2); - v.push(3); - assert!(v.spilled()); - v.clear(); - // Shrink to inline. - v.grow(2); - assert!(!v.spilled()); - assert_eq!(v.capacity(), 2); - assert_eq!(v.len(), 0); - v.push(4); - assert_eq!(v[..], [4]); -} - -#[test] -fn resumable_extend() { - let s = "a b c"; - // This iterator yields: (Some('a'), None, Some('b'), None, Some('c')), None - let it = s - .chars() - .scan(0, |_, ch| if ch.is_whitespace() { None } else { Some(ch) }); - let mut v: SmallVec<[char; 4]> = SmallVec::new(); - v.extend(it); - assert_eq!(v[..], ['a']); -} - -// #139 -#[test] -fn uninhabited() { - enum Void {} - let _sv = SmallVec::<[Void; 8]>::new(); -} - -#[test] -fn grow_spilled_same_size() { - let mut v: SmallVec<[u8; 2]> = SmallVec::new(); - v.push(0); - v.push(1); - v.push(2); - assert!(v.spilled()); - assert_eq!(v.capacity(), 4); - // grow with the same capacity - v.grow(4); - assert_eq!(v.capacity(), 4); - assert_eq!(v[..], [0, 1, 2]); -} - -#[cfg(feature = "const_generics")] -#[test] -fn const_generics() { - let _v = SmallVec::<[i32; 987]>::default(); -} - -#[cfg(feature = "const_new")] -#[test] -fn const_new() { - let v = const_new_inner(); - assert_eq!(v.capacity(), 4); - assert_eq!(v.len(), 0); - let v = const_new_inline_sized(); - assert_eq!(v.capacity(), 4); - assert_eq!(v.len(), 4); - assert_eq!(v[0], 1); - let v = const_new_inline_args(); - assert_eq!(v.capacity(), 2); - assert_eq!(v.len(), 2); - assert_eq!(v[0], 1); - assert_eq!(v[1], 4); -} -#[cfg(feature = "const_new")] -const fn const_new_inner() -> SmallVec<[i32; 4]> { - SmallVec::<[i32; 4]>::new_const() -} -#[cfg(feature = "const_new")] -const fn const_new_inline_sized() -> SmallVec<[i32; 4]> { - crate::smallvec_inline![1; 4] -} -#[cfg(feature = "const_new")] -const fn const_new_inline_args() -> SmallVec<[i32; 2]> { - crate::smallvec_inline![1, 4] -} - -#[test] -fn empty_macro() { - let _v: SmallVec<[u8; 1]> = smallvec![]; -} - -#[test] -fn zero_size_items() { - SmallVec::<[(); 0]>::new().push(()); -} - -#[test] -fn test_insert_many_overflow() { - let mut v: SmallVec<[u8; 1]> = SmallVec::new(); - v.push(123); - - // Prepare an iterator with small lower bound - let iter = (0u8..5).filter(|n| n % 2 == 0); - assert_eq!(iter.size_hint().0, 0); - - v.insert_many(0, iter); - assert_eq!(&*v, &[0, 2, 4, 123]); -} - -#[test] -fn test_clone_from() { - let mut a: SmallVec<[u8; 2]> = SmallVec::new(); - a.push(1); - a.push(2); - a.push(3); - - let mut b: SmallVec<[u8; 2]> = SmallVec::new(); - b.push(10); - - let mut c: SmallVec<[u8; 2]> = SmallVec::new(); - c.push(20); - c.push(21); - c.push(22); - - a.clone_from(&b); - assert_eq!(&*a, &[10]); - - b.clone_from(&c); - assert_eq!(&*b, &[20, 21, 22]); -} - -#[test] -fn test_size() { - use core::mem::size_of; - assert_eq!(24, size_of::<SmallVec<[u8; 8]>>()); -} - -#[cfg(feature = "drain_filter")] -#[test] -fn drain_filter() { - let mut a: SmallVec<[u8; 2]> = smallvec![1u8, 2, 3, 4, 5, 6, 7, 8]; - - let b: SmallVec<[u8; 2]> = a.drain_filter(|x| *x % 3 == 0).collect(); - - assert_eq!(a, SmallVec::<[u8; 2]>::from_slice(&[1u8, 2, 4, 5, 7, 8])); - assert_eq!(b, SmallVec::<[u8; 2]>::from_slice(&[3u8, 6])); -} - -#[cfg(feature = "drain_keep_rest")] -#[test] -fn drain_keep_rest() { - let mut a: SmallVec<[i32; 3]> = smallvec![1i32, 2, 3, 4, 5, 6, 7, 8]; - let mut df = a.drain_filter(|x| *x % 2 == 0); - - assert_eq!(df.next().unwrap(), 2); - assert_eq!(df.next().unwrap(), 4); - - df.keep_rest(); - - assert_eq!(a, SmallVec::<[i32; 3]>::from_slice(&[1i32, 3, 5, 6, 7, 8])); -} diff --git a/vendor/smallvec/tests/debugger_visualizer.rs b/vendor/smallvec/tests/debugger_visualizer.rs deleted file mode 100644 index b39aa9d..0000000 --- a/vendor/smallvec/tests/debugger_visualizer.rs +++ /dev/null @@ -1,68 +0,0 @@ -use debugger_test::debugger_test; -use smallvec::{smallvec, SmallVec}; - -#[inline(never)] -fn __break() {} - -#[debugger_test( - debugger = "cdb", - commands = r#" -.nvlist -dx sv - -g - -dx sv - -g - -dx sv -"#, - expected_statements = r#" -sv : { len=0x2 is_inline=true } [Type: smallvec::SmallVec<array$<i32,4> >] - [<Raw View>] [Type: smallvec::SmallVec<array$<i32,4> >] - [capacity] : 4 - [len] : 0x2 [Type: unsigned __int64] - [0] : 1 [Type: int] - [1] : 2 [Type: int] - -sv : { len=0x5 is_inline=false } [Type: smallvec::SmallVec<array$<i32,4> >] - [<Raw View>] [Type: smallvec::SmallVec<array$<i32,4> >] - [capacity] : 0x8 [Type: unsigned __int64] - [len] : 0x5 [Type: unsigned __int64] - [0] : 5 [Type: int] - [1] : 2 [Type: int] - [2] : 3 [Type: int] - [3] : 4 [Type: int] - [4] : 5 [Type: int] - -sv : { len=0x5 is_inline=false } [Type: smallvec::SmallVec<array$<i32,4> >] - [<Raw View>] [Type: smallvec::SmallVec<array$<i32,4> >] - [capacity] : 0x8 [Type: unsigned __int64] - [len] : 0x5 [Type: unsigned __int64] - [0] : 2 [Type: int] - [1] : 3 [Type: int] - [2] : 4 [Type: int] - [3] : 5 [Type: int] - [4] : 5 [Type: int] -"# -)] -#[inline(never)] -fn test_debugger_visualizer() { - // This SmallVec can hold up to 4 items on the stack: - let mut sv: SmallVec<[i32; 4]> = smallvec![1, 2]; - __break(); - - // Overfill the SmallVec to move its contents to the heap - for i in 3..6 { - sv.push(i); - } - - // Update the contents of the first value of the SmallVec. - sv[0] = sv[1] + sv[2]; - __break(); - - // Sort the SmallVec in place. - sv.sort(); - __break(); -} diff --git a/vendor/smallvec/tests/macro.rs b/vendor/smallvec/tests/macro.rs deleted file mode 100644 index fa52e79..0000000 --- a/vendor/smallvec/tests/macro.rs +++ /dev/null @@ -1,24 +0,0 @@ -/// This file tests `smallvec!` without actually having the macro in scope. -/// This forces any recursion to use a `$crate` prefix to reliably find itself. - -#[test] -fn smallvec() { - let mut vec: smallvec::SmallVec<[i32; 2]>; - - macro_rules! check { - ($init:tt) => { - vec = smallvec::smallvec! $init; - assert_eq!(*vec, *vec! $init); - } - } - - check!([0; 0]); - check!([1; 1]); - check!([2; 2]); - check!([3; 3]); - - check!([]); - check!([1]); - check!([1, 2]); - check!([1, 2, 3]); -} |