├── .github └── workflows │ └── ci.yml ├── .gitignore ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── build.rs └── src ├── lib.rs └── serde_support.rs /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | pull_request: 6 | workflow_dispatch: 7 | schedule: 8 | - cron: '0 0 1 * *' # Monthly 9 | 10 | jobs: 11 | build: 12 | strategy: 13 | fail-fast: false 14 | 15 | matrix: 16 | label: 17 | - Linux 18 | - Windows 19 | - macOS 20 | 21 | rust: 22 | # Should be 1.17.0, but the cargo registry broke backwards compatibility: 23 | # https://github.com/rust-lang/cargo/issues/14237 24 | # 25 | # It's possible to build on 1.17.0 by removing all serde dependencies and features. 26 | - 1.19.0 27 | - stable 28 | - beta 29 | 30 | include: 31 | - label: Linux 32 | os: ubuntu-24.04 33 | 34 | - label: Windows 35 | os: windows-2022 36 | 37 | - label: macOS 38 | os: macOS-14 39 | 40 | exclude: 41 | # aarch64 doesn't exist for Rust this old. 42 | - label: macOS 43 | rust: 1.19.0 44 | 45 | name: test - ${{ matrix.rust }} - ${{ matrix.label }} 46 | runs-on: ${{ matrix.os }} 47 | 48 | steps: 49 | - uses: actions/checkout@v4 50 | with: 51 | show-progress: false 52 | 53 | - uses: dtolnay/rust-toolchain@master 54 | with: 55 | toolchain: ${{ matrix.rust }} 56 | 57 | - name: Build 58 | run: cargo build 59 | 60 | - name: Test 61 | run: cargo test 62 | 63 | - name: Build (serde_support) 64 | if: matrix.rust != '1.19.0' 65 | run: cargo build --features serde_support 66 | 67 | - name: Test (serde_support) 68 | if: matrix.rust != '1.19.0' 69 | run: cargo test --features serde_support 70 | 71 | - name: Build (serde_support_test) 72 | if: matrix.rust != '1.19.0' 73 | run: cargo build --features serde_support_test 74 | 75 | - name: Test (serde_support_test) 76 | if: matrix.rust != '1.19.0' 77 | run: cargo test --features serde_support_test 78 | 79 | clippy: 80 | runs-on: ubuntu-24.04 81 | 82 | steps: 83 | - uses: actions/checkout@v4 84 | with: 85 | show-progress: false 86 | 87 | - uses: dtolnay/rust-toolchain@stable 88 | with: 89 | components: clippy 90 | 91 | - name: Run clippy 92 | run: cargo clippy --all --all-targets 93 | 94 | rustfmt: 95 | runs-on: ubuntu-24.04 96 | 97 | steps: 98 | - uses: actions/checkout@v4 99 | with: 100 | show-progress: false 101 | 102 | - uses: dtolnay/rust-toolchain@stable 103 | with: 104 | components: rustfmt 105 | 106 | - name: Run rustfmt 107 | run: cargo fmt --all -- --check 108 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | **/*.rs.bk 3 | Cargo.lock 4 | .idea 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## [Unreleased] 4 | 5 | ## [0.2.7] - 2025-03-14 6 | 7 | ### Added 8 | - `CircularQueue::into_vec()` for converting into a `Vec` without extra allocations. 9 | - A corresponding `From` impl. 10 | 11 | ### Fixed 12 | - Warnings on newer Rust versions. 13 | 14 | ## [0.2.6] - 2020-07-27 15 | 16 | ### Added 17 | - `CircularQueue::is_full()` for checking whether the queue is completely filled. 18 | 19 | ### Changed 20 | - `CircularQueue::push()` now returns the element it overwrites, if any. 21 | 22 | ## [0.2.5] - 2020-06-21 23 | 24 | ### Added 25 | - Serde support under the `serde_support` feature. 26 | 27 | ## [0.2.4] - 2020-03-26 28 | 29 | ### Changed 30 | - `CircularQueue::with_capacity()` now accepts zero capacity without panicking. 31 | 32 | ## [0.2.3] - 2020-01-09 33 | 34 | ### Added 35 | - `CircularQueue::asc_iter()` and `asc_iter_mut()` for iterating over the queue 36 | items in oldest-to-newest order. 37 | - Marked `CircularQueue::push()` as `#[inline]`. 38 | 39 | ## [0.2.2] - 2019-09-01 40 | 41 | ### Added 42 | - `PartialEq` and `Eq` implementations for `CircularQueue`. 43 | 44 | ## [0.2.1] - 2019-08-02 45 | 46 | ### Added 47 | - `#![no_std]` support on Rust >= `1.36.0`. 48 | 49 | ## [0.2.0] - 2017-07-24 50 | 51 | ### Added 52 | - `CircularQueue::is_empty()`. 53 | - Zero-sized type support. 54 | 55 | ### Changed 56 | - Renamed `CircularQueue::new()` to `with_capacity()`. 57 | 58 | ## [0.1.2] - 2017-07-21 59 | 60 | ### Added 61 | - `CircularQueue::iter_mut()`. 62 | 63 | [Unreleased]: https://github.com/YaLTeR/circular-queue/compare/v0.2.7...HEAD 64 | [0.2.7]: https://github.com/YaLTeR/circular-queue/compare/v0.2.6...v0.2.7 65 | [0.2.6]: https://github.com/YaLTeR/circular-queue/compare/v0.2.5...v0.2.6 66 | [0.2.5]: https://github.com/YaLTeR/circular-queue/compare/v0.2.4...v0.2.5 67 | [0.2.4]: https://github.com/YaLTeR/circular-queue/compare/v0.2.3...v0.2.4 68 | [0.2.3]: https://github.com/YaLTeR/circular-queue/compare/v0.2.2...v0.2.3 69 | [0.2.2]: https://github.com/YaLTeR/circular-queue/compare/v0.2.1...v0.2.2 70 | [0.2.1]: https://github.com/YaLTeR/circular-queue/compare/v0.2.0...v0.2.1 71 | [0.2.0]: https://github.com/YaLTeR/circular-queue/compare/v0.1.2...v0.2.0 72 | [0.1.2]: https://github.com/YaLTeR/circular-queue/compare/v0.1.1...v0.1.2 73 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "circular-queue" 3 | version = "0.2.7" # remember to update html_root_url 4 | authors = ["Ivan Molodetskikh "] 5 | description = "A circular buffer-like queue." 6 | license = "MIT/Apache-2.0" 7 | build = "build.rs" 8 | edition = "2015" 9 | 10 | readme = "README.md" 11 | documentation = "https://docs.rs/circular-queue" 12 | repository = "https://github.com/YaLTeR/circular-queue" 13 | keywords = ["circular", "buffer", "ring", "queue", "container"] 14 | categories = ["data-structures"] 15 | 16 | [build-dependencies] 17 | version_check = "0.9" 18 | 19 | [features] 20 | default = [] 21 | serde_support = ["serde"] 22 | serde_support_test = ["serde_support", "serde_test", "serde_json", "bincode"] 23 | 24 | [dependencies] 25 | serde = {version = "1.0", optional = true, features = ["derive"]} 26 | serde_test = {version = "1.0", optional = true} 27 | serde_json = {version = "1.0", optional = true} 28 | bincode = {version = "1.2.1", optional = true} 29 | 30 | [package.metadata.docs.rs] 31 | features = ["serde_support"] 32 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017-2019 Ivan Molodetskikh 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # circular-queue 2 | 3 | [![crates.io](https://img.shields.io/crates/v/circular-queue.svg)](https://crates.io/crates/circular-queue) 4 | [![Documentation](https://docs.rs/circular-queue/badge.svg)](https://docs.rs/circular-queue) 5 | 6 | A circular buffer-like queue container. Created with a set capacity. When pushing new items over capacity, old ones get overwritten. Supports iteration in newest to oldest and in oldest to newest order. 7 | 8 | ## License 9 | 10 | Licensed under either of 11 | 12 | * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) 13 | * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) 14 | 15 | at your option. 16 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | extern crate version_check; 2 | 3 | fn main() { 4 | println!("cargo:rustc-check-cfg=cfg(has_extern_crate_alloc)"); 5 | if version_check::is_min_version("1.36.0").unwrap_or(false) { 6 | println!("cargo:rustc-cfg=has_extern_crate_alloc"); 7 | } 8 | 9 | println!("cargo:rustc-check-cfg=cfg(has_relaxed_orphan_rule)"); 10 | if version_check::is_min_version("1.41.0").unwrap_or(false) { 11 | println!("cargo:rustc-cfg=has_relaxed_orphan_rule"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! A circular buffer-like queue. 2 | //! 3 | //! The `CircularQueue` is created with a set capacity, then items are pushed in. When the queue 4 | //! runs out of capacity, newer items start overwriting the old ones, starting from the oldest. 5 | //! 6 | //! There are built-in iterators that go from the newest items to the oldest ones and from the 7 | //! oldest items to the newest ones. 8 | //! 9 | //! Two queues are considered equal if iterating over them with `iter()` would yield the same 10 | //! sequence of elements. 11 | //! 12 | //! Enable the `serde_support` feature for [Serde](https://serde.rs/) support. 13 | //! 14 | //! # Examples 15 | //! 16 | //! ``` 17 | //! use circular_queue::CircularQueue; 18 | //! 19 | //! let mut queue = CircularQueue::with_capacity(3); 20 | //! queue.push(1); 21 | //! queue.push(2); 22 | //! queue.push(3); 23 | //! queue.push(4); 24 | //! 25 | //! assert_eq!(queue.len(), 3); 26 | //! 27 | //! let mut iter = queue.iter(); 28 | //! 29 | //! assert_eq!(iter.next(), Some(&4)); 30 | //! assert_eq!(iter.next(), Some(&3)); 31 | //! assert_eq!(iter.next(), Some(&2)); 32 | //! ``` 33 | 34 | #![cfg_attr(has_extern_crate_alloc, no_std)] 35 | #![doc(html_root_url = "https://docs.rs/circular-queue/0.2.7")] 36 | 37 | #[cfg(has_extern_crate_alloc)] 38 | extern crate alloc; 39 | 40 | #[cfg(has_extern_crate_alloc)] 41 | use alloc::vec::Vec; 42 | #[cfg(has_extern_crate_alloc)] 43 | use core::iter::{Chain, Rev}; 44 | #[cfg(has_extern_crate_alloc)] 45 | use core::mem::replace; 46 | #[cfg(has_extern_crate_alloc)] 47 | use core::slice::{Iter as SliceIter, IterMut as SliceIterMut}; 48 | 49 | #[cfg(not(has_extern_crate_alloc))] 50 | use std::iter::{Chain, Rev}; 51 | #[cfg(not(has_extern_crate_alloc))] 52 | use std::mem::replace; 53 | #[cfg(not(has_extern_crate_alloc))] 54 | use std::slice::{Iter as SliceIter, IterMut as SliceIterMut}; 55 | 56 | #[cfg(feature = "serde_support")] 57 | mod serde_support; 58 | 59 | /// A circular buffer-like queue. 60 | #[derive(Clone, Debug)] 61 | pub struct CircularQueue { 62 | data: Vec, 63 | // Using our own capacity instead of the one stored in Vec to ensure consistent behavior with 64 | // zero-sized types. 65 | capacity: usize, 66 | insertion_index: usize, 67 | } 68 | 69 | /// An iterator over `CircularQueue`. 70 | pub type Iter<'a, T> = Chain>, Rev>>; 71 | 72 | /// A mutable iterator over `CircularQueue`. 73 | pub type IterMut<'a, T> = Chain>, Rev>>; 74 | 75 | /// An ascending iterator over `CircularQueue`. 76 | pub type AscIter<'a, T> = Chain, SliceIter<'a, T>>; 77 | 78 | /// An mutable ascending iterator over `CircularQueue`. 79 | pub type AscIterMut<'a, T> = Chain, SliceIterMut<'a, T>>; 80 | 81 | /// A value popped from `CircularQueue` as the result of a push operation. 82 | pub type Popped = Option; 83 | 84 | impl CircularQueue { 85 | /// Constructs a new, empty `CircularQueue` with the requested capacity. 86 | /// 87 | /// # Examples 88 | /// 89 | /// ``` 90 | /// use circular_queue::CircularQueue; 91 | /// 92 | /// let mut queue: CircularQueue = CircularQueue::with_capacity(5); 93 | /// ``` 94 | #[inline] 95 | pub fn with_capacity(capacity: usize) -> Self { 96 | Self { 97 | data: Vec::with_capacity(capacity), 98 | capacity, 99 | insertion_index: 0, 100 | } 101 | } 102 | 103 | /// Returns the current number of elements in the queue. 104 | /// 105 | /// # Examples 106 | /// 107 | /// ``` 108 | /// use circular_queue::CircularQueue; 109 | /// 110 | /// let mut queue = CircularQueue::with_capacity(5); 111 | /// queue.push(1); 112 | /// queue.push(2); 113 | /// queue.push(3); 114 | /// 115 | /// assert_eq!(queue.len(), 3); 116 | /// ``` 117 | #[inline] 118 | pub fn len(&self) -> usize { 119 | self.data.len() 120 | } 121 | 122 | /// Returns `true` if the queue contains no elements. 123 | /// 124 | /// # Examples 125 | /// 126 | /// ``` 127 | /// use circular_queue::CircularQueue; 128 | /// 129 | /// let mut queue = CircularQueue::with_capacity(5); 130 | /// assert!(queue.is_empty()); 131 | /// 132 | /// queue.push(1); 133 | /// assert!(!queue.is_empty()); 134 | /// ``` 135 | #[inline] 136 | pub fn is_empty(&self) -> bool { 137 | self.data.is_empty() 138 | } 139 | 140 | /// Returns `true` if the queue is full. 141 | /// 142 | /// # Examples 143 | /// 144 | /// ``` 145 | /// use circular_queue::CircularQueue; 146 | /// 147 | /// let mut queue = CircularQueue::with_capacity(5); 148 | /// 149 | /// assert!(!queue.is_full()); 150 | /// 151 | /// queue.push(1); 152 | /// queue.push(2); 153 | /// queue.push(3); 154 | /// queue.push(4); 155 | /// queue.push(5); 156 | /// 157 | /// assert!(queue.is_full()); 158 | /// ``` 159 | #[inline] 160 | pub fn is_full(&self) -> bool { 161 | self.capacity() == self.len() 162 | } 163 | 164 | /// Returns the capacity of the queue. 165 | /// 166 | /// # Examples 167 | /// 168 | /// ``` 169 | /// use circular_queue::CircularQueue; 170 | /// 171 | /// let queue: CircularQueue = CircularQueue::with_capacity(5); 172 | /// assert_eq!(queue.capacity(), 5); 173 | /// ``` 174 | #[inline] 175 | pub fn capacity(&self) -> usize { 176 | self.capacity 177 | } 178 | 179 | /// Clears the queue. 180 | /// 181 | /// # Examples 182 | /// 183 | /// ``` 184 | /// use circular_queue::CircularQueue; 185 | /// 186 | /// let mut queue = CircularQueue::with_capacity(5); 187 | /// queue.push(1); 188 | /// queue.push(2); 189 | /// queue.push(3); 190 | /// 191 | /// queue.clear(); 192 | /// assert_eq!(queue.len(), 0); 193 | /// ``` 194 | #[inline] 195 | pub fn clear(&mut self) { 196 | self.data.clear(); 197 | self.insertion_index = 0; 198 | } 199 | 200 | /// Pushes a new element into the queue. 201 | /// 202 | /// Once the capacity is reached, pushing new items will overwrite old ones. 203 | /// 204 | /// In case an old value is overwritten, it will be returned. 205 | /// 206 | /// # Examples 207 | /// 208 | /// ``` 209 | /// use circular_queue::CircularQueue; 210 | /// 211 | /// let mut queue = CircularQueue::with_capacity(3); 212 | /// 213 | /// queue.push(1); 214 | /// queue.push(2); 215 | /// 216 | /// assert_eq!(queue.push(3), None); 217 | /// assert_eq!(queue.push(4), Some(1)); 218 | /// 219 | /// assert_eq!(queue.len(), 3); 220 | /// 221 | /// let mut iter = queue.iter(); 222 | /// 223 | /// assert_eq!(iter.next(), Some(&4)); 224 | /// assert_eq!(iter.next(), Some(&3)); 225 | /// assert_eq!(iter.next(), Some(&2)); 226 | /// ``` 227 | #[inline] 228 | pub fn push(&mut self, x: T) -> Popped { 229 | let mut old = None; 230 | 231 | if self.capacity() == 0 { 232 | return old; 233 | } 234 | 235 | if !self.is_full() { 236 | self.data.push(x); 237 | } else { 238 | old = Some(replace(&mut self.data[self.insertion_index], x)); 239 | } 240 | 241 | self.insertion_index = (self.insertion_index + 1) % self.capacity(); 242 | 243 | old 244 | } 245 | 246 | /// Returns an iterator over the queue's contents. 247 | /// 248 | /// The iterator goes from the most recently pushed items to the oldest ones. 249 | /// 250 | /// # Examples 251 | /// 252 | /// ``` 253 | /// use circular_queue::CircularQueue; 254 | /// 255 | /// let mut queue = CircularQueue::with_capacity(3); 256 | /// queue.push(1); 257 | /// queue.push(2); 258 | /// queue.push(3); 259 | /// queue.push(4); 260 | /// 261 | /// let mut iter = queue.iter(); 262 | /// 263 | /// assert_eq!(iter.next(), Some(&4)); 264 | /// assert_eq!(iter.next(), Some(&3)); 265 | /// assert_eq!(iter.next(), Some(&2)); 266 | /// ``` 267 | #[inline] 268 | pub fn iter(&self) -> Iter { 269 | let (a, b) = self.data.split_at(self.insertion_index); 270 | a.iter().rev().chain(b.iter().rev()) 271 | } 272 | 273 | /// Returns a mutable iterator over the queue's contents. 274 | /// 275 | /// The iterator goes from the most recently pushed items to the oldest ones. 276 | /// 277 | /// # Examples 278 | /// 279 | /// ``` 280 | /// use circular_queue::CircularQueue; 281 | /// 282 | /// let mut queue = CircularQueue::with_capacity(3); 283 | /// queue.push(1); 284 | /// queue.push(2); 285 | /// queue.push(3); 286 | /// queue.push(4); 287 | /// 288 | /// let mut iter = queue.iter_mut(); 289 | /// 290 | /// assert_eq!(iter.next(), Some(&mut 4)); 291 | /// assert_eq!(iter.next(), Some(&mut 3)); 292 | /// assert_eq!(iter.next(), Some(&mut 2)); 293 | /// ``` 294 | #[inline] 295 | pub fn iter_mut(&mut self) -> IterMut { 296 | let (a, b) = self.data.split_at_mut(self.insertion_index); 297 | a.iter_mut().rev().chain(b.iter_mut().rev()) 298 | } 299 | 300 | /// Returns an ascending iterator over the queue's contents. 301 | /// 302 | /// The iterator goes from the least recently pushed items to the newest ones. 303 | /// 304 | /// # Examples 305 | /// 306 | /// ``` 307 | /// use circular_queue::CircularQueue; 308 | /// 309 | /// let mut queue = CircularQueue::with_capacity(3); 310 | /// queue.push(1); 311 | /// queue.push(2); 312 | /// queue.push(3); 313 | /// queue.push(4); 314 | /// 315 | /// let mut iter = queue.asc_iter(); 316 | /// 317 | /// assert_eq!(iter.next(), Some(&2)); 318 | /// assert_eq!(iter.next(), Some(&3)); 319 | /// assert_eq!(iter.next(), Some(&4)); 320 | /// ``` 321 | #[inline] 322 | pub fn asc_iter(&self) -> AscIter { 323 | let (a, b) = self.data.split_at(self.insertion_index); 324 | b.iter().chain(a.iter()) 325 | } 326 | 327 | /// Returns a mutable ascending iterator over the queue's contents. 328 | /// 329 | /// The iterator goes from the least recently pushed items to the newest ones. 330 | /// 331 | /// # Examples 332 | /// 333 | /// ``` 334 | /// use circular_queue::CircularQueue; 335 | /// 336 | /// let mut queue = CircularQueue::with_capacity(3); 337 | /// queue.push(1); 338 | /// queue.push(2); 339 | /// queue.push(3); 340 | /// queue.push(4); 341 | /// 342 | /// let mut iter = queue.asc_iter_mut(); 343 | /// 344 | /// assert_eq!(iter.next(), Some(&mut 2)); 345 | /// assert_eq!(iter.next(), Some(&mut 3)); 346 | /// assert_eq!(iter.next(), Some(&mut 4)); 347 | /// ``` 348 | #[inline] 349 | pub fn asc_iter_mut(&mut self) -> AscIterMut { 350 | let (a, b) = self.data.split_at_mut(self.insertion_index); 351 | b.iter_mut().chain(a.iter_mut()) 352 | } 353 | 354 | /// Converts the queue into a `Vec` going from the most recently pushed items to the oldest 355 | /// ones. 356 | /// 357 | /// # Examples 358 | /// 359 | /// ``` 360 | /// use circular_queue::CircularQueue; 361 | /// 362 | /// let mut queue = CircularQueue::with_capacity(3); 363 | /// queue.push(1); 364 | /// queue.push(2); 365 | /// queue.push(3); 366 | /// queue.push(4); 367 | /// 368 | /// let v = queue.into_vec(); 369 | /// 370 | /// assert_eq!(v, vec![4, 3, 2]); 371 | /// ``` 372 | #[inline] 373 | pub fn into_vec(mut self) -> Vec { 374 | self.data[self.insertion_index..].reverse(); // Reverse the upper part. 375 | self.data[..self.insertion_index].reverse(); // Reverse the lower part. 376 | self.data 377 | } 378 | } 379 | 380 | impl PartialEq for CircularQueue { 381 | #[inline] 382 | fn eq(&self, other: &CircularQueue) -> bool { 383 | self.len() == other.len() && self.iter().zip(other.iter()).all(|(a, b)| a == b) 384 | } 385 | } 386 | 387 | impl Eq for CircularQueue {} 388 | 389 | #[cfg(has_relaxed_orphan_rule)] 390 | impl From> for Vec { 391 | #[inline] 392 | fn from(queue: CircularQueue) -> Self { 393 | queue.into_vec() 394 | } 395 | } 396 | 397 | #[cfg(test)] 398 | mod tests { 399 | use super::*; 400 | #[cfg(has_extern_crate_alloc)] 401 | use alloc::vec; 402 | 403 | #[test] 404 | fn zero_capacity() { 405 | let mut q = CircularQueue::::with_capacity(0); 406 | assert_eq!(q.len(), 0); 407 | assert_eq!(q.capacity(), 0); 408 | assert!(q.is_empty()); 409 | 410 | q.push(3); 411 | q.push(4); 412 | q.push(5); 413 | 414 | assert_eq!(q.len(), 0); 415 | assert_eq!(q.capacity(), 0); 416 | assert!(q.is_empty()); 417 | 418 | assert_eq!(q.iter().count(), 0); 419 | assert_eq!(q.asc_iter().count(), 0); 420 | 421 | q.clear(); 422 | } 423 | 424 | #[test] 425 | fn empty_queue() { 426 | let q = CircularQueue::::with_capacity(5); 427 | 428 | assert!(q.is_empty()); 429 | assert_eq!(q.iter().next(), None); 430 | } 431 | 432 | #[test] 433 | fn partially_full_queue() { 434 | let mut q = CircularQueue::with_capacity(5); 435 | q.push(1); 436 | q.push(2); 437 | q.push(3); 438 | 439 | assert!(!q.is_empty()); 440 | assert_eq!(q.len(), 3); 441 | 442 | let res: Vec<_> = q.iter().map(|&x| x).collect(); 443 | assert_eq!(res, [3, 2, 1]); 444 | } 445 | 446 | #[test] 447 | fn full_queue() { 448 | let mut q = CircularQueue::with_capacity(5); 449 | q.push(1); 450 | q.push(2); 451 | q.push(3); 452 | q.push(4); 453 | q.push(5); 454 | 455 | assert_eq!(q.len(), 5); 456 | 457 | let res: Vec<_> = q.iter().map(|&x| x).collect(); 458 | assert_eq!(res, [5, 4, 3, 2, 1]); 459 | } 460 | 461 | #[test] 462 | fn over_full_queue() { 463 | let mut q = CircularQueue::with_capacity(5); 464 | q.push(1); 465 | q.push(2); 466 | q.push(3); 467 | q.push(4); 468 | q.push(5); 469 | q.push(6); 470 | q.push(7); 471 | 472 | assert_eq!(q.len(), 5); 473 | 474 | let res: Vec<_> = q.iter().map(|&x| x).collect(); 475 | assert_eq!(res, [7, 6, 5, 4, 3]); 476 | } 477 | 478 | #[test] 479 | fn clear() { 480 | let mut q = CircularQueue::with_capacity(5); 481 | q.push(1); 482 | q.push(2); 483 | q.push(3); 484 | q.push(4); 485 | q.push(5); 486 | q.push(6); 487 | q.push(7); 488 | 489 | q.clear(); 490 | 491 | assert_eq!(q.len(), 0); 492 | assert_eq!(q.iter().next(), None); 493 | 494 | q.push(1); 495 | q.push(2); 496 | q.push(3); 497 | 498 | assert_eq!(q.len(), 3); 499 | 500 | let res: Vec<_> = q.iter().map(|&x| x).collect(); 501 | assert_eq!(res, [3, 2, 1]); 502 | } 503 | 504 | #[test] 505 | fn mutable_iterator() { 506 | let mut q = CircularQueue::with_capacity(5); 507 | q.push(1); 508 | q.push(2); 509 | q.push(3); 510 | q.push(4); 511 | q.push(5); 512 | q.push(6); 513 | q.push(7); 514 | 515 | for x in q.iter_mut() { 516 | *x *= 2; 517 | } 518 | 519 | let res: Vec<_> = q.iter().map(|&x| x).collect(); 520 | assert_eq!(res, [14, 12, 10, 8, 6]); 521 | } 522 | 523 | #[test] 524 | fn zero_sized() { 525 | let mut q = CircularQueue::with_capacity(3); 526 | assert_eq!(q.capacity(), 3); 527 | 528 | q.push(()); 529 | q.push(()); 530 | q.push(()); 531 | q.push(()); 532 | 533 | assert_eq!(q.len(), 3); 534 | 535 | let mut iter = q.iter(); 536 | assert_eq!(iter.next(), Some(&())); 537 | assert_eq!(iter.next(), Some(&())); 538 | assert_eq!(iter.next(), Some(&())); 539 | assert_eq!(iter.next(), None); 540 | } 541 | 542 | #[test] 543 | fn empty_queue_eq() { 544 | let q1 = CircularQueue::::with_capacity(5); 545 | let q2 = CircularQueue::::with_capacity(5); 546 | assert_eq!(q1, q2); 547 | 548 | let q3 = CircularQueue::::with_capacity(6); 549 | assert_eq!(q1, q3); // Capacity doesn't matter as long as the same elements are yielded. 550 | } 551 | 552 | #[test] 553 | fn partially_full_queue_eq() { 554 | let mut q1 = CircularQueue::with_capacity(5); 555 | q1.push(1); 556 | q1.push(2); 557 | q1.push(3); 558 | 559 | let mut q2 = CircularQueue::with_capacity(5); 560 | q2.push(1); 561 | q2.push(2); 562 | assert_ne!(q1, q2); 563 | 564 | q2.push(3); 565 | assert_eq!(q1, q2); 566 | 567 | q2.push(4); 568 | assert_ne!(q1, q2); 569 | } 570 | 571 | #[test] 572 | fn full_queue_eq() { 573 | let mut q1 = CircularQueue::with_capacity(5); 574 | q1.push(1); 575 | q1.push(2); 576 | q1.push(3); 577 | q1.push(4); 578 | q1.push(5); 579 | 580 | let mut q2 = CircularQueue::with_capacity(5); 581 | q2.push(1); 582 | q2.push(2); 583 | q2.push(3); 584 | q2.push(4); 585 | q2.push(5); 586 | 587 | assert_eq!(q1, q2); 588 | } 589 | 590 | #[test] 591 | fn over_full_queue_eq() { 592 | let mut q1 = CircularQueue::with_capacity(5); 593 | q1.push(1); 594 | q1.push(2); 595 | q1.push(3); 596 | q1.push(4); 597 | q1.push(5); 598 | q1.push(6); 599 | q1.push(7); 600 | 601 | let mut q2 = CircularQueue::with_capacity(5); 602 | q2.push(1); 603 | q2.push(2); 604 | q2.push(3); 605 | q2.push(4); 606 | q2.push(5); 607 | q2.push(6); 608 | assert_ne!(q1, q2); 609 | 610 | q2.push(7); 611 | assert_eq!(q1, q2); 612 | 613 | q2.push(8); 614 | assert_ne!(q1, q2); 615 | 616 | q2.push(3); 617 | q2.push(4); 618 | q2.push(5); 619 | q2.push(6); 620 | q2.push(7); 621 | assert_eq!(q1, q2); 622 | } 623 | 624 | #[test] 625 | fn clear_eq() { 626 | let mut q1 = CircularQueue::with_capacity(5); 627 | q1.push(1); 628 | q1.push(2); 629 | q1.push(3); 630 | q1.push(4); 631 | q1.push(5); 632 | q1.push(6); 633 | q1.push(7); 634 | q1.clear(); 635 | 636 | let mut q2 = CircularQueue::with_capacity(5); 637 | assert_eq!(q1, q2); 638 | 639 | q2.push(1); 640 | q2.clear(); 641 | assert_eq!(q1, q2); 642 | } 643 | 644 | #[test] 645 | fn zero_sized_eq() { 646 | let mut q1 = CircularQueue::with_capacity(3); 647 | q1.push(()); 648 | q1.push(()); 649 | q1.push(()); 650 | q1.push(()); 651 | 652 | let mut q2 = CircularQueue::with_capacity(3); 653 | q2.push(()); 654 | q2.push(()); 655 | assert_ne!(q1, q2); 656 | 657 | q2.push(()); 658 | assert_eq!(q1, q2); 659 | 660 | q2.push(()); 661 | assert_eq!(q1, q2); 662 | 663 | q2.push(()); 664 | assert_eq!(q1, q2); 665 | } 666 | 667 | #[test] 668 | fn into_vec() { 669 | let mut q = CircularQueue::with_capacity(4); 670 | q.push(1); 671 | q.push(2); 672 | q.push(3); 673 | 674 | let v = q.clone().into_vec(); 675 | assert_eq!(v, vec![3, 2, 1]); 676 | 677 | q.push(4); 678 | q.push(5); 679 | let v = q.clone().into_vec(); 680 | assert_eq!(v, vec![5, 4, 3, 2]); 681 | 682 | q.push(6); 683 | let v = q.into_vec(); 684 | assert_eq!(v, vec![6, 5, 4, 3]); 685 | } 686 | 687 | #[cfg(has_relaxed_orphan_rule)] 688 | #[test] 689 | fn vec_from() { 690 | let mut q = CircularQueue::with_capacity(3); 691 | q.push(1); 692 | q.push(2); 693 | q.push(3); 694 | q.push(4); 695 | 696 | let v = Vec::from(q); 697 | assert_eq!(v, vec![4, 3, 2]); 698 | } 699 | } 700 | -------------------------------------------------------------------------------- /src/serde_support.rs: -------------------------------------------------------------------------------- 1 | extern crate serde; 2 | 3 | use super::*; 4 | 5 | use self::serde::ser::{Serialize, SerializeSeq, SerializeStruct, Serializer}; 6 | use self::serde::{Deserialize, Deserializer}; 7 | 8 | /// Struct used to hold the iterator over the data for serialization 9 | struct CircularQueueSerialize<'a, T> { 10 | length: usize, 11 | values: AscIter<'a, T>, 12 | } 13 | 14 | impl<'a, T> Serialize for CircularQueueSerialize<'a, T> 15 | where 16 | T: Serialize, 17 | { 18 | fn serialize(&self, serializer: S) -> Result 19 | where 20 | S: Serializer, 21 | { 22 | let mut seq = serializer.serialize_seq(Some(self.length))?; 23 | for e in self.values.clone() { 24 | seq.serialize_element(e)?; 25 | } 26 | seq.end() 27 | } 28 | } 29 | 30 | impl Serialize for CircularQueue 31 | where 32 | T: Serialize, 33 | { 34 | fn serialize(&self, serializer: S) -> Result 35 | where 36 | S: Serializer, 37 | { 38 | let to_ser = CircularQueueSerialize { 39 | length: self.len(), 40 | values: self.asc_iter(), 41 | }; 42 | 43 | let mut seq = serializer.serialize_struct("CircularQueueData", 2)?; 44 | seq.serialize_field("capacity", &self.capacity)?; 45 | seq.serialize_field("values", &to_ser)?; 46 | seq.end() 47 | } 48 | } 49 | 50 | #[derive(Deserialize)] 51 | struct CircularQueueData { 52 | capacity: usize, 53 | values: Vec, 54 | } 55 | 56 | impl<'de, T> Deserialize<'de> for CircularQueue 57 | where 58 | T: Deserialize<'de>, 59 | { 60 | fn deserialize(deserializer: D) -> Result, D::Error> 61 | where 62 | D: Deserializer<'de>, 63 | { 64 | let data = CircularQueueData::deserialize(deserializer)?; 65 | let mut queue = CircularQueue::with_capacity(data.capacity); 66 | for elem in data.values { 67 | queue.push(elem); 68 | } 69 | Ok(queue) 70 | } 71 | } 72 | 73 | #[cfg(feature = "serde_support_test")] 74 | #[cfg(test)] 75 | mod tests { 76 | use super::*; 77 | extern crate bincode; 78 | extern crate serde_json; 79 | extern crate serde_test; 80 | 81 | use self::serde_test::{assert_tokens, Token}; 82 | 83 | #[test] 84 | fn serialization_works() { 85 | let mut q = CircularQueue::with_capacity(8); 86 | q.push(1); 87 | q.push(2); 88 | 89 | assert_tokens( 90 | &q, 91 | &[ 92 | Token::Struct { 93 | name: "CircularQueueData", 94 | len: 2, 95 | }, 96 | Token::Str("capacity"), 97 | Token::U64(8), 98 | Token::Str("values"), 99 | Token::Seq { len: Some(2) }, 100 | Token::I32(1), 101 | Token::I32(2), 102 | Token::SeqEnd, 103 | Token::StructEnd, 104 | ], 105 | ); 106 | } 107 | 108 | #[test] 109 | fn serialization_with_empty_queue() { 110 | let q = CircularQueue::<()>::with_capacity(0); 111 | 112 | assert_tokens( 113 | &q, 114 | &[ 115 | Token::Struct { 116 | name: "CircularQueueData", 117 | len: 2, 118 | }, 119 | Token::Str("capacity"), 120 | Token::U64(0), 121 | Token::Str("values"), 122 | Token::Seq { len: Some(0) }, 123 | Token::SeqEnd, 124 | Token::StructEnd, 125 | ], 126 | ); 127 | } 128 | 129 | #[test] 130 | fn serialization_preserves_order() { 131 | let mut q = CircularQueue::with_capacity(4); 132 | // Fill the q 133 | for i in 0..4 { 134 | q.push(i); 135 | } 136 | // Add a couple of new values 137 | q.push(4); 138 | q.push(5); 139 | // At this point, the queue should be [2, 3, 4, 5] 140 | 141 | assert_tokens( 142 | &q, 143 | &[ 144 | Token::Struct { 145 | name: "CircularQueueData", 146 | len: 2, 147 | }, 148 | Token::Str("capacity"), 149 | Token::U64(4), 150 | Token::Str("values"), 151 | Token::Seq { len: Some(4) }, 152 | Token::I32(2), 153 | Token::I32(3), 154 | Token::I32(4), 155 | Token::I32(5), 156 | Token::SeqEnd, 157 | Token::StructEnd, 158 | ], 159 | ); 160 | } 161 | 162 | #[test] 163 | fn serialization_to_json() { 164 | let mut q = CircularQueue::with_capacity(4); 165 | q.push(3); 166 | q.push(7); 167 | assert_eq!( 168 | serde_json::to_string(&q).unwrap(), 169 | r#"{"capacity":4,"values":[3,7]}"# 170 | ); 171 | } 172 | 173 | #[test] 174 | fn serialization_from_json() { 175 | let mut q = CircularQueue::with_capacity(4); 176 | q.push(3); 177 | q.push(7); 178 | let p = 179 | serde_json::from_str::>(r#"{"capacity":4,"values":[3,7]}"#).unwrap(); 180 | assert_eq!(p, q); 181 | } 182 | 183 | #[test] 184 | fn serialization_from_json_empty() { 185 | let q = CircularQueue::with_capacity(4); 186 | let p = 187 | serde_json::from_str::>(r#"{"capacity":4,"values":[]}"#).unwrap(); 188 | assert_eq!(p, q); 189 | } 190 | 191 | #[test] 192 | fn serialization_to_bincode() { 193 | let mut q = CircularQueue::with_capacity(4); 194 | q.push(3); 195 | q.push(9); 196 | let v = bincode::serialize(&q).unwrap(); 197 | let p = bincode::deserialize::>(&v).unwrap(); 198 | assert_eq!(p, q); 199 | } 200 | 201 | #[test] 202 | fn serialization_with_oversized_vector_preserves_last_values() { 203 | let mut q = CircularQueue::with_capacity(2); 204 | q.push(7); 205 | q.push(8); 206 | let oversize = 207 | serde_json::from_str::>(r#"{"capacity":2,"values":[3,7,8]}"#) 208 | .unwrap(); 209 | assert_eq!(oversize, q); 210 | } 211 | } 212 | --------------------------------------------------------------------------------