├── .editorconfig ├── .github ├── dependabot.yml └── workflows │ └── ci.yaml ├── .gitignore ├── .scripts ├── all.sh ├── cl-aux.sh ├── common.sh ├── fuzz.sh ├── ndstruct.sh └── rust-tools.sh ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── cl-aux ├── Cargo.toml ├── LICENSE ├── README.md └── src │ ├── lib.rs │ ├── macros.rs │ ├── structures.rs │ ├── structures │ ├── array_wrapper.rs │ ├── array_wrapper_ref.rs │ ├── auto_clear.rs │ ├── doc_tests.rs │ ├── error.rs │ ├── full_auto_clear.rs │ ├── iter_wrapper.rs │ └── single_item_storage.rs │ ├── traits.rs │ ├── traits │ ├── capacity.rs │ ├── capacity_upper_bound.rs │ ├── clear.rs │ ├── dyn_contig_coll.rs │ ├── dyn_string.rs │ ├── extend.rs │ ├── get.rs │ ├── get_mut.rs │ ├── insert.rs │ ├── iter.rs │ ├── length.rs │ ├── push.rs │ ├── remove.rs │ ├── retain.rs │ ├── single_type_storage.rs │ ├── size_hint.rs │ ├── swap.rs │ ├── truncate.rs │ └── with_capacity.rs │ └── tuple_impls.rs ├── ndstruct-fuzz ├── Cargo.toml ├── coo.rs ├── csl.rs ├── random_coo.rs └── random_csl.rs ├── ndstruct ├── Cargo.toml ├── LICENSE ├── README.md └── src │ ├── coo.rs │ ├── coo │ ├── coo_error.rs │ └── coo_utils.rs │ ├── csl.rs │ ├── csl │ ├── csl_error.rs │ ├── csl_line_constructor.rs │ ├── csl_line_iter.rs │ ├── csl_rayon.rs │ ├── csl_rnd.rs │ └── csl_utils.rs │ ├── dense.rs │ ├── dense │ └── dense_error.rs │ ├── doc_tests.rs │ ├── error.rs │ ├── lib.rs │ └── utils.rs ├── rust-toolchain ├── rust-tools ├── Cargo.toml ├── LICENSE ├── README.md └── src │ ├── action_option.rs │ ├── actions.rs │ ├── actions │ ├── cargo.rs │ ├── rust_flags.rs │ ├── set_up.rs │ ├── target_dir.rs │ └── tools.rs │ ├── cfg.rs │ ├── cfg │ └── you_rust.rs │ ├── cfg_option.rs │ ├── error.rs │ ├── macros.rs │ ├── main.rs │ ├── params.rs │ ├── parse_cfg.rs │ └── transforming_params.rs └── rustfmt.toml /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 2 7 | indent_style = space 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | updates: 4 | - package-ecosystem: "cargo" 5 | directory: "/" 6 | schedule: 7 | interval: daily 8 | 9 | - package-ecosystem: "github-actions" 10 | directory: "/" 11 | schedule: 12 | interval: "weekly" 13 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | pull_request: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | fuzz: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v4 13 | - uses: actions-rs/toolchain@v1 14 | with: 15 | override: true 16 | profile: minimal 17 | toolchain: nightly-2024-09-07 18 | - uses: actions-rs/install@v0.1 19 | with: 20 | crate: cargo-fuzz 21 | use-tool-cache: true 22 | 23 | - run: .scripts/fuzz.sh 24 | 25 | internal-tests: 26 | runs-on: ubuntu-latest 27 | steps: 28 | - uses: actions/checkout@v4 29 | - uses: actions-rs/toolchain@v1 30 | with: 31 | components: clippy, rustfmt 32 | override: true 33 | profile: minimal 34 | toolchain: nightly-2024-09-07 35 | - uses: Swatinem/rust-cache@v2 36 | 37 | - run: .scripts/all.sh -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | **/*.rs.bk 3 | **/artifacts 4 | **/Cargo.lock 5 | **/corpus 6 | **/target 7 | **/target -------------------------------------------------------------------------------- /.scripts/all.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | . ".scripts/common.sh" 4 | 5 | $rt rustfmt 6 | $rt clippy 7 | 8 | .scripts/cl-aux.sh 9 | .scripts/ndstruct.sh 10 | .scripts/rust-tools.sh 11 | 12 | cargo test --all-features --doc -------------------------------------------------------------------------------- /.scripts/cl-aux.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | . ".scripts/common.sh" 4 | 5 | $rt test-with-features cl-aux 6 | $rt test-with-features cl-aux alloc 7 | $rt test-with-features cl-aux arrayvec 8 | $rt test-with-features cl-aux serde 9 | $rt test-with-features cl-aux smallvec 10 | $rt test-with-features cl-aux std 11 | $rt test-with-features cl-aux tinyvec 12 | -------------------------------------------------------------------------------- /.scripts/common.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euxo pipefail 4 | 5 | export rt='cargo run --bin rust-tools -- --template you-rust' 6 | 7 | export CARGO_TARGET_DIR="$($rt target-dir)" 8 | export RUST_BACKTRACE=1 9 | export RUSTFLAGS="$($rt rust-flags)" 10 | -------------------------------------------------------------------------------- /.scripts/fuzz.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euxo pipefail 4 | 5 | cargo fuzz run --features libfuzzer-sys/link_libfuzzer --fuzz-dir ndstruct-fuzz coo -- -runs=100000 6 | cargo fuzz run --features libfuzzer-sys/link_libfuzzer --fuzz-dir ndstruct-fuzz csl -- -runs=100000 7 | -------------------------------------------------------------------------------- /.scripts/ndstruct.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | . ".scripts/common.sh" 4 | 5 | $rt test-generic ndstruct 6 | $rt test-with-features ndstruct alloc 7 | $rt test-with-features ndstruct std 8 | $rt test-with-features ndstruct rand 9 | $rt test-with-features ndstruct rayon 10 | $rt test-with-features ndstruct serde 11 | -------------------------------------------------------------------------------- /.scripts/rust-tools.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | . ".scripts/common.sh" 4 | 5 | $rt test-with-features rust-tools 6 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "arbitrary" 7 | version = "1.3.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" 10 | dependencies = [ 11 | "derive_arbitrary", 12 | ] 13 | 14 | [[package]] 15 | name = "arrayvec" 16 | version = "0.7.6" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" 19 | 20 | [[package]] 21 | name = "cc" 22 | version = "1.1.18" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476" 25 | dependencies = [ 26 | "jobserver", 27 | "libc", 28 | "shlex", 29 | ] 30 | 31 | [[package]] 32 | name = "cl-aux" 33 | version = "5.0.1" 34 | dependencies = [ 35 | "arrayvec", 36 | "serde", 37 | "smallvec", 38 | "tinyvec", 39 | ] 40 | 41 | [[package]] 42 | name = "crossbeam-deque" 43 | version = "0.8.5" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" 46 | dependencies = [ 47 | "crossbeam-epoch", 48 | "crossbeam-utils", 49 | ] 50 | 51 | [[package]] 52 | name = "crossbeam-epoch" 53 | version = "0.9.18" 54 | source = "registry+https://github.com/rust-lang/crates.io-index" 55 | checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" 56 | dependencies = [ 57 | "crossbeam-utils", 58 | ] 59 | 60 | [[package]] 61 | name = "crossbeam-utils" 62 | version = "0.8.20" 63 | source = "registry+https://github.com/rust-lang/crates.io-index" 64 | checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" 65 | 66 | [[package]] 67 | name = "derive_arbitrary" 68 | version = "1.3.2" 69 | source = "registry+https://github.com/rust-lang/crates.io-index" 70 | checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" 71 | dependencies = [ 72 | "proc-macro2", 73 | "quote", 74 | "syn", 75 | ] 76 | 77 | [[package]] 78 | name = "either" 79 | version = "1.13.0" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" 82 | 83 | [[package]] 84 | name = "jobserver" 85 | version = "0.1.32" 86 | source = "registry+https://github.com/rust-lang/crates.io-index" 87 | checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" 88 | dependencies = [ 89 | "libc", 90 | ] 91 | 92 | [[package]] 93 | name = "libc" 94 | version = "0.2.158" 95 | source = "registry+https://github.com/rust-lang/crates.io-index" 96 | checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" 97 | 98 | [[package]] 99 | name = "libfuzzer-sys" 100 | version = "0.4.7" 101 | source = "registry+https://github.com/rust-lang/crates.io-index" 102 | checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7" 103 | dependencies = [ 104 | "arbitrary", 105 | "cc", 106 | "once_cell", 107 | ] 108 | 109 | [[package]] 110 | name = "ndstruct" 111 | version = "2.2.0" 112 | dependencies = [ 113 | "cl-aux", 114 | "rand", 115 | "rayon", 116 | "serde", 117 | ] 118 | 119 | [[package]] 120 | name = "ndstruct-fuzz" 121 | version = "0.0.0" 122 | dependencies = [ 123 | "arbitrary", 124 | "libfuzzer-sys", 125 | "ndstruct", 126 | "rand", 127 | "rayon", 128 | ] 129 | 130 | [[package]] 131 | name = "once_cell" 132 | version = "1.19.0" 133 | source = "registry+https://github.com/rust-lang/crates.io-index" 134 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" 135 | 136 | [[package]] 137 | name = "proc-macro2" 138 | version = "1.0.86" 139 | source = "registry+https://github.com/rust-lang/crates.io-index" 140 | checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" 141 | dependencies = [ 142 | "unicode-ident", 143 | ] 144 | 145 | [[package]] 146 | name = "quote" 147 | version = "1.0.37" 148 | source = "registry+https://github.com/rust-lang/crates.io-index" 149 | checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" 150 | dependencies = [ 151 | "proc-macro2", 152 | ] 153 | 154 | [[package]] 155 | name = "rand" 156 | version = "0.8.5" 157 | source = "registry+https://github.com/rust-lang/crates.io-index" 158 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 159 | dependencies = [ 160 | "rand_core", 161 | ] 162 | 163 | [[package]] 164 | name = "rand_core" 165 | version = "0.6.4" 166 | source = "registry+https://github.com/rust-lang/crates.io-index" 167 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 168 | 169 | [[package]] 170 | name = "rayon" 171 | version = "1.10.0" 172 | source = "registry+https://github.com/rust-lang/crates.io-index" 173 | checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" 174 | dependencies = [ 175 | "either", 176 | "rayon-core", 177 | ] 178 | 179 | [[package]] 180 | name = "rayon-core" 181 | version = "1.12.1" 182 | source = "registry+https://github.com/rust-lang/crates.io-index" 183 | checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" 184 | dependencies = [ 185 | "crossbeam-deque", 186 | "crossbeam-utils", 187 | ] 188 | 189 | [[package]] 190 | name = "rust-tools" 191 | version = "1.0.3" 192 | 193 | [[package]] 194 | name = "serde" 195 | version = "1.0.210" 196 | source = "registry+https://github.com/rust-lang/crates.io-index" 197 | checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" 198 | dependencies = [ 199 | "serde_derive", 200 | ] 201 | 202 | [[package]] 203 | name = "serde_derive" 204 | version = "1.0.210" 205 | source = "registry+https://github.com/rust-lang/crates.io-index" 206 | checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" 207 | dependencies = [ 208 | "proc-macro2", 209 | "quote", 210 | "syn", 211 | ] 212 | 213 | [[package]] 214 | name = "shlex" 215 | version = "1.3.0" 216 | source = "registry+https://github.com/rust-lang/crates.io-index" 217 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 218 | 219 | [[package]] 220 | name = "smallvec" 221 | version = "1.13.2" 222 | source = "registry+https://github.com/rust-lang/crates.io-index" 223 | checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" 224 | 225 | [[package]] 226 | name = "syn" 227 | version = "2.0.77" 228 | source = "registry+https://github.com/rust-lang/crates.io-index" 229 | checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" 230 | dependencies = [ 231 | "proc-macro2", 232 | "quote", 233 | "unicode-ident", 234 | ] 235 | 236 | [[package]] 237 | name = "tinyvec" 238 | version = "1.8.0" 239 | source = "registry+https://github.com/rust-lang/crates.io-index" 240 | checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" 241 | dependencies = [ 242 | "tinyvec_macros", 243 | ] 244 | 245 | [[package]] 246 | name = "tinyvec_macros" 247 | version = "0.1.1" 248 | source = "registry+https://github.com/rust-lang/crates.io-index" 249 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 250 | 251 | [[package]] 252 | name = "unicode-ident" 253 | version = "1.0.13" 254 | source = "registry+https://github.com/rust-lang/crates.io-index" 255 | checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" 256 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [profile.profiling] 2 | inherits = "release" 3 | debug = true 4 | 5 | [workspace] 6 | members = ["cl-aux", "ndstruct", "ndstruct-fuzz", "rust-tools"] 7 | resolver = "2" 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Regular crates 2 | 3 | Aggregation of single-crate projects. See the desired project's README for more information. -------------------------------------------------------------------------------- /cl-aux/Cargo.toml: -------------------------------------------------------------------------------- 1 | [dependencies] 2 | arrayvec = { default-features = false, optional = true, version = "0.7" } 3 | serde = { default-features = false, optional = true, version = "1.0" } 4 | smallvec = { default-features = false, optional = true, version = "1.13" } 5 | tinyvec = { default-features = false, optional = true, version = "1.0" } 6 | 7 | [features] 8 | alloc = ["tinyvec?/alloc"] 9 | default = [] 10 | std = ["alloc"] 11 | 12 | [package] 13 | authors = ["Caio Fernandes "] 14 | categories = ["development-tools"] 15 | description = "Provides elements that describe collections" 16 | edition = "2021" 17 | keywords = ["collections", "traits"] 18 | license = "Apache-2.0" 19 | name = "cl-aux" 20 | readme = "README.md" 21 | repository = "https://github.com/c410-f3r/regular-crates" 22 | rust-version = "1.65" 23 | version = "5.0.1" 24 | -------------------------------------------------------------------------------- /cl-aux/LICENSE: -------------------------------------------------------------------------------- 1 | ../LICENSE -------------------------------------------------------------------------------- /cl-aux/README.md: -------------------------------------------------------------------------------- 1 | # Auxiliary elements for collections 2 | 3 | [![CI](https://github.com/c410-f3r/cl-traits/workflows/CI/badge.svg)](https://github.com/c410-f3r/cl-traits/actions?query=workflow%3ACI) 4 | [![crates.io](https://img.shields.io/crates/v/cl-traits.svg)](https://crates.io/crates/cl-traits) 5 | [![Documentation](https://docs.rs/cl-traits/badge.svg)](https://docs.rs/cl-traits) 6 | [![License](https://img.shields.io/badge/license-APACHE2-blue.svg)](./LICENSE) 7 | ![Rustc](https://img.shields.io/badge/rustc-1.52-lightgray) 8 | 9 | Provides well-defined traits with single methods that enable the achievement of maximum flexibility and freedom in several different operations instead of imposing abstract subsets. 10 | 11 | ```rust 12 | use cl_aux::Length; 13 | 14 | struct SomeCustomArray([i32; 2], [i32; 4]); 15 | 16 | impl Length for SomeCustomArray { 17 | fn length(&self) -> usize { 18 | self.0.length() + self.1.length() 19 | } 20 | } 21 | 22 | fn main() { 23 | let v = SomeCustomArray([1, 2], [3, 4, 5, 6]); 24 | assert_eq!(v.length(), 6); 25 | } 26 | ``` 27 | 28 | Also provides structures for common use-cases. 29 | 30 | ```rust 31 | use cl_aux::ArrayWrapper; 32 | 33 | fn main() { 34 | let _array: [usize; 1] = ArrayWrapper::from_fn(|idx| idx).0; 35 | } 36 | ``` 37 | -------------------------------------------------------------------------------- /cl-aux/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![doc = include_str!("../README.md")] 2 | #![cfg_attr(not(feature = "std"), no_std)] 3 | 4 | #[cfg(feature = "alloc")] 5 | extern crate alloc; 6 | 7 | #[macro_use] 8 | mod macros; 9 | 10 | mod structures; 11 | mod traits; 12 | mod tuple_impls; 13 | 14 | pub use structures::*; 15 | pub use traits::*; 16 | 17 | /// Alias of [`core::result::Result`]. 18 | pub type Result = core::result::Result; 19 | -------------------------------------------------------------------------------- /cl-aux/src/macros.rs: -------------------------------------------------------------------------------- 1 | macro_rules! _check_capacity { 2 | ($elem:expr) => {{ 3 | let capacity_upper_bound = crate::CapacityUpperBound::capacity_upper_bound($elem); 4 | let length = crate::Length::length($elem); 5 | if length >= capacity_upper_bound { 6 | return Err(crate::Error::InsufficientCapacity(capacity_upper_bound)); 7 | } 8 | }}; 9 | } 10 | 11 | macro_rules! _check_indcs { 12 | ($elem:expr, $( $idx:expr ),*) => {{ 13 | let length = crate::Length::length($elem); 14 | if $( $idx >= length || )* false { 15 | return Err(crate::Error::OutOfBounds(length)); 16 | } 17 | }}; 18 | } 19 | 20 | macro_rules! _get { 21 | ($elem:expr, $idx:expr) => {{ 22 | $elem.get($idx).ok_or(crate::Error::OutOfBounds($idx)) 23 | }}; 24 | } 25 | 26 | macro_rules! _get_mut { 27 | ($elem:expr, $idx:expr) => {{ 28 | $elem.get_mut($idx).ok_or(crate::Error::OutOfBounds($idx)) 29 | }}; 30 | } 31 | -------------------------------------------------------------------------------- /cl-aux/src/structures.rs: -------------------------------------------------------------------------------- 1 | mod array_wrapper; 2 | mod array_wrapper_ref; 3 | mod auto_clear; 4 | #[doc(hidden)] 5 | pub mod doc_tests; 6 | mod error; 7 | mod full_auto_clear; 8 | mod iter_wrapper; 9 | mod single_item_storage; 10 | 11 | pub use array_wrapper::*; 12 | pub use array_wrapper_ref::*; 13 | pub use auto_clear::*; 14 | pub use error::*; 15 | pub use full_auto_clear::*; 16 | pub use iter_wrapper::*; 17 | pub use single_item_storage::*; 18 | -------------------------------------------------------------------------------- /cl-aux/src/structures/array_wrapper_ref.rs: -------------------------------------------------------------------------------- 1 | use core::{borrow::Borrow, ops::Deref, slice::Iter}; 2 | 3 | /// Immutable array reference wrapper similar to [`crate::ArrayWrapper`]. 4 | #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] 5 | #[repr(transparent)] 6 | pub struct ArrayWrapperRef<'array, T, const N: usize>( 7 | /// The actual array reference. 8 | pub &'array [T; N], 9 | ); 10 | 11 | impl AsRef<[T; N]> for ArrayWrapperRef<'_, T, N> { 12 | #[inline] 13 | fn as_ref(&self) -> &[T; N] { 14 | self 15 | } 16 | } 17 | 18 | impl Borrow<[T; N]> for ArrayWrapperRef<'_, T, N> { 19 | #[inline] 20 | fn borrow(&self) -> &[T; N] { 21 | self 22 | } 23 | } 24 | 25 | impl Deref for ArrayWrapperRef<'_, T, N> { 26 | type Target = [T; N]; 27 | 28 | #[inline] 29 | fn deref(&self) -> &[T; N] { 30 | self.0 31 | } 32 | } 33 | 34 | impl<'array, T, const N: usize> From<&'array [T; N]> for ArrayWrapperRef<'array, T, N> { 35 | #[inline] 36 | fn from(from: &'array [T; N]) -> Self { 37 | Self(from) 38 | } 39 | } 40 | 41 | impl<'array, T, const N: usize> IntoIterator for &'array ArrayWrapperRef<'array, T, N> { 42 | type IntoIter = Iter<'array, T>; 43 | type Item = &'array T; 44 | 45 | #[inline] 46 | fn into_iter(self) -> Self::IntoIter { 47 | self.0.iter() 48 | } 49 | } 50 | 51 | #[cfg(feature = "serde")] 52 | mod serde { 53 | use crate::ArrayWrapperRef; 54 | use serde::{ser::SerializeTuple, Serialize, Serializer}; 55 | 56 | impl Serialize for ArrayWrapperRef<'_, T, N> 57 | where 58 | T: Serialize, 59 | { 60 | #[inline] 61 | fn serialize(&self, serializer: S) -> Result 62 | where 63 | S: Serializer, 64 | { 65 | let mut seq = serializer.serialize_tuple(N)?; 66 | for elem in self.0 { 67 | seq.serialize_element(elem)?; 68 | } 69 | seq.end() 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /cl-aux/src/structures/auto_clear.rs: -------------------------------------------------------------------------------- 1 | use crate::Clear; 2 | use core::{ 3 | borrow::{Borrow, BorrowMut}, 4 | ops::{Deref, DerefMut}, 5 | }; 6 | 7 | /// Any mutable item wrapped in this structure is automatically cleaned when dropped. 8 | #[derive(Debug, Eq, Ord, PartialEq, PartialOrd)] 9 | pub struct AutoClear(T) 10 | where 11 | T: Clear; 12 | 13 | impl AsMut for AutoClear 14 | where 15 | T: Clear, 16 | { 17 | #[inline] 18 | fn as_mut(&mut self) -> &mut T { 19 | self 20 | } 21 | } 22 | 23 | impl AsRef for AutoClear 24 | where 25 | T: Clear, 26 | { 27 | #[inline] 28 | fn as_ref(&self) -> &T { 29 | self 30 | } 31 | } 32 | 33 | impl Borrow for AutoClear 34 | where 35 | T: Clear, 36 | { 37 | #[inline] 38 | fn borrow(&self) -> &T { 39 | self 40 | } 41 | } 42 | 43 | impl BorrowMut for AutoClear 44 | where 45 | T: Clear, 46 | { 47 | #[inline] 48 | fn borrow_mut(&mut self) -> &mut T { 49 | self 50 | } 51 | } 52 | 53 | impl Deref for AutoClear 54 | where 55 | T: Clear, 56 | { 57 | type Target = T; 58 | 59 | #[inline] 60 | fn deref(&self) -> &Self::Target { 61 | &self.0 62 | } 63 | } 64 | 65 | impl DerefMut for AutoClear 66 | where 67 | T: Clear, 68 | { 69 | #[inline] 70 | fn deref_mut(&mut self) -> &mut Self::Target { 71 | &mut self.0 72 | } 73 | } 74 | 75 | impl Drop for AutoClear 76 | where 77 | T: Clear, 78 | { 79 | #[inline] 80 | fn drop(&mut self) { 81 | self.0.clear(); 82 | } 83 | } 84 | 85 | impl From for AutoClear 86 | where 87 | T: Clear, 88 | { 89 | #[inline] 90 | fn from(from: T) -> Self { 91 | Self(from) 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /cl-aux/src/structures/doc_tests.rs: -------------------------------------------------------------------------------- 1 | //! Instances for documentation tests 2 | 3 | /// Mutable slice with three elements 4 | #[doc(hidden)] 5 | #[macro_export] 6 | macro_rules! slice_mut { 7 | () => { 8 | &mut [1i32, 2, 3][..] 9 | }; 10 | } 11 | 12 | use crate::SingleItemStorage; 13 | #[cfg(feature = "alloc")] 14 | use alloc::{ 15 | collections::{BTreeMap, BTreeSet}, 16 | string::String, 17 | vec::Vec, 18 | }; 19 | pub use slice_mut; 20 | #[cfg(feature = "std")] 21 | use std::collections::{HashMap, HashSet}; 22 | 23 | /// Array with three elements 24 | #[inline] 25 | #[must_use] 26 | pub fn array() -> [i32; 3] { 27 | [1, 2, 3] 28 | } 29 | 30 | /// [`arrayvec::ArrayString`] filled with "Hello" 31 | #[cfg(feature = "arrayvec")] 32 | #[inline] 33 | #[must_use] 34 | pub fn array_string() -> arrayvec::ArrayString<10> { 35 | let mut s = arrayvec::ArrayString::new(); 36 | s.push_str("Hello"); 37 | s 38 | } 39 | 40 | /// `ArrayVec` with three elements 41 | #[cfg(feature = "arrayvec")] 42 | #[inline] 43 | #[must_use] 44 | pub fn array_vec() -> arrayvec::ArrayVec { 45 | let mut vec = arrayvec::ArrayVec::new(); 46 | vec.extend([1, 2, 3].iter().copied()); 47 | vec 48 | } 49 | 50 | /// `BTreeMap` with three elements 51 | #[cfg(feature = "alloc")] 52 | #[inline] 53 | #[must_use] 54 | pub fn b_tree_map() -> BTreeMap { 55 | [(0, 1), (1, 2), (2, 3)].iter().copied().collect() 56 | } 57 | 58 | /// `BTreeSet` with three elements 59 | #[cfg(feature = "alloc")] 60 | #[inline] 61 | #[must_use] 62 | pub fn b_tree_set() -> BTreeSet { 63 | [1, 2, 3].iter().copied().collect() 64 | } 65 | 66 | /// `HashMap` with three elements 67 | #[cfg(feature = "std")] 68 | #[inline] 69 | #[must_use] 70 | pub fn hash_map() -> HashMap { 71 | [(0, 1), (1, 2), (2, 3)].iter().copied().collect() 72 | } 73 | 74 | /// `HashSet` with three elements 75 | #[cfg(feature = "std")] 76 | #[inline] 77 | #[must_use] 78 | pub fn hash_set() -> HashSet { 79 | [1, 2, 3].iter().copied().collect() 80 | } 81 | 82 | #[inline] 83 | #[must_use] 84 | /// `SingleItemStorage` containing `'1i32` 85 | pub fn single_item_storage() -> SingleItemStorage { 86 | 1i32.into() 87 | } 88 | 89 | #[inline] 90 | #[must_use] 91 | /// Slice with three elements 92 | pub fn slice() -> &'static [i32] { 93 | &[1, 2, 3] 94 | } 95 | 96 | #[cfg(feature = "smallvec")] 97 | #[inline] 98 | #[must_use] 99 | /// `SmallVec` with three elements 100 | pub fn small_vec() -> smallvec::SmallVec<[i32; 5]> { 101 | let mut vec = smallvec::SmallVec::new(); 102 | vec.extend([1, 2, 3].iter().copied()); 103 | vec 104 | } 105 | 106 | /// [String] filled with "Hello" 107 | #[cfg(feature = "alloc")] 108 | #[inline] 109 | #[must_use] 110 | pub fn string() -> String { 111 | String::from("Hello") 112 | } 113 | 114 | #[cfg(feature = "tinyvec")] 115 | #[inline] 116 | #[must_use] 117 | /// `ArrayVec` with three elements 118 | pub fn tiny_vec_array_vec() -> tinyvec::ArrayVec<[i32; 5]> { 119 | let mut vec = tinyvec::ArrayVec::new(); 120 | vec.extend([1, 2, 3].iter().copied()); 121 | vec 122 | } 123 | 124 | #[cfg(all(feature = "alloc", feature = "tinyvec"))] 125 | #[inline] 126 | #[must_use] 127 | /// `TinyVec` with three elements 128 | pub fn tiny_vec_tiny_vec() -> tinyvec::TinyVec<[i32; 5]> { 129 | let mut vec = tinyvec::TinyVec::new(); 130 | vec.extend([1, 2, 3].iter().copied()); 131 | vec 132 | } 133 | 134 | #[cfg(feature = "alloc")] 135 | #[inline] 136 | #[must_use] 137 | /// `Vec` with three elements 138 | pub fn vec() -> Vec { 139 | let mut vec = Vec::with_capacity(5); 140 | vec.extend([1, 2, 3].iter().copied()); 141 | vec 142 | } 143 | -------------------------------------------------------------------------------- /cl-aux/src/structures/error.rs: -------------------------------------------------------------------------------- 1 | use core::fmt::{Debug, Display, Formatter}; 2 | 3 | /// Groups all possible crate errors 4 | #[derive(Clone, Copy, Debug, Eq, PartialEq)] 5 | pub enum Error { 6 | /// It is not possible to insert an already existing element 7 | AlreadyExistingElement, 8 | /// Structure can't store more elements 9 | InsufficientCapacity(usize), 10 | /// Index is out of structure bounds 11 | OutOfBounds(usize), 12 | } 13 | 14 | impl Display for Error { 15 | #[inline] 16 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> { 17 | Debug::fmt(self, f) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /cl-aux/src/structures/full_auto_clear.rs: -------------------------------------------------------------------------------- 1 | use crate::Clear; 2 | use core::{ 3 | borrow::{Borrow, BorrowMut}, 4 | ops::{Deref, DerefMut}, 5 | }; 6 | 7 | /// Any mutable item wrapped in this structure is automatically cleaned when initialized and 8 | /// dropped. 9 | #[derive(Debug, Eq, Ord, PartialEq, PartialOrd)] 10 | pub struct FullAutoClear(T) 11 | where 12 | T: Clear; 13 | 14 | impl AsMut for FullAutoClear 15 | where 16 | T: Clear, 17 | { 18 | #[inline] 19 | fn as_mut(&mut self) -> &mut T { 20 | self 21 | } 22 | } 23 | 24 | impl AsRef for FullAutoClear 25 | where 26 | T: Clear, 27 | { 28 | #[inline] 29 | fn as_ref(&self) -> &T { 30 | self 31 | } 32 | } 33 | 34 | impl Borrow for FullAutoClear 35 | where 36 | T: Clear, 37 | { 38 | #[inline] 39 | fn borrow(&self) -> &T { 40 | self 41 | } 42 | } 43 | 44 | impl BorrowMut for FullAutoClear 45 | where 46 | T: Clear, 47 | { 48 | #[inline] 49 | fn borrow_mut(&mut self) -> &mut T { 50 | self 51 | } 52 | } 53 | 54 | impl Deref for FullAutoClear 55 | where 56 | T: Clear, 57 | { 58 | type Target = T; 59 | 60 | #[inline] 61 | fn deref(&self) -> &Self::Target { 62 | &self.0 63 | } 64 | } 65 | 66 | impl DerefMut for FullAutoClear 67 | where 68 | T: Clear, 69 | { 70 | #[inline] 71 | fn deref_mut(&mut self) -> &mut Self::Target { 72 | &mut self.0 73 | } 74 | } 75 | 76 | impl Drop for FullAutoClear 77 | where 78 | T: Clear, 79 | { 80 | #[inline] 81 | fn drop(&mut self) { 82 | self.0.clear(); 83 | } 84 | } 85 | 86 | impl From for FullAutoClear 87 | where 88 | T: Clear, 89 | { 90 | #[inline] 91 | fn from(mut from: T) -> Self { 92 | from.clear(); 93 | Self(from) 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /cl-aux/src/structures/iter_wrapper.rs: -------------------------------------------------------------------------------- 1 | /// A wrapper around `I: Iterator` to workaround trait implementation conflicts 2 | #[derive(Debug)] 3 | pub struct IterWrapper( 4 | /// Iterator 5 | pub I, 6 | ) 7 | where 8 | I: Iterator; 9 | 10 | #[cfg(feature = "serde")] 11 | mod serde { 12 | use crate::IterWrapper; 13 | use serde::{ser::SerializeSeq, Serialize, Serializer}; 14 | 15 | impl Serialize for IterWrapper 16 | where 17 | I: Clone + Iterator, 18 | I::Item: Serialize, 19 | { 20 | #[inline] 21 | fn serialize(&self, serializer: S) -> Result 22 | where 23 | S: Serializer, 24 | { 25 | let mut seq = serializer.serialize_seq(None)?; 26 | for elem in self.0.clone() { 27 | seq.serialize_element(&elem)?; 28 | } 29 | seq.end() 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /cl-aux/src/structures/single_item_storage.rs: -------------------------------------------------------------------------------- 1 | use core::slice; 2 | 3 | /// A structure that holds one, and only one `T`. 4 | /// 5 | /// Behaves like [T; 1] but has additional `Default` and `From` implementations. 6 | #[derive(Debug, Default, Eq, PartialEq, PartialOrd)] 7 | pub struct SingleItemStorage( 8 | // Single item 9 | pub T, 10 | ); 11 | 12 | impl AsMut<[T]> for SingleItemStorage { 13 | #[inline] 14 | fn as_mut(&mut self) -> &mut [T] { 15 | slice::from_mut(&mut self.0) 16 | } 17 | } 18 | 19 | impl AsRef<[T]> for SingleItemStorage { 20 | #[inline] 21 | fn as_ref(&self) -> &[T] { 22 | slice::from_ref(&self.0) 23 | } 24 | } 25 | 26 | impl From for SingleItemStorage { 27 | #[inline] 28 | fn from(from: T) -> Self { 29 | Self(from) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /cl-aux/src/traits.rs: -------------------------------------------------------------------------------- 1 | mod capacity; 2 | mod capacity_upper_bound; 3 | mod clear; 4 | mod dyn_contig_coll; 5 | mod dyn_string; 6 | mod extend; 7 | mod get; 8 | mod get_mut; 9 | mod insert; 10 | mod iter; 11 | mod length; 12 | mod push; 13 | mod remove; 14 | mod retain; 15 | mod single_type_storage; 16 | mod size_hint; 17 | mod swap; 18 | mod truncate; 19 | mod with_capacity; 20 | 21 | pub use capacity::Capacity; 22 | pub use capacity_upper_bound::CapacityUpperBound; 23 | pub use clear::Clear; 24 | pub use dyn_contig_coll::DynContigColl; 25 | pub use dyn_string::DynString; 26 | pub use extend::Extend; 27 | pub use get::Get; 28 | pub use get_mut::GetMut; 29 | pub use insert::Insert; 30 | pub use iter::Iter; 31 | pub use length::Length; 32 | pub use push::Push; 33 | pub use remove::Remove; 34 | pub use retain::Retain; 35 | pub use single_type_storage::SingleTypeStorage; 36 | pub use size_hint::SizeHint; 37 | pub use swap::Swap; 38 | pub use truncate::Truncate; 39 | pub use with_capacity::WithCapacity; 40 | -------------------------------------------------------------------------------- /cl-aux/src/traits/capacity.rs: -------------------------------------------------------------------------------- 1 | use crate::SingleItemStorage; 2 | #[cfg(feature = "alloc")] 3 | use alloc::{string::String, vec::Vec}; 4 | 5 | /// See [`Capacity::capacity`] for more information. 6 | pub trait Capacity { 7 | /// The number of elements the implementation has pre-allocated as an internal buffer. Not 8 | /// necessarily the current number of inserted elements. 9 | fn capacity(&self) -> usize; 10 | } 11 | 12 | impl Capacity for &T 13 | where 14 | T: Capacity, 15 | { 16 | #[inline] 17 | fn capacity(&self) -> usize { 18 | (*self).capacity() 19 | } 20 | } 21 | 22 | /// ```rust 23 | /// assert_eq!(cl_aux::Capacity::capacity(&()), 0); 24 | /// ``` 25 | impl Capacity for () { 26 | #[inline] 27 | fn capacity(&self) -> usize { 28 | 0 29 | } 30 | } 31 | 32 | /// ```rust 33 | /// assert_eq!(cl_aux::Capacity::capacity(&Some(0)), 1); 34 | /// ``` 35 | impl Capacity for Option { 36 | #[inline] 37 | fn capacity(&self) -> usize { 38 | 1 39 | } 40 | } 41 | 42 | /// ```rust 43 | /// let mut structure = cl_aux::doc_tests::single_item_storage(); 44 | /// assert_eq!(cl_aux::Capacity::capacity(&structure), 1); 45 | /// ``` 46 | impl Capacity for SingleItemStorage { 47 | #[inline] 48 | fn capacity(&self) -> usize { 49 | 1 50 | } 51 | } 52 | 53 | /// ```rust 54 | /// let mut structure = cl_aux::doc_tests::array(); 55 | /// assert_eq!(cl_aux::Capacity::capacity(&structure), 3); 56 | /// ``` 57 | impl Capacity for [T; N] { 58 | #[inline] 59 | fn capacity(&self) -> usize { 60 | N 61 | } 62 | } 63 | 64 | /// ```rust 65 | /// let structure = cl_aux::doc_tests::slice(); 66 | /// assert_eq!(cl_aux::Length::length(&structure), 3); 67 | /// ``` 68 | impl Capacity for &'_ [T] { 69 | #[inline] 70 | fn capacity(&self) -> usize { 71 | self.len() 72 | } 73 | } 74 | 75 | /// ```rust 76 | /// let mut structure = cl_aux::doc_tests::slice_mut!(); 77 | /// assert_eq!(cl_aux::Length::length(&mut structure), 3); 78 | /// ``` 79 | impl Capacity for &'_ mut [T] { 80 | #[inline] 81 | fn capacity(&self) -> usize { 82 | self.len() 83 | } 84 | } 85 | 86 | /// ```rust 87 | /// let mut structure = cl_aux::doc_tests::string(); 88 | /// assert_eq!(cl_aux::Capacity::capacity(&structure), 5); 89 | /// ``` 90 | #[cfg(feature = "alloc")] 91 | impl Capacity for String { 92 | #[inline] 93 | fn capacity(&self) -> usize { 94 | self.capacity() 95 | } 96 | } 97 | 98 | /// ```rust 99 | /// let mut structure = cl_aux::doc_tests::vec(); 100 | /// assert_eq!(cl_aux::Capacity::capacity(&structure), 5); 101 | /// ``` 102 | #[cfg(feature = "alloc")] 103 | impl Capacity for Vec { 104 | #[inline] 105 | fn capacity(&self) -> usize { 106 | self.capacity() 107 | } 108 | } 109 | 110 | /// ```rust 111 | /// let mut structure = cl_aux::doc_tests::array_string(); 112 | /// assert_eq!(cl_aux::Capacity::capacity(&structure), 10); 113 | /// ``` 114 | #[cfg(feature = "arrayvec")] 115 | impl Capacity for arrayvec::ArrayString { 116 | #[inline] 117 | fn capacity(&self) -> usize { 118 | self.capacity() 119 | } 120 | } 121 | 122 | /// ```rust 123 | /// let mut structure = cl_aux::doc_tests::array_vec(); 124 | /// assert_eq!(cl_aux::Capacity::capacity(&structure), 5); 125 | /// ``` 126 | #[cfg(feature = "arrayvec")] 127 | impl Capacity for arrayvec::ArrayVec { 128 | #[inline] 129 | fn capacity(&self) -> usize { 130 | self.capacity() 131 | } 132 | } 133 | 134 | /// ```rust 135 | /// let mut structure = cl_aux::doc_tests::small_vec(); 136 | /// assert_eq!(cl_aux::Capacity::capacity(&structure), 5); 137 | /// ``` 138 | #[cfg(feature = "smallvec")] 139 | impl Capacity for smallvec::SmallVec 140 | where 141 | A: smallvec::Array, 142 | { 143 | #[inline] 144 | fn capacity(&self) -> usize { 145 | self.capacity() 146 | } 147 | } 148 | 149 | /// ```rust 150 | /// let mut structure = cl_aux::doc_tests::tiny_vec_array_vec(); 151 | /// assert_eq!(cl_aux::Capacity::capacity(&structure), 5); 152 | /// ``` 153 | #[cfg(feature = "tinyvec")] 154 | impl Capacity for tinyvec::ArrayVec 155 | where 156 | A: tinyvec::Array, 157 | A::Item: Default, 158 | { 159 | #[inline] 160 | fn capacity(&self) -> usize { 161 | self.capacity() 162 | } 163 | } 164 | 165 | /// ```rust 166 | /// let mut structure = cl_aux::doc_tests::tiny_vec_tiny_vec(); 167 | /// assert_eq!(cl_aux::Capacity::capacity(&structure), 5); 168 | /// ``` 169 | #[cfg(all(feature = "alloc", feature = "tinyvec"))] 170 | impl Capacity for tinyvec::TinyVec 171 | where 172 | A: tinyvec::Array, 173 | A::Item: Default, 174 | { 175 | #[inline] 176 | fn capacity(&self) -> usize { 177 | self.capacity() 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /cl-aux/src/traits/capacity_upper_bound.rs: -------------------------------------------------------------------------------- 1 | use crate::SingleItemStorage; 2 | #[cfg(feature = "alloc")] 3 | use alloc::{string::String, vec::Vec}; 4 | 5 | /// See [`CapacityUpperBound::capacity_upper_bound`] for more information. 6 | pub trait CapacityUpperBound { 7 | /// The maximum theoretical number of elements a type implementation is able to store. 8 | const CAPACITY_UPPER_BOUND: usize; 9 | 10 | /// Instance method representing [`Self::CAPACITY_UPPER_BOUND`]. 11 | #[inline] 12 | fn capacity_upper_bound(&self) -> usize { 13 | Self::CAPACITY_UPPER_BOUND 14 | } 15 | } 16 | 17 | impl CapacityUpperBound for &T 18 | where 19 | T: CapacityUpperBound, 20 | { 21 | const CAPACITY_UPPER_BOUND: usize = T::CAPACITY_UPPER_BOUND; 22 | 23 | #[inline] 24 | fn capacity_upper_bound(&self) -> usize { 25 | (*self).capacity_upper_bound() 26 | } 27 | } 28 | 29 | /// ```rust 30 | /// assert_eq!(cl_aux::CapacityUpperBound::capacity_upper_bound(&()), 0); 31 | /// ``` 32 | impl CapacityUpperBound for () { 33 | const CAPACITY_UPPER_BOUND: usize = 0; 34 | } 35 | 36 | /// ```rust 37 | /// assert_eq!(cl_aux::CapacityUpperBound::capacity_upper_bound(&Some(0)), 1); 38 | /// ``` 39 | impl CapacityUpperBound for Option { 40 | const CAPACITY_UPPER_BOUND: usize = 1; 41 | } 42 | 43 | /// ```rust 44 | /// let mut structure = cl_aux::doc_tests::single_item_storage(); 45 | /// assert_eq!(cl_aux::Capacity::capacity(&structure), 1); 46 | /// ``` 47 | impl CapacityUpperBound for SingleItemStorage { 48 | const CAPACITY_UPPER_BOUND: usize = 1; 49 | } 50 | 51 | /// ```rust 52 | /// let mut structure = cl_aux::doc_tests::array(); 53 | /// assert_eq!(cl_aux::CapacityUpperBound::capacity_upper_bound(&structure), 3); 54 | /// ``` 55 | impl CapacityUpperBound for [T; N] { 56 | const CAPACITY_UPPER_BOUND: usize = N; 57 | } 58 | 59 | /// ```rust 60 | /// let structure = cl_aux::doc_tests::slice(); 61 | /// assert_eq!(cl_aux::CapacityUpperBound::capacity_upper_bound(&structure), 2305843009213693951); 62 | /// ``` 63 | impl CapacityUpperBound for &'_ [T] { 64 | const CAPACITY_UPPER_BOUND: usize = _capacity_upper_bound_of_type::(); 65 | } 66 | 67 | /// ```rust 68 | /// let mut structure = cl_aux::doc_tests::slice_mut!(); 69 | /// assert_eq!(cl_aux::CapacityUpperBound::capacity_upper_bound(&mut structure), 2305843009213693951); 70 | /// ``` 71 | impl CapacityUpperBound for &'_ mut [T] { 72 | const CAPACITY_UPPER_BOUND: usize = _capacity_upper_bound_of_type::(); 73 | } 74 | 75 | /// ```rust 76 | /// let mut structure = cl_aux::doc_tests::string(); 77 | /// assert_eq!(cl_aux::CapacityUpperBound::capacity_upper_bound(&structure), 9223372036854775807); 78 | /// ``` 79 | #[cfg(feature = "alloc")] 80 | impl CapacityUpperBound for String { 81 | const CAPACITY_UPPER_BOUND: usize = _capacity_upper_bound_of_type::(); 82 | } 83 | 84 | /// ```rust 85 | /// let mut structure = cl_aux::doc_tests::vec(); 86 | /// assert_eq!(cl_aux::CapacityUpperBound::capacity_upper_bound(&structure), 2305843009213693951); 87 | /// ``` 88 | #[cfg(feature = "alloc")] 89 | impl CapacityUpperBound for Vec { 90 | const CAPACITY_UPPER_BOUND: usize = _capacity_upper_bound_of_type::(); 91 | } 92 | 93 | /// ```rust 94 | /// let mut structure = cl_aux::doc_tests::array_string(); 95 | /// assert_eq!(cl_aux::CapacityUpperBound::capacity_upper_bound(&structure), 10); 96 | /// ``` 97 | #[cfg(feature = "arrayvec")] 98 | impl CapacityUpperBound for arrayvec::ArrayString { 99 | const CAPACITY_UPPER_BOUND: usize = N; 100 | } 101 | 102 | /// ```rust 103 | /// let mut structure = cl_aux::doc_tests::array_vec(); 104 | /// assert_eq!(cl_aux::CapacityUpperBound::capacity_upper_bound(&structure), 5); 105 | /// ``` 106 | #[cfg(feature = "arrayvec")] 107 | impl CapacityUpperBound for arrayvec::ArrayVec { 108 | const CAPACITY_UPPER_BOUND: usize = N; 109 | } 110 | 111 | /// ```rust 112 | /// let mut structure = cl_aux::doc_tests::small_vec(); 113 | /// assert_eq!(cl_aux::CapacityUpperBound::capacity_upper_bound(&structure), 2305843009213693951); 114 | /// ``` 115 | #[cfg(feature = "smallvec")] 116 | impl CapacityUpperBound for smallvec::SmallVec 117 | where 118 | A: smallvec::Array, 119 | { 120 | const CAPACITY_UPPER_BOUND: usize = _capacity_upper_bound_of_type::(); 121 | } 122 | 123 | /// ```rust 124 | /// let mut structure = cl_aux::doc_tests::tiny_vec_array_vec(); 125 | /// assert_eq!(cl_aux::CapacityUpperBound::capacity_upper_bound(&structure), 5); 126 | /// ``` 127 | #[cfg(feature = "tinyvec")] 128 | impl CapacityUpperBound for tinyvec::ArrayVec 129 | where 130 | A: tinyvec::Array, 131 | A::Item: Default, 132 | { 133 | const CAPACITY_UPPER_BOUND: usize = A::CAPACITY; 134 | } 135 | 136 | /// ```rust 137 | /// let mut structure = cl_aux::doc_tests::tiny_vec_tiny_vec(); 138 | /// assert_eq!(cl_aux::CapacityUpperBound::capacity_upper_bound(&structure), 2305843009213693951); 139 | /// ``` 140 | #[cfg(all(feature = "alloc", feature = "tinyvec"))] 141 | impl CapacityUpperBound for tinyvec::TinyVec 142 | where 143 | A: tinyvec::Array, 144 | A::Item: Default, 145 | { 146 | const CAPACITY_UPPER_BOUND: usize = _capacity_upper_bound_of_type::(); 147 | } 148 | 149 | #[inline] 150 | const fn _capacity_upper_bound_of_type() -> usize { 151 | let isize_max_usize = isize::MAX.unsigned_abs(); 152 | if let Some(elem) = isize_max_usize.checked_div(size_of::()) { 153 | elem 154 | } else { 155 | 0 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /cl-aux/src/traits/clear.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "alloc")] 2 | use alloc::{string::String, vec::Vec}; 3 | 4 | /// See [`Clear::clear`] for more information. 5 | pub trait Clear { 6 | /// "Clears" the internal buffer, "erasing" all elements. 7 | fn clear(&mut self); 8 | } 9 | 10 | impl Clear for &mut T 11 | where 12 | T: Clear, 13 | { 14 | #[inline] 15 | fn clear(&mut self) { 16 | (*self).clear(); 17 | } 18 | } 19 | 20 | impl Clear for () { 21 | #[inline] 22 | fn clear(&mut self) {} 23 | } 24 | 25 | /// ```rust 26 | /// let mut opt = Some(0); 27 | /// cl_aux::Clear::clear(&mut opt); 28 | /// assert_eq!(opt, None); 29 | /// ``` 30 | impl Clear for Option { 31 | #[inline] 32 | fn clear(&mut self) { 33 | *self = None; 34 | } 35 | } 36 | 37 | /// ```rust 38 | /// let mut structure = cl_aux::doc_tests::string(); 39 | /// cl_aux::Clear::clear(&mut structure); 40 | /// assert_eq!(structure.len(), 0); 41 | /// ``` 42 | #[cfg(feature = "alloc")] 43 | impl Clear for String { 44 | #[inline] 45 | fn clear(&mut self) { 46 | self.clear(); 47 | } 48 | } 49 | 50 | /// ```rust 51 | /// let mut structure = cl_aux::doc_tests::vec(); 52 | /// cl_aux::Clear::clear(&mut structure); 53 | /// assert_eq!(structure.len(), 0); 54 | /// ``` 55 | #[cfg(feature = "alloc")] 56 | impl Clear for Vec { 57 | #[inline] 58 | fn clear(&mut self) { 59 | self.clear(); 60 | } 61 | } 62 | 63 | /// ```rust 64 | /// let mut structure = cl_aux::doc_tests::array_string(); 65 | /// cl_aux::Clear::clear(&mut structure); 66 | /// assert_eq!(structure.len(), 0); 67 | /// ``` 68 | #[cfg(feature = "arrayvec")] 69 | impl Clear for arrayvec::ArrayString { 70 | #[inline] 71 | fn clear(&mut self) { 72 | self.clear(); 73 | } 74 | } 75 | 76 | /// ```rust 77 | /// let mut structure = cl_aux::doc_tests::array_vec(); 78 | /// cl_aux::Clear::clear(&mut structure); 79 | /// assert_eq!(structure.len(), 0); 80 | /// ``` 81 | #[cfg(feature = "arrayvec")] 82 | impl Clear for arrayvec::ArrayVec { 83 | #[inline] 84 | fn clear(&mut self) { 85 | self.clear(); 86 | } 87 | } 88 | 89 | /// ```rust 90 | /// let mut structure = cl_aux::doc_tests::small_vec(); 91 | /// cl_aux::Clear::clear(&mut structure); 92 | /// assert_eq!(structure.len(), 0); 93 | /// ``` 94 | #[cfg(feature = "smallvec")] 95 | impl Clear for smallvec::SmallVec 96 | where 97 | A: smallvec::Array, 98 | { 99 | #[inline] 100 | fn clear(&mut self) { 101 | self.clear(); 102 | } 103 | } 104 | 105 | /// ```rust 106 | /// let mut structure = cl_aux::doc_tests::tiny_vec_array_vec(); 107 | /// cl_aux::Clear::clear(&mut structure); 108 | /// assert_eq!(structure.len(), 0); 109 | /// ``` 110 | #[cfg(feature = "tinyvec")] 111 | impl Clear for tinyvec::ArrayVec 112 | where 113 | A: tinyvec::Array, 114 | A::Item: Default, 115 | { 116 | #[inline] 117 | fn clear(&mut self) { 118 | self.clear(); 119 | } 120 | } 121 | 122 | /// ```rust 123 | /// let mut structure = cl_aux::doc_tests::tiny_vec_tiny_vec(); 124 | /// cl_aux::Clear::clear(&mut structure); 125 | /// assert_eq!(structure.len(), 0); 126 | /// ``` 127 | #[cfg(all(feature = "alloc", feature = "tinyvec"))] 128 | impl Clear for tinyvec::TinyVec 129 | where 130 | A: tinyvec::Array, 131 | A::Item: Default, 132 | { 133 | #[inline] 134 | fn clear(&mut self) { 135 | self.clear(); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /cl-aux/src/traits/dyn_contig_coll.rs: -------------------------------------------------------------------------------- 1 | use crate::{Capacity, Clear, Push, Truncate, WithCapacity}; 2 | use core::ops::{Deref, DerefMut}; 3 | 4 | /// Dynamic Contiguous Collection 5 | /// 6 | /// A growable vector-like abstraction for generic elements. 7 | /// 8 | #[cfg_attr(feature = "alloc", doc = "```rust")] 9 | #[cfg_attr(not(feature = "alloc"), doc = "```ignore")] 10 | /// fn stuff(dcc: &mut T) 11 | /// where 12 | /// T: cl_aux::DynContigColl 13 | /// { 14 | /// dcc.clear(); 15 | /// dcc.extend([4, 5, 6]).unwrap(); 16 | /// dcc.truncate(1); 17 | /// } 18 | /// 19 | /// let mut dcc = vec![0, 1, 2, 3]; 20 | /// stuff(&mut dcc); 21 | /// assert_eq!(dcc, &[4]); 22 | /// ``` 23 | pub trait DynContigColl: 24 | AsRef<[T]> 25 | + Clear 26 | + Capacity 27 | + Default 28 | + Deref 29 | + DerefMut 30 | + crate::Extend 31 | + Push 32 | + Truncate 33 | + WithCapacity 34 | { 35 | } 36 | 37 | impl DynContigColl for U where 38 | U: AsRef<[T]> 39 | + Clear 40 | + Capacity 41 | + Default 42 | + Deref 43 | + DerefMut 44 | + crate::Extend 45 | + Push 46 | + Truncate 47 | + WithCapacity 48 | { 49 | } 50 | -------------------------------------------------------------------------------- /cl-aux/src/traits/dyn_string.rs: -------------------------------------------------------------------------------- 1 | use crate::{Capacity, Clear, Push, Truncate, WithCapacity}; 2 | use core::{ 3 | fmt::Write, 4 | ops::{Deref, DerefMut}, 5 | }; 6 | 7 | /// Dynamic String 8 | /// 9 | /// Any owned growing string-like structure that `cl-aux` knows should implement this trait. 10 | /// 11 | #[cfg_attr(feature = "alloc", doc = "```rust")] 12 | #[cfg_attr(not(feature = "alloc"), doc = "```ignore")] 13 | /// fn stuff(s: &mut S) 14 | /// where 15 | /// S: cl_aux::DynString 16 | /// { 17 | /// s.clear(); 18 | /// s.push("World").unwrap(); 19 | /// s.truncate(1); 20 | /// } 21 | /// 22 | /// let mut s = String::from("Hello"); 23 | /// stuff(&mut s); 24 | /// assert_eq!(s, "W"); 25 | /// ``` 26 | pub trait DynString: 27 | AsRef 28 | + Capacity 29 | + Clear 30 | + Default 31 | + Deref 32 | + DerefMut 33 | + crate::Extend 34 | + Push 35 | + for<'str> Push<&'str str, Error = crate::Error> 36 | + Truncate 37 | + WithCapacity 38 | + Write 39 | { 40 | } 41 | 42 | impl DynString for T where 43 | T: AsRef 44 | + Capacity 45 | + Clear 46 | + Default 47 | + Deref 48 | + DerefMut 49 | + crate::Extend 50 | + Push 51 | + for<'str> Push<&'str str, Error = crate::Error> 52 | + Truncate 53 | + WithCapacity 54 | + Write 55 | { 56 | } 57 | -------------------------------------------------------------------------------- /cl-aux/src/traits/extend.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "alloc")] 2 | use alloc::{string::String, vec::Vec}; 3 | 4 | /// See [`Extend::extend`] for more information. 5 | pub trait Extend { 6 | /// Error 7 | type Error; 8 | 9 | /// Returns an mutable inner reference of a derived element. 10 | fn extend(&mut self, into_iter: impl IntoIterator) -> Result<(), Self::Error>; 11 | } 12 | 13 | impl Extend for &mut T 14 | where 15 | T: Extend, 16 | { 17 | type Error = T::Error; 18 | 19 | #[inline] 20 | fn extend(&mut self, into_iter: impl IntoIterator) -> Result<(), Self::Error> { 21 | (*self).extend(into_iter) 22 | } 23 | } 24 | 25 | impl Extend for () { 26 | type Error = crate::Error; 27 | 28 | #[inline] 29 | fn extend(&mut self, _: impl IntoIterator) -> Result<(), Self::Error> { 30 | Ok(()) 31 | } 32 | } 33 | 34 | /// ```rust 35 | /// let mut opt = None; 36 | /// cl_aux::Extend::extend(&mut opt, [3]).unwrap(); 37 | /// assert_eq!(opt, Some(3)); 38 | /// ``` 39 | impl Extend for Option { 40 | type Error = crate::Error; 41 | 42 | #[inline] 43 | fn extend(&mut self, into_iter: impl IntoIterator) -> Result<(), Self::Error> { 44 | _check_capacity!(self); 45 | let err = || crate::Error::InsufficientCapacity(1); 46 | let mut iter = into_iter.into_iter(); 47 | let next = iter.next().ok_or_else(err)?; 48 | *self = Some(next); 49 | if iter.next().is_some() { 50 | Err(err()) 51 | } else { 52 | Ok(()) 53 | } 54 | } 55 | } 56 | 57 | /// ```rust 58 | /// let mut structure = cl_aux::doc_tests::string(); 59 | /// cl_aux::Extend::extend(&mut structure, ['!']); 60 | /// assert_eq!(structure.as_str(), "Hello!"); 61 | /// ``` 62 | #[cfg(feature = "alloc")] 63 | impl Extend for String { 64 | type Error = crate::Error; 65 | 66 | #[inline] 67 | fn extend(&mut self, into_iter: impl IntoIterator) -> Result<(), Self::Error> { 68 | core::iter::Extend::extend(self, into_iter); 69 | Ok(()) 70 | } 71 | } 72 | 73 | /// ```rust 74 | /// let mut structure = cl_aux::doc_tests::vec(); 75 | /// cl_aux::Extend::extend(&mut structure, [20]); 76 | /// assert_eq!(&structure[..], &[1, 2, 3, 20][..]); 77 | /// ``` 78 | #[cfg(feature = "alloc")] 79 | impl Extend for Vec { 80 | type Error = crate::Error; 81 | 82 | #[inline] 83 | fn extend(&mut self, into_iter: impl IntoIterator) -> Result<(), Self::Error> { 84 | core::iter::Extend::extend(self, into_iter); 85 | Ok(()) 86 | } 87 | } 88 | 89 | /// ```rust 90 | /// let mut structure = cl_aux::doc_tests::array_string(); 91 | /// cl_aux::Extend::extend(&mut structure, "!".chars()); 92 | /// assert_eq!(structure.as_str(), "Hello!"); 93 | /// ``` 94 | #[cfg(feature = "arrayvec")] 95 | impl Extend for arrayvec::ArrayString 96 | where 97 | Self: crate::Push, 98 | { 99 | type Error = >::Error; 100 | 101 | #[inline] 102 | fn extend(&mut self, into_iter: impl IntoIterator) -> Result<(), Self::Error> { 103 | for elem in into_iter { 104 | crate::Push::push(self, elem)?; 105 | } 106 | Ok(()) 107 | } 108 | } 109 | 110 | /// ```rust 111 | /// let mut structure = cl_aux::doc_tests::array_vec(); 112 | /// cl_aux::Extend::extend(&mut structure, [20]); 113 | /// assert_eq!(&structure[..], &[1, 2, 3, 20][..]); 114 | /// ``` 115 | #[cfg(feature = "arrayvec")] 116 | impl Extend for arrayvec::ArrayVec 117 | where 118 | Self: crate::Push, 119 | { 120 | type Error = >::Error; 121 | 122 | #[inline] 123 | fn extend(&mut self, into_iter: impl IntoIterator) -> Result<(), Self::Error> { 124 | for elem in into_iter { 125 | crate::Push::push(self, elem)?; 126 | } 127 | Ok(()) 128 | } 129 | } 130 | 131 | /// ```rust 132 | /// let mut structure = cl_aux::doc_tests::small_vec(); 133 | /// cl_aux::Extend::extend(&mut structure, [20]); 134 | /// assert_eq!(&structure[..], &[1, 2, 3, 20][..]); 135 | /// ``` 136 | #[cfg(feature = "smallvec")] 137 | impl Extend for smallvec::SmallVec 138 | where 139 | A: smallvec::Array, 140 | Self: crate::Push, 141 | { 142 | type Error = >::Error; 143 | 144 | #[inline] 145 | fn extend(&mut self, into_iter: impl IntoIterator) -> Result<(), Self::Error> { 146 | for elem in into_iter { 147 | crate::Push::push(self, elem)?; 148 | } 149 | Ok(()) 150 | } 151 | } 152 | 153 | /// ```rust 154 | /// let mut structure = cl_aux::doc_tests::tiny_vec_array_vec(); 155 | /// cl_aux::Extend::extend(&mut structure, [20]); 156 | /// assert_eq!(&structure[..], &[1, 2, 3, 20][..]); 157 | /// ``` 158 | #[cfg(feature = "tinyvec")] 159 | impl Extend for tinyvec::ArrayVec 160 | where 161 | A: tinyvec::Array, 162 | Self: crate::Push, 163 | { 164 | type Error = >::Error; 165 | 166 | #[inline] 167 | fn extend(&mut self, into_iter: impl IntoIterator) -> Result<(), Self::Error> { 168 | for elem in into_iter { 169 | crate::Push::push(self, elem)?; 170 | } 171 | Ok(()) 172 | } 173 | } 174 | 175 | /// ```rust 176 | /// let mut structure = cl_aux::doc_tests::tiny_vec_tiny_vec(); 177 | /// cl_aux::Extend::extend(&mut structure, [20]); 178 | /// assert_eq!(&structure[..], &[1, 2, 3, 20][..]); 179 | /// ``` 180 | #[cfg(all(feature = "alloc", feature = "tinyvec"))] 181 | impl Extend for tinyvec::TinyVec 182 | where 183 | A: tinyvec::Array, 184 | A::Item: Default, 185 | Self: crate::Push, 186 | { 187 | type Error = >::Error; 188 | 189 | #[inline] 190 | fn extend(&mut self, into_iter: impl IntoIterator) -> Result<(), Self::Error> { 191 | for elem in into_iter { 192 | crate::Push::push(self, elem)?; 193 | } 194 | Ok(()) 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /cl-aux/src/traits/get.rs: -------------------------------------------------------------------------------- 1 | use crate::SingleItemStorage; 2 | #[cfg(feature = "alloc")] 3 | use alloc::vec::Vec; 4 | 5 | /// See [`Get::get`] for more information. 6 | pub trait Get { 7 | /// Error 8 | type Error; 9 | /// Input 10 | type Input; 11 | /// Output 12 | type Output<'output> 13 | where 14 | Self: 'output; 15 | 16 | /// Returns an immutable inner reference of a derived element. 17 | fn get(&self, input: Self::Input) -> Result, Self::Error>; 18 | } 19 | 20 | impl Get for &T 21 | where 22 | T: Get, 23 | { 24 | type Error = T::Error; 25 | type Input = T::Input; 26 | type Output<'output> = T::Output<'output> 27 | where 28 | Self: 'output; 29 | 30 | #[inline] 31 | fn get(&self, input: Self::Input) -> Result, Self::Error> { 32 | (*self).get(input) 33 | } 34 | } 35 | 36 | /// ```rust 37 | /// let structure = cl_aux::doc_tests::single_item_storage(); 38 | /// assert_eq!(cl_aux::Get::get(&structure, 0), Ok(&1)); 39 | /// ``` 40 | impl Get for SingleItemStorage { 41 | type Error = crate::Error; 42 | type Input = usize; 43 | type Output<'output> = &'output T 44 | where 45 | Self: 'output; 46 | 47 | #[inline] 48 | fn get(&self, _: Self::Input) -> Result, Self::Error> { 49 | _get!(self.as_ref(), 0) 50 | } 51 | } 52 | 53 | /// ```rust 54 | /// let structure = cl_aux::doc_tests::array(); 55 | /// assert_eq!(cl_aux::Get::get(&structure, 0), Ok(&1)); 56 | /// ``` 57 | impl Get for [T; N] { 58 | type Error = crate::Error; 59 | type Input = usize; 60 | type Output<'output> = &'output T 61 | where 62 | Self: 'output; 63 | 64 | #[inline] 65 | fn get(&self, input: Self::Input) -> Result, Self::Error> { 66 | _get!(self.as_ref(), input) 67 | } 68 | } 69 | 70 | /// ```rust 71 | /// let structure = cl_aux::doc_tests::slice(); 72 | /// assert_eq!(cl_aux::Get::get(&structure, 0), Ok(&1)); 73 | /// ``` 74 | impl Get for &'_ [T] { 75 | type Error = crate::Error; 76 | type Input = usize; 77 | type Output<'output> = &'output T 78 | where 79 | Self: 'output; 80 | 81 | #[inline] 82 | fn get(&self, input: Self::Input) -> Result, Self::Error> { 83 | _get!(self.as_ref(), input) 84 | } 85 | } 86 | 87 | /// ```rust 88 | /// let mut structure = cl_aux::doc_tests::slice_mut!(); 89 | /// assert_eq!(cl_aux::Get::get(&mut structure, 0), Ok(&1)); 90 | /// ``` 91 | impl Get for &'_ mut [T] { 92 | type Error = crate::Error; 93 | type Input = usize; 94 | type Output<'output> = &'output T 95 | where 96 | Self: 'output; 97 | 98 | #[inline] 99 | fn get(&self, input: Self::Input) -> Result, Self::Error> { 100 | _get!(self.as_ref(), input) 101 | } 102 | } 103 | 104 | /// ```rust 105 | /// let structure = cl_aux::doc_tests::vec(); 106 | /// assert_eq!(cl_aux::Get::get(&structure, 0), Ok(&1)); 107 | /// ``` 108 | #[cfg(feature = "alloc")] 109 | impl Get for Vec { 110 | type Error = crate::Error; 111 | type Input = usize; 112 | type Output<'output> = &'output T 113 | where 114 | Self: 'output; 115 | 116 | #[inline] 117 | fn get(&self, input: Self::Input) -> Result, Self::Error> { 118 | _get!(self.as_slice(), input) 119 | } 120 | } 121 | 122 | /// ```rust 123 | /// let structure = cl_aux::doc_tests::array_vec(); 124 | /// assert_eq!(cl_aux::Get::get(&structure, 0), Ok(&1)); 125 | /// ``` 126 | #[cfg(feature = "arrayvec")] 127 | impl Get for arrayvec::ArrayVec { 128 | type Error = crate::Error; 129 | type Input = usize; 130 | type Output<'output> = &'output T 131 | where 132 | Self: 'output; 133 | 134 | #[inline] 135 | fn get(&self, input: Self::Input) -> Result, Self::Error> { 136 | _get!(self.as_ref(), input) 137 | } 138 | } 139 | 140 | /// ```rust 141 | /// let structure = cl_aux::doc_tests::small_vec(); 142 | /// assert_eq!(cl_aux::Get::get(&structure, 0), Ok(&1)); 143 | /// ``` 144 | #[cfg(feature = "smallvec")] 145 | impl Get for smallvec::SmallVec 146 | where 147 | A: smallvec::Array, 148 | { 149 | type Error = crate::Error; 150 | type Input = usize; 151 | type Output<'output> = &'output A::Item 152 | where 153 | Self: 'output; 154 | 155 | #[inline] 156 | fn get(&self, input: Self::Input) -> Result, Self::Error> { 157 | _get!(self.as_ref(), input) 158 | } 159 | } 160 | 161 | /// ```rust 162 | /// let structure = cl_aux::doc_tests::tiny_vec_array_vec(); 163 | /// assert_eq!(cl_aux::Get::get(&structure, 0), Ok(&1)); 164 | /// ``` 165 | #[cfg(feature = "tinyvec")] 166 | impl Get for tinyvec::ArrayVec 167 | where 168 | A: tinyvec::Array, 169 | A::Item: Default, 170 | { 171 | type Error = crate::Error; 172 | type Input = usize; 173 | type Output<'output> = &'output A::Item 174 | where 175 | Self: 'output; 176 | 177 | #[inline] 178 | fn get(&self, input: Self::Input) -> Result, Self::Error> { 179 | _get!(self.as_ref(), input) 180 | } 181 | } 182 | 183 | /// ```rust 184 | /// let structure = cl_aux::doc_tests::tiny_vec_tiny_vec(); 185 | /// assert_eq!(cl_aux::Get::get(&structure, 0), Ok(&1)); 186 | /// ``` 187 | #[cfg(all(feature = "alloc", feature = "tinyvec"))] 188 | impl Get for tinyvec::TinyVec 189 | where 190 | A: tinyvec::Array, 191 | A::Item: Default, 192 | { 193 | type Error = crate::Error; 194 | type Input = usize; 195 | type Output<'output> = &'output A::Item 196 | where 197 | Self: 'output; 198 | 199 | #[inline] 200 | fn get(&self, input: Self::Input) -> Result, Self::Error> { 201 | _get!(self.as_ref(), input) 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /cl-aux/src/traits/get_mut.rs: -------------------------------------------------------------------------------- 1 | use crate::SingleItemStorage; 2 | #[cfg(feature = "alloc")] 3 | use alloc::vec::Vec; 4 | 5 | /// See [`GetMut::get_mut`] for more information. 6 | pub trait GetMut { 7 | /// Error 8 | type Error; 9 | /// Input 10 | type Input; 11 | /// Output 12 | type Output<'output> 13 | where 14 | Self: 'output; 15 | 16 | /// Returns an mutable inner reference of a derived element. 17 | fn get_mut(&mut self, input: Self::Input) -> Result, Self::Error>; 18 | } 19 | 20 | impl GetMut for &mut T 21 | where 22 | T: GetMut, 23 | { 24 | type Error = T::Error; 25 | type Input = T::Input; 26 | type Output<'output> = T::Output<'output> 27 | where 28 | Self: 'output; 29 | 30 | #[inline] 31 | fn get_mut(&mut self, input: Self::Input) -> Result, Self::Error> { 32 | (*self).get_mut(input) 33 | } 34 | } 35 | 36 | /// ```rust 37 | /// let mut structure = cl_aux::doc_tests::single_item_storage(); 38 | /// assert_eq!(cl_aux::GetMut::get_mut(&mut structure, 0), Ok(&mut 1)); 39 | /// ``` 40 | impl GetMut for SingleItemStorage { 41 | type Error = crate::Error; 42 | type Input = usize; 43 | type Output<'output> = &'output mut T 44 | where 45 | Self: 'output; 46 | 47 | #[inline] 48 | fn get_mut(&mut self, input: Self::Input) -> Result, Self::Error> { 49 | _get_mut!(self.as_mut(), input) 50 | } 51 | } 52 | 53 | /// ```rust 54 | /// let mut structure = cl_aux::doc_tests::array(); 55 | /// assert_eq!(cl_aux::GetMut::get_mut(&mut structure, 0), Ok(&mut 1)); 56 | /// ``` 57 | impl GetMut for [T; N] { 58 | type Error = crate::Error; 59 | type Input = usize; 60 | type Output<'output> = &'output mut T 61 | where 62 | Self: 'output; 63 | 64 | #[inline] 65 | fn get_mut(&mut self, input: Self::Input) -> Result, Self::Error> { 66 | _get_mut!(self.as_mut(), input) 67 | } 68 | } 69 | 70 | /// ```rust 71 | /// let mut structure = cl_aux::doc_tests::slice_mut!(); 72 | /// assert_eq!(cl_aux::GetMut::get_mut(&mut structure, 0), Ok(&mut 1)); 73 | /// ``` 74 | impl GetMut for &'_ mut [T] { 75 | type Error = crate::Error; 76 | type Input = usize; 77 | type Output<'output> = &'output mut T 78 | where 79 | Self: 'output; 80 | 81 | #[inline] 82 | fn get_mut(&mut self, input: Self::Input) -> Result, Self::Error> { 83 | _get_mut!(self.as_mut(), input) 84 | } 85 | } 86 | 87 | /// ```rust 88 | /// let mut structure = cl_aux::doc_tests::vec(); 89 | /// assert_eq!(cl_aux::GetMut::get_mut(&mut structure, 0), Ok(&mut 1)); 90 | /// ``` 91 | #[cfg(feature = "alloc")] 92 | impl GetMut for Vec { 93 | type Error = crate::Error; 94 | type Input = usize; 95 | type Output<'output> = &'output mut T 96 | where 97 | Self: 'output; 98 | 99 | #[inline] 100 | fn get_mut(&mut self, input: Self::Input) -> Result, Self::Error> { 101 | _get_mut!(self.as_mut_slice(), input) 102 | } 103 | } 104 | 105 | /// ```rust 106 | /// let mut structure = cl_aux::doc_tests::array_vec(); 107 | /// assert_eq!(cl_aux::GetMut::get_mut(&mut structure, 0), Ok(&mut 1)); 108 | /// ``` 109 | #[cfg(feature = "arrayvec")] 110 | impl GetMut for arrayvec::ArrayVec { 111 | type Error = crate::Error; 112 | type Input = usize; 113 | type Output<'output> = &'output mut T 114 | where 115 | Self: 'output; 116 | 117 | #[inline] 118 | fn get_mut(&mut self, input: Self::Input) -> Result, Self::Error> { 119 | _get_mut!(self.as_mut(), input) 120 | } 121 | } 122 | 123 | /// ```rust 124 | /// let mut structure = cl_aux::doc_tests::small_vec(); 125 | /// assert_eq!(cl_aux::GetMut::get_mut(&mut structure, 0), Ok(&mut 1)); 126 | /// ``` 127 | #[cfg(feature = "smallvec")] 128 | impl GetMut for smallvec::SmallVec 129 | where 130 | A: smallvec::Array, 131 | { 132 | type Error = crate::Error; 133 | type Input = usize; 134 | type Output<'output> = &'output mut A::Item 135 | where 136 | Self: 'output; 137 | 138 | #[inline] 139 | fn get_mut(&mut self, input: Self::Input) -> Result, Self::Error> { 140 | _get_mut!(self.as_mut(), input) 141 | } 142 | } 143 | 144 | /// ```rust 145 | /// let mut structure = cl_aux::doc_tests::tiny_vec_array_vec(); 146 | /// assert_eq!(cl_aux::GetMut::get_mut(&mut structure, 0), Ok(&mut 1)); 147 | /// ``` 148 | #[cfg(feature = "tinyvec")] 149 | impl GetMut for tinyvec::ArrayVec 150 | where 151 | A: tinyvec::Array, 152 | { 153 | type Error = crate::Error; 154 | type Input = usize; 155 | type Output<'output> = &'output mut A::Item 156 | where 157 | Self: 'output; 158 | 159 | #[inline] 160 | fn get_mut(&mut self, input: Self::Input) -> Result, Self::Error> { 161 | _get_mut!(self.as_mut(), input) 162 | } 163 | } 164 | 165 | /// ```rust 166 | /// let mut structure = cl_aux::doc_tests::tiny_vec_tiny_vec(); 167 | /// assert_eq!(cl_aux::GetMut::get_mut(&mut structure, 0), Ok(&mut 1)); 168 | /// ``` 169 | #[cfg(all(feature = "alloc", feature = "tinyvec"))] 170 | impl GetMut for tinyvec::TinyVec 171 | where 172 | A: tinyvec::Array, 173 | A::Item: Default, 174 | { 175 | type Error = crate::Error; 176 | type Input = usize; 177 | type Output<'output> = &'output mut A::Item 178 | where 179 | Self: 'output; 180 | 181 | #[inline] 182 | fn get_mut(&mut self, input: Self::Input) -> Result, Self::Error> { 183 | _get_mut!(self.as_mut(), input) 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /cl-aux/src/traits/insert.rs: -------------------------------------------------------------------------------- 1 | #![allow( 2 | // `_manage_hash` is also used by BTreeMap 3 | clippy::map_entry 4 | )] 5 | 6 | macro_rules! _manage_hash { 7 | ($hash:expr, $key:expr, $value:expr) => {{ 8 | if $hash.contains_key(&$key) { 9 | Err(crate::Error::AlreadyExistingElement) 10 | } else { 11 | let _maybe_discarded = $hash.insert($key, $value); 12 | Ok(()) 13 | } 14 | }}; 15 | } 16 | 17 | macro_rules! _manage_set { 18 | ($set:expr, $value:expr) => {{ 19 | if $set.contains(&$value) { 20 | Err(crate::Error::AlreadyExistingElement) 21 | } else { 22 | let _ = $set.insert($value); 23 | Ok(()) 24 | } 25 | }}; 26 | } 27 | 28 | #[cfg(feature = "alloc")] 29 | use alloc::{ 30 | collections::{BTreeMap, BTreeSet}, 31 | vec::Vec, 32 | }; 33 | #[cfg(feature = "std")] 34 | use std::collections::{HashMap, HashSet}; 35 | 36 | /// See [`Insert::insert`] for more information. 37 | pub trait Insert { 38 | /// Error 39 | type Error; 40 | /// Input 41 | type Input; 42 | 43 | /// Inserts an `Input` element. 44 | fn insert(&mut self, input: Self::Input) -> Result<(), Self::Error>; 45 | } 46 | 47 | impl Insert for &mut T 48 | where 49 | T: Insert, 50 | { 51 | type Error = T::Error; 52 | type Input = T::Input; 53 | 54 | #[inline] 55 | fn insert(&mut self, input: Self::Input) -> Result<(), Self::Error> { 56 | (*self).insert(input) 57 | } 58 | } 59 | 60 | /// ```rust 61 | /// let mut structure = cl_aux::doc_tests::b_tree_map(); 62 | /// cl_aux::Insert::insert(&mut structure, (10, 100)); 63 | /// assert_eq!(structure.iter().find(|(k, v)| **k == 10), Some((&10, &100))); 64 | /// ``` 65 | #[cfg(feature = "alloc")] 66 | impl Insert for BTreeMap 67 | where 68 | K: Ord, 69 | { 70 | type Error = crate::Error; 71 | type Input = (K, V); 72 | 73 | #[inline] 74 | fn insert(&mut self, (key, val): Self::Input) -> Result<(), Self::Error> { 75 | _manage_hash!(self, key, val) 76 | } 77 | } 78 | 79 | /// ```rust 80 | /// let mut structure = cl_aux::doc_tests::b_tree_set(); 81 | /// cl_aux::Insert::insert(&mut structure, 10); 82 | /// assert_eq!(structure.iter().find(|&&e| e == 10), Some(&10)); 83 | /// ``` 84 | #[cfg(feature = "alloc")] 85 | impl Insert for BTreeSet 86 | where 87 | V: Ord, 88 | { 89 | type Error = crate::Error; 90 | type Input = V; 91 | 92 | #[inline] 93 | fn insert(&mut self, input: Self::Input) -> Result<(), Self::Error> { 94 | _manage_set!(self, input) 95 | } 96 | } 97 | 98 | /// ```rust 99 | /// let mut structure = cl_aux::doc_tests::hash_map(); 100 | /// cl_aux::Insert::insert(&mut structure, (10, 100)); 101 | /// assert_eq!(structure.iter().find(|(k, v)| **k == 10), Some((&10, &100))); 102 | /// ``` 103 | #[cfg(feature = "std")] 104 | impl Insert for HashMap 105 | where 106 | K: Eq + core::hash::Hash, 107 | S: core::hash::BuildHasher, 108 | { 109 | type Error = crate::Error; 110 | type Input = (K, V); 111 | 112 | #[inline] 113 | fn insert(&mut self, (k, v): Self::Input) -> Result<(), Self::Error> { 114 | _manage_hash!(self, k, v) 115 | } 116 | } 117 | 118 | /// ```rust 119 | /// let mut structure = cl_aux::doc_tests::hash_set(); 120 | /// cl_aux::Insert::insert(&mut structure, 10); 121 | /// assert_eq!(structure.iter().find(|&&e| e == 10), Some(&10)); 122 | /// ``` 123 | #[cfg(feature = "std")] 124 | impl Insert for HashSet 125 | where 126 | V: core::hash::Hash + Eq, 127 | S: core::hash::BuildHasher, 128 | { 129 | type Error = crate::Error; 130 | type Input = V; 131 | 132 | #[inline] 133 | fn insert(&mut self, v: Self::Input) -> Result<(), Self::Error> { 134 | _manage_set!(self, v) 135 | } 136 | } 137 | 138 | /// ```rust 139 | /// let mut opt = None; 140 | /// cl_aux::Insert::insert(&mut opt, 3); 141 | /// assert_eq!(opt, Some(3)); 142 | /// ``` 143 | impl Insert for Option { 144 | type Error = crate::Error; 145 | type Input = T; 146 | 147 | #[inline] 148 | fn insert(&mut self, input: Self::Input) -> Result<(), Self::Error> { 149 | if self.is_some() { 150 | Err(crate::Error::InsufficientCapacity(1)) 151 | } else { 152 | *self = Some(input); 153 | Ok(()) 154 | } 155 | } 156 | } 157 | 158 | /// ```rust 159 | /// let mut structure = cl_aux::doc_tests::vec(); 160 | /// cl_aux::Insert::insert(&mut structure, (0, 10)); 161 | /// assert_eq!(structure.get(0), Some(&10)); 162 | /// ``` 163 | #[cfg(feature = "alloc")] 164 | impl Insert for Vec { 165 | type Error = crate::Error; 166 | type Input = (usize, T); 167 | 168 | #[inline] 169 | fn insert(&mut self, (idx, elem): Self::Input) -> Result<(), Self::Error> { 170 | _check_indcs!(self, idx); 171 | self.insert(idx, elem); 172 | Ok(()) 173 | } 174 | } 175 | 176 | /// ```rust 177 | /// let mut structure = cl_aux::doc_tests::array_vec(); 178 | /// cl_aux::Insert::insert(&mut structure, (0, 10)); 179 | /// assert_eq!(structure.get(0), Some(&10)); 180 | /// ``` 181 | #[cfg(feature = "arrayvec")] 182 | impl Insert for arrayvec::ArrayVec { 183 | type Error = crate::Error; 184 | type Input = (usize, T); 185 | 186 | #[inline] 187 | fn insert(&mut self, (idx, elem): Self::Input) -> Result<(), Self::Error> { 188 | _check_indcs!(self, idx); 189 | self.insert(idx, elem); 190 | Ok(()) 191 | } 192 | } 193 | 194 | /// ```rust 195 | /// let mut structure = cl_aux::doc_tests::small_vec(); 196 | /// cl_aux::Insert::insert(&mut structure, (0, 10)); 197 | /// assert_eq!(structure.get(0), Some(&10)); 198 | /// ``` 199 | #[cfg(feature = "smallvec")] 200 | impl Insert for smallvec::SmallVec 201 | where 202 | A: smallvec::Array, 203 | { 204 | type Error = crate::Error; 205 | type Input = (usize, A::Item); 206 | 207 | #[inline] 208 | fn insert(&mut self, (idx, elem): Self::Input) -> Result<(), Self::Error> { 209 | _check_indcs!(self, idx); 210 | self.insert(idx, elem); 211 | Ok(()) 212 | } 213 | } 214 | 215 | /// ```rust 216 | /// let mut structure = cl_aux::doc_tests::tiny_vec_array_vec(); 217 | /// cl_aux::Insert::insert(&mut structure, (0, 10)); 218 | /// assert_eq!(structure.get(0), Some(&10)); 219 | /// ``` 220 | #[cfg(feature = "tinyvec")] 221 | impl Insert for tinyvec::ArrayVec 222 | where 223 | A: tinyvec::Array, 224 | A::Item: Default, 225 | { 226 | type Error = crate::Error; 227 | type Input = (usize, A::Item); 228 | 229 | #[inline] 230 | fn insert(&mut self, (idx, elem): Self::Input) -> Result<(), Self::Error> { 231 | _check_indcs!(self, idx); 232 | self.insert(idx, elem); 233 | Ok(()) 234 | } 235 | } 236 | 237 | /// ```rust 238 | /// let mut structure = cl_aux::doc_tests::tiny_vec_tiny_vec(); 239 | /// cl_aux::Insert::insert(&mut structure, (0, 10)); 240 | /// assert_eq!(structure.get(0), Some(&10)); 241 | /// ``` 242 | #[cfg(all(feature = "alloc", feature = "tinyvec"))] 243 | impl Insert for tinyvec::TinyVec 244 | where 245 | A: tinyvec::Array, 246 | A::Item: Default, 247 | { 248 | type Error = crate::Error; 249 | type Input = (usize, A::Item); 250 | 251 | #[inline] 252 | fn insert(&mut self, (idx, elem): Self::Input) -> Result<(), Self::Error> { 253 | _check_indcs!(self, idx); 254 | self.insert(idx, elem); 255 | Ok(()) 256 | } 257 | } 258 | -------------------------------------------------------------------------------- /cl-aux/src/traits/iter.rs: -------------------------------------------------------------------------------- 1 | use crate::SingleItemStorage; 2 | #[cfg(feature = "alloc")] 3 | use alloc::{string::String, vec::Vec}; 4 | use core::{option, slice}; 5 | 6 | /// See [`Iter::iter`] for more information. 7 | pub trait Iter { 8 | /// Iterator 9 | type Output<'iter>: Iterator 10 | where 11 | Self: 'iter; 12 | 13 | /// Returns a new iterator that refers inner elements. 14 | fn iter(&self) -> Self::Output<'_>; 15 | } 16 | 17 | impl Iter for &T 18 | where 19 | T: Iter, 20 | { 21 | type Output<'iter> = T::Output<'iter> 22 | where 23 | Self: 'iter; 24 | 25 | #[inline] 26 | fn iter(&self) -> Self::Output<'_> { 27 | (*self).iter() 28 | } 29 | } 30 | 31 | /// ```rust 32 | /// assert_eq!(cl_aux::Iter::iter(&()).next(), None); 33 | /// ``` 34 | impl Iter for () { 35 | type Output<'iter> = slice::Iter<'iter, ()>; 36 | 37 | #[inline] 38 | fn iter(&self) -> Self::Output<'_> { 39 | [].as_ref().iter() 40 | } 41 | } 42 | 43 | /// ```rust 44 | /// assert_eq!(cl_aux::Iter::iter(&Some(0)).next().unwrap(), &0); 45 | /// ``` 46 | impl Iter for Option { 47 | type Output<'iter> = option::Iter<'iter, T> 48 | where 49 | T: 'iter; 50 | 51 | #[inline] 52 | fn iter(&self) -> Self::Output<'_> { 53 | self.iter() 54 | } 55 | } 56 | 57 | /// ```rust 58 | /// let structure = cl_aux::doc_tests::single_item_storage(); 59 | /// assert_eq!(cl_aux::Iter::iter(&structure).next().unwrap(), &1); 60 | /// ``` 61 | impl Iter for SingleItemStorage { 62 | type Output<'iter> = slice::Iter<'iter, T> 63 | where 64 | T: 'iter; 65 | 66 | #[inline] 67 | fn iter(&self) -> Self::Output<'_> { 68 | slice::from_ref(&self.0).iter() 69 | } 70 | } 71 | 72 | /// ```rust 73 | /// let mut structure = cl_aux::doc_tests::array(); 74 | /// assert_eq!(cl_aux::Iter::iter(&structure).next().unwrap(), &1); 75 | /// ``` 76 | impl Iter for [T; N] { 77 | type Output<'iter> = slice::Iter<'iter, T> 78 | where 79 | T: 'iter; 80 | 81 | #[inline] 82 | fn iter(&self) -> Self::Output<'_> { 83 | self.as_ref().iter() 84 | } 85 | } 86 | 87 | /// ```rust 88 | /// let structure = cl_aux::doc_tests::slice(); 89 | /// assert_eq!(cl_aux::Iter::iter(&structure).next().unwrap(), &1); 90 | /// ``` 91 | impl Iter for &'_ [T] { 92 | type Output<'iter> = slice::Iter<'iter, T> 93 | where 94 | Self: 'iter; 95 | 96 | #[inline] 97 | fn iter(&self) -> Self::Output<'_> { 98 | self.as_ref().iter() 99 | } 100 | } 101 | 102 | /// ```rust 103 | /// let mut structure = cl_aux::doc_tests::string(); 104 | /// assert_eq!(cl_aux::Iter::iter(&structure).next().unwrap(), 'H'); 105 | /// ``` 106 | #[cfg(feature = "alloc")] 107 | impl Iter for String { 108 | type Output<'iter> = core::str::Chars<'iter>; 109 | 110 | #[inline] 111 | fn iter(&self) -> Self::Output<'_> { 112 | self.chars() 113 | } 114 | } 115 | 116 | /// ```rust 117 | /// let mut structure = cl_aux::doc_tests::vec(); 118 | /// assert_eq!(cl_aux::Iter::iter(&structure).next().unwrap(), &1); 119 | /// ``` 120 | #[cfg(feature = "alloc")] 121 | impl Iter for Vec { 122 | type Output<'iter> = slice::Iter<'iter, T> 123 | where 124 | T: 'iter; 125 | 126 | #[inline] 127 | fn iter(&self) -> Self::Output<'_> { 128 | self.as_slice().iter() 129 | } 130 | } 131 | 132 | /// ```rust 133 | /// let mut structure = cl_aux::doc_tests::array_string(); 134 | /// assert_eq!(cl_aux::Iter::iter(&structure).next().unwrap(), 'H'); 135 | /// ``` 136 | #[cfg(feature = "arrayvec")] 137 | impl Iter for arrayvec::ArrayString { 138 | type Output<'iter> = core::str::Chars<'iter>; 139 | 140 | #[inline] 141 | fn iter(&self) -> Self::Output<'_> { 142 | self.chars() 143 | } 144 | } 145 | 146 | /// ```rust 147 | /// let mut structure = cl_aux::doc_tests::array_vec(); 148 | /// assert_eq!(cl_aux::Iter::iter(&structure).next().unwrap(), &1); 149 | /// ``` 150 | #[cfg(feature = "arrayvec")] 151 | impl Iter for arrayvec::ArrayVec { 152 | type Output<'iter> = slice::Iter<'iter, T> 153 | where 154 | T: 'iter; 155 | 156 | #[inline] 157 | fn iter(&self) -> Self::Output<'_> { 158 | self.as_slice().iter() 159 | } 160 | } 161 | 162 | /// ```rust 163 | /// let mut structure = cl_aux::doc_tests::small_vec(); 164 | /// assert_eq!(cl_aux::Iter::iter(&structure).next().unwrap(), &1); 165 | /// ``` 166 | #[cfg(feature = "smallvec")] 167 | impl Iter for smallvec::SmallVec 168 | where 169 | A: smallvec::Array, 170 | { 171 | type Output<'iter> = slice::Iter<'iter, A::Item> 172 | where 173 | A: 'iter; 174 | 175 | #[inline] 176 | fn iter(&self) -> Self::Output<'_> { 177 | self.as_slice().iter() 178 | } 179 | } 180 | 181 | /// ```rust 182 | /// let mut structure = cl_aux::doc_tests::tiny_vec_array_vec(); 183 | /// assert_eq!(cl_aux::Iter::iter(&structure).next().unwrap(), &1); 184 | /// ``` 185 | #[cfg(feature = "tinyvec")] 186 | impl Iter for tinyvec::ArrayVec 187 | where 188 | A: tinyvec::Array, 189 | A::Item: Default, 190 | { 191 | type Output<'iter> = slice::Iter<'iter, A::Item> 192 | where 193 | A: 'iter; 194 | 195 | #[inline] 196 | fn iter(&self) -> Self::Output<'_> { 197 | self.as_slice().iter() 198 | } 199 | } 200 | 201 | /// ```rust 202 | /// let mut structure = cl_aux::doc_tests::tiny_vec_tiny_vec(); 203 | /// assert_eq!(cl_aux::Iter::iter(&structure).next().unwrap(), &1); 204 | /// ``` 205 | #[cfg(all(feature = "alloc", feature = "tinyvec"))] 206 | impl Iter for tinyvec::TinyVec 207 | where 208 | A: tinyvec::Array, 209 | A::Item: Default, 210 | { 211 | type Output<'iter> = slice::Iter<'iter, A::Item> 212 | where 213 | A: 'iter; 214 | 215 | #[inline] 216 | fn iter(&self) -> Self::Output<'_> { 217 | self.as_slice().iter() 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /cl-aux/src/traits/length.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "alloc")] 2 | use alloc::{ 3 | collections::{BTreeMap, BTreeSet}, 4 | string::String, 5 | vec::Vec, 6 | }; 7 | #[cfg(feature = "std")] 8 | use std::collections::{HashMap, HashSet}; 9 | 10 | use crate::SingleItemStorage; 11 | 12 | /// See [`Length::length`] for more information. 13 | pub trait Length { 14 | /// Holds a certain number of elements. 15 | fn length(&self) -> usize; 16 | } 17 | 18 | impl Length for &T 19 | where 20 | T: Length, 21 | { 22 | #[inline] 23 | fn length(&self) -> usize { 24 | (*self).length() 25 | } 26 | } 27 | 28 | /// ```rust 29 | /// assert_eq!(cl_aux::Length::length(&()), 0); 30 | /// ``` 31 | impl Length for () { 32 | #[inline] 33 | fn length(&self) -> usize { 34 | 0 35 | } 36 | } 37 | 38 | /// ```rust 39 | /// let mut opt = Some(0); 40 | /// assert_eq!(cl_aux::Length::length(&opt), 1); 41 | /// opt.take(); 42 | /// assert_eq!(cl_aux::Length::length(&opt), 0); 43 | /// ``` 44 | impl Length for Option { 45 | #[inline] 46 | fn length(&self) -> usize { 47 | usize::from(self.is_some()) 48 | } 49 | } 50 | 51 | /// ```rust 52 | /// let structure = cl_aux::doc_tests::single_item_storage(); 53 | /// assert_eq!(cl_aux::Length::length(&structure), 1); 54 | /// ``` 55 | impl Length for SingleItemStorage { 56 | #[inline] 57 | fn length(&self) -> usize { 58 | 1 59 | } 60 | } 61 | 62 | /// ```rust 63 | /// let structure = cl_aux::doc_tests::slice(); 64 | /// assert_eq!(cl_aux::Length::length(&structure), 3); 65 | /// ``` 66 | impl Length for &'_ [T] { 67 | #[inline] 68 | fn length(&self) -> usize { 69 | self.len() 70 | } 71 | } 72 | 73 | /// ```rust 74 | /// let mut structure = cl_aux::doc_tests::slice_mut!(); 75 | /// assert_eq!(cl_aux::Length::length(&mut structure), 3); 76 | /// ``` 77 | impl Length for &'_ mut [T] { 78 | #[inline] 79 | fn length(&self) -> usize { 80 | self.len() 81 | } 82 | } 83 | 84 | /// ```rust 85 | /// let structure = cl_aux::doc_tests::array(); 86 | /// assert_eq!(cl_aux::Length::length(&structure), 3); 87 | /// ``` 88 | impl Length for [T; N] { 89 | #[inline] 90 | fn length(&self) -> usize { 91 | self.len() 92 | } 93 | } 94 | 95 | /// ```rust 96 | /// let mut structure = cl_aux::doc_tests::b_tree_map(); 97 | /// assert_eq!(cl_aux::Length::length(&structure), 3); 98 | /// ``` 99 | #[cfg(feature = "alloc")] 100 | impl Length for BTreeMap { 101 | #[inline] 102 | fn length(&self) -> usize { 103 | self.len() 104 | } 105 | } 106 | 107 | /// ```rust 108 | /// let mut structure = cl_aux::doc_tests::b_tree_set(); 109 | /// assert_eq!(cl_aux::Length::length(&structure), 3); 110 | /// ``` 111 | #[cfg(feature = "alloc")] 112 | impl Length for BTreeSet { 113 | #[inline] 114 | fn length(&self) -> usize { 115 | self.len() 116 | } 117 | } 118 | 119 | /// ```rust 120 | /// let mut structure = cl_aux::doc_tests::hash_map(); 121 | /// assert_eq!(cl_aux::Length::length(&structure), 3); 122 | /// ``` 123 | #[cfg(feature = "std")] 124 | impl Length for HashMap 125 | where 126 | S: core::hash::BuildHasher, 127 | { 128 | #[inline] 129 | fn length(&self) -> usize { 130 | self.len() 131 | } 132 | } 133 | 134 | /// ```rust 135 | /// let mut structure = cl_aux::doc_tests::hash_set(); 136 | /// assert_eq!(cl_aux::Length::length(&structure), 3); 137 | /// ``` 138 | #[cfg(feature = "std")] 139 | impl Length for HashSet 140 | where 141 | S: core::hash::BuildHasher, 142 | { 143 | #[inline] 144 | fn length(&self) -> usize { 145 | self.len() 146 | } 147 | } 148 | 149 | /// ```rust 150 | /// let structure = cl_aux::doc_tests::string(); 151 | /// assert_eq!(cl_aux::Length::length(&structure), 5); 152 | /// ``` 153 | #[cfg(feature = "alloc")] 154 | impl Length for String { 155 | #[inline] 156 | fn length(&self) -> usize { 157 | self.len() 158 | } 159 | } 160 | 161 | /// ```rust 162 | /// let structure = cl_aux::doc_tests::vec(); 163 | /// assert_eq!(cl_aux::Length::length(&structure), 3); 164 | /// ``` 165 | #[cfg(feature = "alloc")] 166 | impl Length for Vec { 167 | #[inline] 168 | fn length(&self) -> usize { 169 | self.len() 170 | } 171 | } 172 | 173 | /// ```rust 174 | /// let structure = cl_aux::doc_tests::array_string(); 175 | /// assert_eq!(cl_aux::Length::length(&structure), 5); 176 | /// ``` 177 | #[cfg(feature = "arrayvec")] 178 | impl Length for arrayvec::ArrayString { 179 | #[inline] 180 | fn length(&self) -> usize { 181 | self.len() 182 | } 183 | } 184 | 185 | /// ```rust 186 | /// let structure = cl_aux::doc_tests::array_vec(); 187 | /// assert_eq!(cl_aux::Length::length(&structure), 3); 188 | /// ``` 189 | #[cfg(feature = "arrayvec")] 190 | impl Length for arrayvec::ArrayVec { 191 | #[inline] 192 | fn length(&self) -> usize { 193 | self.len() 194 | } 195 | } 196 | 197 | /// ```rust 198 | /// let structure = cl_aux::doc_tests::small_vec(); 199 | /// assert_eq!(cl_aux::Length::length(&structure), 3); 200 | /// ``` 201 | #[cfg(feature = "smallvec")] 202 | impl Length for smallvec::SmallVec 203 | where 204 | A: smallvec::Array, 205 | { 206 | #[inline] 207 | fn length(&self) -> usize { 208 | self.len() 209 | } 210 | } 211 | 212 | /// ```rust 213 | /// let structure = cl_aux::doc_tests::tiny_vec_array_vec(); 214 | /// assert_eq!(cl_aux::Length::length(&structure), 3); 215 | /// ``` 216 | #[cfg(feature = "tinyvec")] 217 | impl Length for tinyvec::ArrayVec 218 | where 219 | A: tinyvec::Array, 220 | A::Item: Default, 221 | { 222 | #[inline] 223 | fn length(&self) -> usize { 224 | self.len() 225 | } 226 | } 227 | 228 | /// ```rust 229 | /// let structure = cl_aux::doc_tests::tiny_vec_tiny_vec(); 230 | /// assert_eq!(cl_aux::Length::length(&structure), 3); 231 | /// ``` 232 | #[cfg(all(feature = "alloc", feature = "tinyvec"))] 233 | impl Length for tinyvec::TinyVec 234 | where 235 | A: tinyvec::Array, 236 | A::Item: Default, 237 | { 238 | #[inline] 239 | fn length(&self) -> usize { 240 | self.len() 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /cl-aux/src/traits/push.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "alloc")] 2 | use alloc::{string::String, vec::Vec}; 3 | 4 | /// See [`Push::push`] for more information. 5 | pub trait Push { 6 | /// Error 7 | type Error; 8 | 9 | /// Pushes an element, increasing the storage length. 10 | fn push(&mut self, input: I) -> Result<(), Self::Error>; 11 | } 12 | 13 | impl Push for &mut T 14 | where 15 | T: Push, 16 | { 17 | type Error = T::Error; 18 | 19 | #[inline] 20 | fn push(&mut self, input: I) -> Result<(), Self::Error> { 21 | (*self).push(input) 22 | } 23 | } 24 | 25 | /// ```rust 26 | /// let mut opt = None; 27 | /// cl_aux::Push::push(&mut opt, 3); 28 | /// assert_eq!(opt, Some(3)); 29 | /// ``` 30 | impl Push for () { 31 | type Error = crate::Error; 32 | 33 | #[inline] 34 | fn push(&mut self, _: T) -> Result<(), Self::Error> { 35 | Ok(()) 36 | } 37 | } 38 | 39 | /// ```rust 40 | /// let mut opt = None; 41 | /// cl_aux::Push::push(&mut opt, 3); 42 | /// assert_eq!(opt, Some(3)); 43 | /// ``` 44 | impl Push for Option { 45 | type Error = crate::Error; 46 | 47 | #[inline] 48 | fn push(&mut self, input: T) -> Result<(), Self::Error> { 49 | if self.is_some() { 50 | Err(crate::Error::InsufficientCapacity(1)) 51 | } else { 52 | *self = Some(input); 53 | Ok(()) 54 | } 55 | } 56 | } 57 | 58 | /// ```rust 59 | /// let mut structure = cl_aux::doc_tests::string(); 60 | /// cl_aux::Push::push(&mut structure, '!'); 61 | /// assert_eq!(structure.as_str(), "Hello!"); 62 | /// ``` 63 | #[cfg(feature = "alloc")] 64 | impl Push for String { 65 | type Error = crate::Error; 66 | 67 | #[inline] 68 | fn push(&mut self, input: char) -> Result<(), Self::Error> { 69 | _check_capacity!(self); 70 | self.push(input); 71 | Ok(()) 72 | } 73 | } 74 | 75 | /// ```rust 76 | /// let mut structure = cl_aux::doc_tests::string(); 77 | /// cl_aux::Push::push(&mut structure, "!!"); 78 | /// assert_eq!(structure.as_str(), "Hello!!"); 79 | /// ``` 80 | #[cfg(feature = "alloc")] 81 | impl<'input> Push<&'input str> for String { 82 | type Error = crate::Error; 83 | 84 | #[inline] 85 | fn push(&mut self, input: &'input str) -> Result<(), Self::Error> { 86 | _check_capacity!(self); 87 | self.push_str(input); 88 | Ok(()) 89 | } 90 | } 91 | 92 | /// ```rust 93 | /// let mut structure = cl_aux::doc_tests::vec(); 94 | /// cl_aux::Push::push(&mut structure, 20); 95 | /// assert_eq!(structure.get(3), Some(&20)); 96 | /// ``` 97 | #[cfg(feature = "alloc")] 98 | impl Push for Vec { 99 | type Error = crate::Error; 100 | 101 | #[inline] 102 | fn push(&mut self, input: T) -> Result<(), Self::Error> { 103 | _check_capacity!(self); 104 | self.push(input); 105 | Ok(()) 106 | } 107 | } 108 | 109 | /// ```rust 110 | /// let mut structure = cl_aux::doc_tests::array_string(); 111 | /// cl_aux::Push::push(&mut structure, '!'); 112 | /// assert_eq!(structure.as_str(), "Hello!"); 113 | /// ``` 114 | #[cfg(feature = "arrayvec")] 115 | impl Push for arrayvec::ArrayString { 116 | type Error = crate::Error; 117 | 118 | #[inline] 119 | fn push(&mut self, input: char) -> Result<(), Self::Error> { 120 | _check_capacity!(self); 121 | self.push(input); 122 | Ok(()) 123 | } 124 | } 125 | 126 | /// ```rust 127 | /// let mut structure = cl_aux::doc_tests::array_string(); 128 | /// cl_aux::Push::push(&mut structure, "!!"); 129 | /// assert_eq!(structure.as_str(), "Hello!!"); 130 | /// ``` 131 | #[cfg(feature = "arrayvec")] 132 | impl<'input, const N: usize> Push<&'input str> for arrayvec::ArrayString { 133 | type Error = crate::Error; 134 | 135 | #[inline] 136 | fn push(&mut self, input: &'input str) -> Result<(), Self::Error> { 137 | _check_capacity!(self); 138 | self.push_str(input); 139 | Ok(()) 140 | } 141 | } 142 | 143 | /// ```rust 144 | /// let mut structure = cl_aux::doc_tests::array_vec(); 145 | /// cl_aux::Push::push(&mut structure, 20); 146 | /// assert_eq!(structure.get(3), Some(&20)); 147 | /// ``` 148 | #[cfg(feature = "arrayvec")] 149 | impl Push for arrayvec::ArrayVec { 150 | type Error = crate::Error; 151 | 152 | #[inline] 153 | fn push(&mut self, input: T) -> Result<(), Self::Error> { 154 | _check_capacity!(self); 155 | self.push(input); 156 | Ok(()) 157 | } 158 | } 159 | 160 | /// ```rust 161 | /// let mut structure = cl_aux::doc_tests::small_vec(); 162 | /// cl_aux::Push::push(&mut structure, 20); 163 | /// assert_eq!(structure.get(3), Some(&20)); 164 | /// ``` 165 | #[cfg(feature = "smallvec")] 166 | impl Push for smallvec::SmallVec 167 | where 168 | A: smallvec::Array, 169 | { 170 | type Error = crate::Error; 171 | 172 | #[inline] 173 | fn push(&mut self, input: A::Item) -> Result<(), Self::Error> { 174 | _check_capacity!(self); 175 | self.push(input); 176 | Ok(()) 177 | } 178 | } 179 | 180 | /// ```rust 181 | /// let mut structure = cl_aux::doc_tests::tiny_vec_array_vec(); 182 | /// cl_aux::Push::push(&mut structure, 20); 183 | /// assert_eq!(structure.get(3), Some(&20)); 184 | /// ``` 185 | #[cfg(feature = "tinyvec")] 186 | impl Push for tinyvec::ArrayVec 187 | where 188 | A: tinyvec::Array, 189 | A::Item: Default, 190 | { 191 | type Error = crate::Error; 192 | 193 | #[inline] 194 | fn push(&mut self, input: A::Item) -> Result<(), Self::Error> { 195 | _check_capacity!(self); 196 | self.push(input); 197 | Ok(()) 198 | } 199 | } 200 | 201 | /// ```rust 202 | /// let mut structure = cl_aux::doc_tests::tiny_vec_tiny_vec(); 203 | /// cl_aux::Push::push(&mut structure, 20); 204 | /// assert_eq!(structure.get(3), Some(&20)); 205 | /// ``` 206 | #[cfg(all(feature = "alloc", feature = "tinyvec"))] 207 | impl Push for tinyvec::TinyVec 208 | where 209 | A: tinyvec::Array, 210 | A::Item: Default, 211 | { 212 | type Error = crate::Error; 213 | 214 | #[inline] 215 | fn push(&mut self, input: A::Item) -> Result<(), Self::Error> { 216 | _check_capacity!(self); 217 | self.push(input); 218 | Ok(()) 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /cl-aux/src/traits/remove.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "alloc")] 2 | use alloc::vec::Vec; 3 | 4 | /// See [`Remove::remove`] for more information. 5 | pub trait Remove { 6 | /// Error 7 | type Error; 8 | /// Input 9 | type Input; 10 | /// Output 11 | type Output; 12 | 13 | /// Removes an element referenced by `Input`. 14 | fn remove(&mut self, input: Self::Input) -> Result; 15 | } 16 | 17 | impl Remove for &mut T 18 | where 19 | T: Remove, 20 | { 21 | type Error = T::Error; 22 | type Input = T::Input; 23 | type Output = T::Output; 24 | 25 | #[inline] 26 | fn remove(&mut self, input: Self::Input) -> Result { 27 | (*self).remove(input) 28 | } 29 | } 30 | 31 | /// ```rust 32 | /// let mut structure = cl_aux::doc_tests::vec(); 33 | /// cl_aux::Remove::remove(&mut structure, 0); 34 | /// assert_eq!(structure.get(0), Some(&2)); 35 | /// ``` 36 | #[cfg(feature = "alloc")] 37 | impl Remove for Vec { 38 | type Error = crate::Error; 39 | type Input = usize; 40 | type Output = T; 41 | 42 | #[inline] 43 | fn remove(&mut self, input: Self::Input) -> Result { 44 | _check_indcs!(self, input); 45 | Ok(self.remove(input)) 46 | } 47 | } 48 | 49 | /// ```rust 50 | /// let mut structure = cl_aux::doc_tests::array_vec(); 51 | /// cl_aux::Remove::remove(&mut structure, 0); 52 | /// assert_eq!(structure.get(0), Some(&2)); 53 | /// ``` 54 | #[cfg(feature = "arrayvec")] 55 | impl Remove for arrayvec::ArrayVec { 56 | type Error = crate::Error; 57 | type Input = usize; 58 | type Output = T; 59 | 60 | #[inline] 61 | fn remove(&mut self, input: Self::Input) -> Result { 62 | _check_indcs!(self, input); 63 | Ok(self.remove(input)) 64 | } 65 | } 66 | 67 | /// ```rust 68 | /// let mut structure = cl_aux::doc_tests::small_vec(); 69 | /// cl_aux::Remove::remove(&mut structure, 0); 70 | /// assert_eq!(structure.get(0), Some(&2)); 71 | /// ``` 72 | #[cfg(feature = "smallvec")] 73 | impl Remove for smallvec::SmallVec 74 | where 75 | A: smallvec::Array, 76 | { 77 | type Error = crate::Error; 78 | type Input = usize; 79 | type Output = A::Item; 80 | 81 | #[inline] 82 | fn remove(&mut self, input: Self::Input) -> Result { 83 | _check_indcs!(self, input); 84 | Ok(self.remove(input)) 85 | } 86 | } 87 | 88 | /// ```rust 89 | /// let mut structure = cl_aux::doc_tests::tiny_vec_array_vec(); 90 | /// cl_aux::Remove::remove(&mut structure, 0); 91 | /// assert_eq!(structure.get(0), Some(&2)); 92 | /// ``` 93 | #[cfg(feature = "tinyvec")] 94 | impl Remove for tinyvec::ArrayVec 95 | where 96 | A: tinyvec::Array, 97 | A::Item: Default, 98 | { 99 | type Error = crate::Error; 100 | type Input = usize; 101 | type Output = A::Item; 102 | 103 | #[inline] 104 | fn remove(&mut self, input: Self::Input) -> Result { 105 | _check_indcs!(self, input); 106 | Ok(self.remove(input)) 107 | } 108 | } 109 | 110 | /// ```rust 111 | /// let mut structure = cl_aux::doc_tests::tiny_vec_tiny_vec(); 112 | /// cl_aux::Remove::remove(&mut structure, 0); 113 | /// assert_eq!(structure.get(0), Some(&2)); 114 | /// ``` 115 | #[cfg(all(feature = "alloc", feature = "tinyvec"))] 116 | impl Remove for tinyvec::TinyVec 117 | where 118 | A: tinyvec::Array, 119 | A::Item: Default, 120 | { 121 | type Error = crate::Error; 122 | type Input = usize; 123 | type Output = A::Item; 124 | 125 | #[inline] 126 | fn remove(&mut self, input: Self::Input) -> Result { 127 | _check_indcs!(self, input); 128 | Ok(self.remove(input)) 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /cl-aux/src/traits/retain.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "alloc")] 2 | use alloc::vec::Vec; 3 | 4 | /// See [`Retain::retain`] for more information. 5 | pub trait Retain { 6 | /// Input 7 | type Input; 8 | 9 | /// Retains only the elements specified by the `F` predicate. 10 | fn retain(&mut self, input: Self::Input); 11 | } 12 | 13 | impl Retain for &mut T 14 | where 15 | T: Retain, 16 | { 17 | type Input = T::Input; 18 | 19 | #[inline] 20 | fn retain(&mut self, input: Self::Input) { 21 | (*self).retain(input); 22 | } 23 | } 24 | 25 | /// ```rust 26 | /// let mut opt = Some(1); 27 | /// cl_aux::Retain::retain(&mut opt, |n| n % 2 == 0); 28 | /// assert_eq!(opt, None); 29 | /// ``` 30 | impl Retain for Option { 31 | type Input = fn(&T) -> bool; 32 | 33 | #[inline] 34 | fn retain(&mut self, input: Self::Input) { 35 | if let Some(elem) = self.as_mut() { 36 | if !input(elem) { 37 | *self = None; 38 | } 39 | } 40 | } 41 | } 42 | 43 | /// ```rust 44 | /// let mut structure = cl_aux::doc_tests::vec(); 45 | /// cl_aux::Retain::retain(&mut structure, |n| n % 2 == 0); 46 | /// assert_eq!(&structure, &[2]); 47 | /// ``` 48 | #[cfg(feature = "alloc")] 49 | impl Retain for Vec { 50 | type Input = fn(&T) -> bool; 51 | 52 | #[inline] 53 | fn retain(&mut self, input: Self::Input) { 54 | self.retain(input); 55 | } 56 | } 57 | 58 | /// ```rust 59 | /// let mut structure = cl_aux::doc_tests::array_vec(); 60 | /// cl_aux::Retain::retain(&mut structure, |n| n % 2 == 0); 61 | /// assert_eq!(&structure[..], &[2]); 62 | /// ``` 63 | #[cfg(feature = "arrayvec")] 64 | impl Retain for arrayvec::ArrayVec { 65 | type Input = fn(&T) -> bool; 66 | 67 | #[inline] 68 | fn retain(&mut self, input: Self::Input) { 69 | self.retain(|i| input(i)); 70 | } 71 | } 72 | 73 | /// ```rust 74 | /// let mut structure = cl_aux::doc_tests::small_vec(); 75 | /// cl_aux::Retain::retain(&mut structure, |n| n % 2 == 0); 76 | /// assert_eq!(&structure[..], &[2]); 77 | /// ``` 78 | #[cfg(feature = "smallvec")] 79 | impl Retain for smallvec::SmallVec 80 | where 81 | A: smallvec::Array, 82 | { 83 | type Input = fn(&A::Item) -> bool; 84 | 85 | #[inline] 86 | fn retain(&mut self, input: Self::Input) { 87 | self.retain(|i| input(i)); 88 | } 89 | } 90 | 91 | /// ```rust 92 | /// let mut structure = cl_aux::doc_tests::tiny_vec_array_vec(); 93 | /// cl_aux::Retain::retain(&mut structure, |n| n % 2 == 0); 94 | /// assert_eq!(&structure[..], &[2]); 95 | /// ``` 96 | #[cfg(feature = "tinyvec")] 97 | impl Retain for tinyvec::ArrayVec 98 | where 99 | A: tinyvec::Array, 100 | A::Item: Default, 101 | { 102 | type Input = fn(&A::Item) -> bool; 103 | 104 | #[inline] 105 | fn retain(&mut self, input: Self::Input) { 106 | self.retain(input); 107 | } 108 | } 109 | 110 | /// ```rust 111 | /// let mut structure = cl_aux::doc_tests::tiny_vec_tiny_vec(); 112 | /// cl_aux::Retain::retain(&mut structure, |n| n % 2 == 0); 113 | /// assert_eq!(&structure[..], &[2]); 114 | /// ``` 115 | #[cfg(all(feature = "alloc", feature = "tinyvec"))] 116 | impl Retain for tinyvec::TinyVec 117 | where 118 | A: tinyvec::Array, 119 | A::Item: Default, 120 | { 121 | type Input = fn(&A::Item) -> bool; 122 | 123 | #[inline] 124 | fn retain(&mut self, input: Self::Input) { 125 | self.retain(input); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /cl-aux/src/traits/single_type_storage.rs: -------------------------------------------------------------------------------- 1 | use crate::SingleItemStorage; 2 | #[cfg(feature = "alloc")] 3 | use alloc::vec::Vec; 4 | 5 | /// Anything that can hold a collection of items 6 | pub trait SingleTypeStorage { 7 | /// Storage item 8 | type Item; 9 | } 10 | 11 | impl SingleTypeStorage for &T 12 | where 13 | T: SingleTypeStorage, 14 | { 15 | type Item = T::Item; 16 | } 17 | 18 | impl SingleTypeStorage for &mut T 19 | where 20 | T: SingleTypeStorage, 21 | { 22 | type Item = T::Item; 23 | } 24 | 25 | impl SingleTypeStorage for Option { 26 | type Item = T; 27 | } 28 | 29 | impl SingleTypeStorage for SingleItemStorage { 30 | type Item = T; 31 | } 32 | 33 | impl SingleTypeStorage for [T; N] { 34 | type Item = T; 35 | } 36 | 37 | impl SingleTypeStorage for &'_ [T] { 38 | type Item = T; 39 | } 40 | 41 | impl SingleTypeStorage for &'_ mut [T] { 42 | type Item = T; 43 | } 44 | 45 | #[cfg(feature = "alloc")] 46 | impl SingleTypeStorage for Vec { 47 | type Item = T; 48 | } 49 | 50 | #[cfg(feature = "arrayvec")] 51 | impl SingleTypeStorage for arrayvec::ArrayVec { 52 | type Item = T; 53 | } 54 | 55 | #[cfg(feature = "smallvec")] 56 | impl SingleTypeStorage for smallvec::SmallVec 57 | where 58 | A: smallvec::Array, 59 | { 60 | type Item = A::Item; 61 | } 62 | 63 | #[cfg(feature = "tinyvec")] 64 | impl SingleTypeStorage for tinyvec::ArrayVec 65 | where 66 | A: tinyvec::Array, 67 | A::Item: Default, 68 | { 69 | type Item = A::Item; 70 | } 71 | 72 | #[cfg(all(feature = "alloc", feature = "tinyvec"))] 73 | impl SingleTypeStorage for tinyvec::TinyVec 74 | where 75 | A: tinyvec::Array, 76 | A::Item: Default, 77 | { 78 | type Item = A::Item; 79 | } 80 | -------------------------------------------------------------------------------- /cl-aux/src/traits/size_hint.rs: -------------------------------------------------------------------------------- 1 | use crate::{IterWrapper, Length, SingleItemStorage}; 2 | #[cfg(feature = "alloc")] 3 | use alloc::{ 4 | collections::{BTreeMap, BTreeSet}, 5 | string::String, 6 | vec::Vec, 7 | }; 8 | #[cfg(feature = "std")] 9 | use std::collections::{HashMap, HashSet}; 10 | 11 | /// See [`SizeHint::size_hint`] for more information. 12 | pub trait SizeHint { 13 | /// Has the same semantics of [`Iterator::size_hint`]. 14 | fn size_hint(&self) -> (usize, Option); 15 | } 16 | 17 | impl SizeHint for &T 18 | where 19 | T: SizeHint, 20 | { 21 | #[inline] 22 | fn size_hint(&self) -> (usize, Option) { 23 | (*self).size_hint() 24 | } 25 | } 26 | 27 | impl SizeHint for IterWrapper 28 | where 29 | T: Iterator, 30 | { 31 | #[inline] 32 | fn size_hint(&self) -> (usize, Option) { 33 | self.0.size_hint() 34 | } 35 | } 36 | 37 | /// ```rust 38 | /// assert_eq!(cl_aux::SizeHint::size_hint(&()), (0, Some(0))); 39 | /// ``` 40 | impl SizeHint for () { 41 | #[inline] 42 | fn size_hint(&self) -> (usize, Option) { 43 | (0, Some(0)) 44 | } 45 | } 46 | 47 | /// ```rust 48 | /// let mut opt = Some(0); 49 | /// assert_eq!(cl_aux::SizeHint::size_hint(&opt), (1, Some(1))); 50 | /// opt.take(); 51 | /// assert_eq!(cl_aux::SizeHint::size_hint(&opt), (0, Some(0))); 52 | /// ``` 53 | impl SizeHint for Option { 54 | #[inline] 55 | fn size_hint(&self) -> (usize, Option) { 56 | (self.length(), Some(self.length())) 57 | } 58 | } 59 | 60 | /// ```rust 61 | /// let structure = cl_aux::doc_tests::single_item_storage(); 62 | /// assert_eq!(cl_aux::SizeHint::size_hint(&structure), (1, Some(1))); 63 | /// ``` 64 | impl SizeHint for SingleItemStorage { 65 | #[inline] 66 | fn size_hint(&self) -> (usize, Option) { 67 | (1, Some(1)) 68 | } 69 | } 70 | 71 | /// ```rust 72 | /// let structure = cl_aux::doc_tests::slice(); 73 | /// assert_eq!(cl_aux::SizeHint::size_hint(&structure), (3, Some(3))); 74 | /// ``` 75 | impl SizeHint for [T] { 76 | #[inline] 77 | fn size_hint(&self) -> (usize, Option) { 78 | (self.len(), Some(self.len())) 79 | } 80 | } 81 | 82 | /// ```rust 83 | /// let structure = cl_aux::doc_tests::slice(); 84 | /// assert_eq!(cl_aux::SizeHint::size_hint(&structure), (3, Some(3))); 85 | /// ``` 86 | impl SizeHint for &'_ [T] { 87 | #[inline] 88 | fn size_hint(&self) -> (usize, Option) { 89 | (self.len(), Some(self.len())) 90 | } 91 | } 92 | 93 | /// ```rust 94 | /// let mut structure = cl_aux::doc_tests::slice_mut!(); 95 | /// assert_eq!(cl_aux::SizeHint::size_hint(&mut structure), (3, Some(3))); 96 | /// ``` 97 | impl SizeHint for &'_ mut [T] { 98 | #[inline] 99 | fn size_hint(&self) -> (usize, Option) { 100 | (self.len(), Some(self.len())) 101 | } 102 | } 103 | 104 | /// ```rust 105 | /// let structure = cl_aux::doc_tests::array(); 106 | /// assert_eq!(cl_aux::SizeHint::size_hint(&structure), (3, Some(3))); 107 | /// ``` 108 | impl SizeHint for [T; N] { 109 | #[inline] 110 | fn size_hint(&self) -> (usize, Option) { 111 | (self.len(), Some(self.len())) 112 | } 113 | } 114 | 115 | /// ```rust 116 | /// let mut structure = cl_aux::doc_tests::b_tree_map(); 117 | /// assert_eq!(cl_aux::SizeHint::size_hint(&structure), (3, Some(3))); 118 | /// ``` 119 | #[cfg(feature = "alloc")] 120 | impl SizeHint for BTreeMap { 121 | #[inline] 122 | fn size_hint(&self) -> (usize, Option) { 123 | (self.len(), Some(self.len())) 124 | } 125 | } 126 | 127 | /// ```rust 128 | /// let mut structure = cl_aux::doc_tests::b_tree_set(); 129 | /// assert_eq!(cl_aux::SizeHint::size_hint(&structure), (3, Some(3))); 130 | /// ``` 131 | #[cfg(feature = "alloc")] 132 | impl SizeHint for BTreeSet { 133 | #[inline] 134 | fn size_hint(&self) -> (usize, Option) { 135 | (self.len(), Some(self.len())) 136 | } 137 | } 138 | 139 | /// ```rust 140 | /// let mut structure = cl_aux::doc_tests::hash_map(); 141 | /// assert_eq!(cl_aux::SizeHint::size_hint(&structure), (3, Some(3))); 142 | /// ``` 143 | #[cfg(feature = "std")] 144 | impl SizeHint for HashMap 145 | where 146 | S: core::hash::BuildHasher, 147 | { 148 | #[inline] 149 | fn size_hint(&self) -> (usize, Option) { 150 | (self.len(), Some(self.len())) 151 | } 152 | } 153 | 154 | /// ```rust 155 | /// let mut structure = cl_aux::doc_tests::hash_set(); 156 | /// assert_eq!(cl_aux::SizeHint::size_hint(&structure), (3, Some(3))); 157 | /// ``` 158 | #[cfg(feature = "std")] 159 | impl SizeHint for HashSet 160 | where 161 | S: core::hash::BuildHasher, 162 | { 163 | #[inline] 164 | fn size_hint(&self) -> (usize, Option) { 165 | (self.len(), Some(self.len())) 166 | } 167 | } 168 | 169 | /// ```rust 170 | /// let structure = cl_aux::doc_tests::string(); 171 | /// assert_eq!(cl_aux::SizeHint::size_hint(&structure), (5, Some(5))); 172 | /// ``` 173 | #[cfg(feature = "alloc")] 174 | impl SizeHint for String { 175 | #[inline] 176 | fn size_hint(&self) -> (usize, Option) { 177 | (self.len(), Some(self.len())) 178 | } 179 | } 180 | 181 | /// ```rust 182 | /// let structure = cl_aux::doc_tests::vec(); 183 | /// assert_eq!(cl_aux::SizeHint::size_hint(&structure), (3, Some(3))); 184 | /// ``` 185 | #[cfg(feature = "alloc")] 186 | impl SizeHint for Vec { 187 | #[inline] 188 | fn size_hint(&self) -> (usize, Option) { 189 | (self.len(), Some(self.len())) 190 | } 191 | } 192 | 193 | /// ```rust 194 | /// let structure = cl_aux::doc_tests::array_string(); 195 | /// assert_eq!(cl_aux::SizeHint::size_hint(&structure), (5, Some(5))); 196 | /// ``` 197 | #[cfg(feature = "arrayvec")] 198 | impl SizeHint for arrayvec::ArrayString { 199 | #[inline] 200 | fn size_hint(&self) -> (usize, Option) { 201 | (self.len(), Some(self.len())) 202 | } 203 | } 204 | 205 | /// ```rust 206 | /// let structure = cl_aux::doc_tests::array_vec(); 207 | /// assert_eq!(cl_aux::SizeHint::size_hint(&structure), (3, Some(3))); 208 | /// ``` 209 | #[cfg(feature = "arrayvec")] 210 | impl SizeHint for arrayvec::ArrayVec { 211 | #[inline] 212 | fn size_hint(&self) -> (usize, Option) { 213 | (self.len(), Some(self.len())) 214 | } 215 | } 216 | 217 | /// ```rust 218 | /// let structure = cl_aux::doc_tests::small_vec(); 219 | /// assert_eq!(cl_aux::SizeHint::size_hint(&structure), (3, Some(3))); 220 | /// ``` 221 | #[cfg(feature = "smallvec")] 222 | impl SizeHint for smallvec::SmallVec 223 | where 224 | A: smallvec::Array, 225 | { 226 | #[inline] 227 | fn size_hint(&self) -> (usize, Option) { 228 | (self.len(), Some(self.len())) 229 | } 230 | } 231 | 232 | /// ```rust 233 | /// let structure = cl_aux::doc_tests::tiny_vec_array_vec(); 234 | /// assert_eq!(cl_aux::SizeHint::size_hint(&structure), (3, Some(3))); 235 | /// ``` 236 | #[cfg(feature = "tinyvec")] 237 | impl SizeHint for tinyvec::ArrayVec 238 | where 239 | A: tinyvec::Array, 240 | A::Item: Default, 241 | { 242 | #[inline] 243 | fn size_hint(&self) -> (usize, Option) { 244 | (self.len(), Some(self.len())) 245 | } 246 | } 247 | 248 | /// ```rust 249 | /// let structure = cl_aux::doc_tests::tiny_vec_tiny_vec(); 250 | /// assert_eq!(cl_aux::SizeHint::size_hint(&structure), (3, Some(3))); 251 | /// ``` 252 | #[cfg(all(feature = "alloc", feature = "tinyvec"))] 253 | impl SizeHint for tinyvec::TinyVec 254 | where 255 | A: tinyvec::Array, 256 | A::Item: Default, 257 | { 258 | #[inline] 259 | fn size_hint(&self) -> (usize, Option) { 260 | (self.len(), Some(self.len())) 261 | } 262 | } 263 | -------------------------------------------------------------------------------- /cl-aux/src/traits/swap.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "alloc")] 2 | use alloc::vec::Vec; 3 | 4 | /// See [`Swap::swap`] for more information. 5 | pub trait Swap { 6 | /// Error 7 | type Error; 8 | /// Input 9 | type Input; 10 | 11 | /// Swaps two elements referencied by `Input`. 12 | fn swap(&mut self, input: Self::Input) -> Result<(), Self::Error>; 13 | } 14 | 15 | impl Swap for &mut T 16 | where 17 | T: Swap, 18 | { 19 | type Error = T::Error; 20 | type Input = T::Input; 21 | 22 | #[inline] 23 | fn swap(&mut self, input: Self::Input) -> Result<(), Self::Error> { 24 | (*self).swap(input) 25 | } 26 | } 27 | 28 | /// ```rust 29 | /// let mut structure = cl_aux::doc_tests::array(); 30 | /// cl_aux::Swap::swap(&mut structure, [0, 2]); 31 | /// assert_eq!(structure.get(0), Some(&3)); 32 | /// assert_eq!(structure.get(2), Some(&1)); 33 | /// ``` 34 | impl Swap for [T; N] { 35 | type Error = crate::Error; 36 | type Input = [usize; 2]; 37 | 38 | #[inline] 39 | fn swap(&mut self, [a, b]: Self::Input) -> Result<(), Self::Error> { 40 | manage_slice(self, a, b) 41 | } 42 | } 43 | 44 | /// ```rust 45 | /// let mut structure = cl_aux::doc_tests::slice_mut!(); 46 | /// cl_aux::Swap::swap(&mut structure, [0, 2]); 47 | /// assert_eq!(structure.get(0), Some(&3)); 48 | /// assert_eq!(structure.get(2), Some(&1)); 49 | /// ``` 50 | impl Swap for &'_ mut [T] { 51 | type Error = crate::Error; 52 | type Input = [usize; 2]; 53 | 54 | #[inline] 55 | fn swap(&mut self, [a, b]: Self::Input) -> Result<(), Self::Error> { 56 | manage_slice(self, a, b) 57 | } 58 | } 59 | 60 | /// ```rust 61 | /// let mut structure = cl_aux::doc_tests::vec(); 62 | /// cl_aux::Swap::swap(&mut structure, [0, 2]); 63 | /// assert_eq!(structure.get(0), Some(&3)); 64 | /// assert_eq!(structure.get(2), Some(&1)); 65 | /// ``` 66 | #[cfg(feature = "alloc")] 67 | impl Swap for Vec { 68 | type Error = crate::Error; 69 | type Input = [usize; 2]; 70 | 71 | #[inline] 72 | fn swap(&mut self, [a, b]: Self::Input) -> Result<(), Self::Error> { 73 | manage_slice(self, a, b) 74 | } 75 | } 76 | 77 | /// ```rust 78 | /// let mut structure = cl_aux::doc_tests::array_vec(); 79 | /// cl_aux::Swap::swap(&mut structure, [0, 2]); 80 | /// assert_eq!(structure.get(0), Some(&3)); 81 | /// assert_eq!(structure.get(2), Some(&1)); 82 | /// ``` 83 | #[cfg(feature = "arrayvec")] 84 | impl Swap for arrayvec::ArrayVec { 85 | type Error = crate::Error; 86 | type Input = [usize; 2]; 87 | 88 | #[inline] 89 | fn swap(&mut self, [a, b]: Self::Input) -> Result<(), Self::Error> { 90 | manage_slice(self, a, b) 91 | } 92 | } 93 | 94 | /// ```rust 95 | /// let mut structure = cl_aux::doc_tests::small_vec(); 96 | /// cl_aux::Swap::swap(&mut structure, [0, 2]); 97 | /// assert_eq!(structure.get(0), Some(&3)); 98 | /// assert_eq!(structure.get(2), Some(&1)); 99 | /// ``` 100 | #[cfg(feature = "smallvec")] 101 | impl Swap for smallvec::SmallVec 102 | where 103 | A: smallvec::Array, 104 | { 105 | type Error = crate::Error; 106 | type Input = [usize; 2]; 107 | 108 | #[inline] 109 | fn swap(&mut self, [a, b]: Self::Input) -> Result<(), Self::Error> { 110 | manage_slice(self, a, b) 111 | } 112 | } 113 | 114 | /// ```rust 115 | /// let mut structure = cl_aux::doc_tests::tiny_vec_array_vec(); 116 | /// cl_aux::Swap::swap(&mut structure, [0, 2]); 117 | /// assert_eq!(structure.get(0), Some(&3)); 118 | /// assert_eq!(structure.get(2), Some(&1)); 119 | /// ``` 120 | #[cfg(feature = "tinyvec")] 121 | impl Swap for tinyvec::ArrayVec 122 | where 123 | A: tinyvec::Array, 124 | A::Item: Default, 125 | { 126 | type Error = crate::Error; 127 | type Input = [usize; 2]; 128 | 129 | #[inline] 130 | fn swap(&mut self, [a, b]: Self::Input) -> Result<(), Self::Error> { 131 | manage_slice(self, a, b) 132 | } 133 | } 134 | 135 | /// ```rust 136 | /// let mut structure = cl_aux::doc_tests::tiny_vec_tiny_vec(); 137 | /// cl_aux::Swap::swap(&mut structure, [0, 2]); 138 | /// assert_eq!(structure.get(0), Some(&3)); 139 | /// assert_eq!(structure.get(2), Some(&1)); 140 | /// ``` 141 | #[cfg(all(feature = "alloc", feature = "tinyvec"))] 142 | impl Swap for tinyvec::TinyVec 143 | where 144 | A: tinyvec::Array, 145 | A::Item: Default, 146 | { 147 | type Error = crate::Error; 148 | type Input = [usize; 2]; 149 | 150 | #[inline] 151 | fn swap(&mut self, [a, b]: Self::Input) -> Result<(), Self::Error> { 152 | manage_slice(self, a, b) 153 | } 154 | } 155 | 156 | fn manage_slice(slice: &mut [T], a: usize, b: usize) -> crate::Result<()> { 157 | _check_indcs!(&slice, a, b); 158 | slice.as_mut().swap(a, b); 159 | Ok(()) 160 | } 161 | -------------------------------------------------------------------------------- /cl-aux/src/traits/truncate.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "alloc")] 2 | use alloc::{string::String, vec::Vec}; 3 | 4 | /// See [`Truncate::truncate`] for more information. 5 | pub trait Truncate { 6 | /// Input 7 | type Input; 8 | 9 | /// Truncates the storage, delimiting its length by `Input`. 10 | fn truncate(&mut self, input: Self::Input); 11 | } 12 | 13 | impl Truncate for &mut T 14 | where 15 | T: Truncate, 16 | { 17 | type Input = T::Input; 18 | 19 | #[inline] 20 | fn truncate(&mut self, input: Self::Input) { 21 | (*self).truncate(input); 22 | } 23 | } 24 | 25 | /// ```rust 26 | /// let mut structure = Some(1); 27 | /// cl_aux::Truncate::truncate(&mut structure, 0); 28 | /// assert_eq!(structure, None); 29 | /// ``` 30 | impl Truncate for Option { 31 | type Input = usize; 32 | 33 | #[inline] 34 | fn truncate(&mut self, input: Self::Input) { 35 | if input == 0 { 36 | *self = None; 37 | } 38 | } 39 | } 40 | 41 | /// ```rust 42 | /// let mut structure = cl_aux::doc_tests::string(); 43 | /// cl_aux::Truncate::truncate(&mut structure, 1); 44 | /// assert_eq!(structure.len(), 1); 45 | /// ``` 46 | #[cfg(feature = "alloc")] 47 | impl Truncate for String { 48 | type Input = usize; 49 | 50 | #[inline] 51 | fn truncate(&mut self, input: Self::Input) { 52 | self.truncate(input); 53 | } 54 | } 55 | 56 | /// ```rust 57 | /// let mut structure = cl_aux::doc_tests::vec(); 58 | /// cl_aux::Truncate::truncate(&mut structure, 1); 59 | /// assert_eq!(structure.len(), 1); 60 | /// ``` 61 | #[cfg(feature = "alloc")] 62 | impl Truncate for Vec { 63 | type Input = usize; 64 | 65 | #[inline] 66 | fn truncate(&mut self, input: Self::Input) { 67 | self.truncate(input); 68 | } 69 | } 70 | 71 | /// ```rust 72 | /// let mut structure = cl_aux::doc_tests::array_string(); 73 | /// cl_aux::Truncate::truncate(&mut structure, 1); 74 | /// assert_eq!(structure.len(), 1); 75 | /// ``` 76 | #[cfg(feature = "arrayvec")] 77 | impl Truncate for arrayvec::ArrayString { 78 | type Input = usize; 79 | 80 | #[inline] 81 | fn truncate(&mut self, input: Self::Input) { 82 | self.truncate(input); 83 | } 84 | } 85 | 86 | /// ```rust 87 | /// let mut structure = cl_aux::doc_tests::array_vec(); 88 | /// cl_aux::Truncate::truncate(&mut structure, 1); 89 | /// assert_eq!(structure.len(), 1); 90 | /// ``` 91 | #[cfg(feature = "arrayvec")] 92 | impl Truncate for arrayvec::ArrayVec { 93 | type Input = usize; 94 | 95 | #[inline] 96 | fn truncate(&mut self, input: Self::Input) { 97 | self.truncate(input); 98 | } 99 | } 100 | 101 | /// ```rust 102 | /// let mut structure = cl_aux::doc_tests::small_vec(); 103 | /// cl_aux::Truncate::truncate(&mut structure, 1); 104 | /// assert_eq!(structure.len(), 1); 105 | /// ``` 106 | #[cfg(feature = "smallvec")] 107 | impl Truncate for smallvec::SmallVec 108 | where 109 | A: smallvec::Array, 110 | { 111 | type Input = usize; 112 | 113 | #[inline] 114 | fn truncate(&mut self, input: Self::Input) { 115 | self.truncate(input); 116 | } 117 | } 118 | 119 | /// ```rust 120 | /// let mut structure = cl_aux::doc_tests::tiny_vec_array_vec(); 121 | /// cl_aux::Truncate::truncate(&mut structure, 1); 122 | /// assert_eq!(structure.len(), 1); 123 | /// ``` 124 | #[cfg(feature = "tinyvec")] 125 | impl Truncate for tinyvec::ArrayVec 126 | where 127 | A: tinyvec::Array, 128 | A::Item: Default, 129 | { 130 | type Input = usize; 131 | 132 | #[inline] 133 | fn truncate(&mut self, input: Self::Input) { 134 | self.truncate(input); 135 | } 136 | } 137 | 138 | /// ```rust 139 | /// let mut structure = cl_aux::doc_tests::tiny_vec_tiny_vec(); 140 | /// cl_aux::Truncate::truncate(&mut structure, 1); 141 | /// assert_eq!(structure.len(), 1); 142 | /// ``` 143 | #[cfg(all(feature = "alloc", feature = "tinyvec"))] 144 | impl Truncate for tinyvec::TinyVec 145 | where 146 | A: tinyvec::Array, 147 | A::Item: Default, 148 | { 149 | type Input = usize; 150 | 151 | #[inline] 152 | fn truncate(&mut self, input: Self::Input) { 153 | self.truncate(input); 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /cl-aux/src/traits/with_capacity.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "alloc")] 2 | use alloc::{string::String, vec::Vec}; 3 | 4 | /// See [`WithCapacity::with_capacity`] for more information. 5 | pub trait WithCapacity 6 | where 7 | Self: Sized, 8 | { 9 | /// Error 10 | type Error; 11 | /// Input 12 | type Input; 13 | 14 | /// Creates a new instance based on an initial holding capacity provided by `Input`. 15 | fn with_capacity(input: Self::Input) -> Result; 16 | } 17 | 18 | /// ```rust 19 | /// use cl_aux::Capacity; 20 | /// let structure: [i32; 5]; 21 | /// structure = cl_aux::WithCapacity::with_capacity(0).unwrap(); 22 | /// assert_eq!(structure.capacity(), 5); 23 | /// ``` 24 | impl WithCapacity for [T; N] 25 | where 26 | T: Default, 27 | { 28 | type Error = crate::Error; 29 | type Input = usize; 30 | 31 | #[inline] 32 | fn with_capacity(_: Self::Input) -> Result { 33 | Ok([(); N].map(|_| T::default())) 34 | } 35 | } 36 | 37 | /// ```rust 38 | /// let structure: String = cl_aux::WithCapacity::with_capacity(2).unwrap(); 39 | /// assert_eq!(structure.capacity(), 2); 40 | /// ``` 41 | #[cfg(feature = "alloc")] 42 | impl WithCapacity for String { 43 | type Error = crate::Error; 44 | type Input = usize; 45 | 46 | #[inline] 47 | fn with_capacity(input: Self::Input) -> Result { 48 | Ok(String::with_capacity(input)) 49 | } 50 | } 51 | 52 | /// ```rust 53 | /// let structure: Vec = cl_aux::WithCapacity::with_capacity(2).unwrap(); 54 | /// assert_eq!(structure.capacity(), 2); 55 | /// ``` 56 | #[cfg(feature = "alloc")] 57 | impl WithCapacity for Vec { 58 | type Error = crate::Error; 59 | type Input = usize; 60 | 61 | #[inline] 62 | fn with_capacity(input: Self::Input) -> Result { 63 | Ok(Vec::with_capacity(input)) 64 | } 65 | } 66 | 67 | /// ```rust 68 | /// let structure: arrayvec::ArrayString<5>; 69 | /// structure = cl_aux::WithCapacity::with_capacity(0).unwrap(); 70 | /// assert_eq!(structure.capacity(), 5); 71 | /// ``` 72 | #[cfg(feature = "arrayvec")] 73 | impl WithCapacity for arrayvec::ArrayString { 74 | type Error = crate::Error; 75 | type Input = usize; 76 | 77 | #[inline] 78 | fn with_capacity(_: Self::Input) -> Result { 79 | Ok(arrayvec::ArrayString::new()) 80 | } 81 | } 82 | 83 | /// ```rust 84 | /// let structure: arrayvec::ArrayVec; 85 | /// structure = cl_aux::WithCapacity::with_capacity(0).unwrap(); 86 | /// assert_eq!(structure.capacity(), 5); 87 | /// ``` 88 | #[cfg(feature = "arrayvec")] 89 | impl WithCapacity for arrayvec::ArrayVec { 90 | type Error = crate::Error; 91 | type Input = usize; 92 | 93 | #[inline] 94 | fn with_capacity(_: Self::Input) -> Result { 95 | Ok(arrayvec::ArrayVec::new()) 96 | } 97 | } 98 | 99 | /// ```rust 100 | /// let structure: smallvec::SmallVec<[i32; 5]>; 101 | /// structure = cl_aux::WithCapacity::with_capacity(0).unwrap(); 102 | /// assert_eq!(structure.capacity(), 5); 103 | /// ``` 104 | #[cfg(feature = "smallvec")] 105 | impl WithCapacity for smallvec::SmallVec 106 | where 107 | A: smallvec::Array, 108 | { 109 | type Error = crate::Error; 110 | type Input = usize; 111 | 112 | #[inline] 113 | fn with_capacity(input: Self::Input) -> Result { 114 | Ok(smallvec::SmallVec::with_capacity(input)) 115 | } 116 | } 117 | 118 | /// ```rust 119 | /// let mut structure = cl_aux::doc_tests::tiny_vec_array_vec(); 120 | /// structure = cl_aux::WithCapacity::with_capacity(0).unwrap(); 121 | /// assert_eq!(structure.capacity(), 5); 122 | /// ``` 123 | #[cfg(feature = "tinyvec")] 124 | impl WithCapacity for tinyvec::ArrayVec 125 | where 126 | A: Default + tinyvec::Array, 127 | A::Item: Default, 128 | { 129 | type Error = crate::Error; 130 | type Input = usize; 131 | 132 | #[inline] 133 | fn with_capacity(_: Self::Input) -> Result { 134 | Ok(tinyvec::ArrayVec::new()) 135 | } 136 | } 137 | 138 | /// ```rust 139 | /// let mut structure = cl_aux::doc_tests::tiny_vec_tiny_vec(); 140 | /// structure = cl_aux::WithCapacity::with_capacity(0).unwrap(); 141 | /// assert_eq!(structure.capacity(), 5); 142 | /// ``` 143 | #[cfg(all(feature = "alloc", feature = "tinyvec"))] 144 | impl WithCapacity for tinyvec::TinyVec 145 | where 146 | A: Default + tinyvec::Array, 147 | A::Item: Default, 148 | { 149 | type Error = crate::Error; 150 | type Input = usize; 151 | 152 | #[inline] 153 | fn with_capacity(input: Self::Input) -> Result { 154 | Ok(tinyvec::TinyVec::with_capacity(input)) 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /cl-aux/src/tuple_impls.rs: -------------------------------------------------------------------------------- 1 | use crate::{Capacity, CapacityUpperBound, Clear, Length, SizeHint, Truncate}; 2 | 3 | macro_rules! tuple_impls { 4 | ($( 5 | $tuple_len:tt { 6 | $(($idx:tt) -> $T:ident)* 7 | } 8 | )+) => { 9 | $( 10 | impl<$( $T, )*> Capacity for ($( $T, )*) { 11 | #[inline] 12 | fn capacity(&self) -> usize { 13 | $tuple_len 14 | } 15 | } 16 | 17 | impl<$( $T, )*> CapacityUpperBound for ($( $T, )*) { 18 | const CAPACITY_UPPER_BOUND: usize = $tuple_len; 19 | } 20 | 21 | #[allow(non_snake_case)] 22 | impl<$( $T: Clear, )*> Clear for ($( $T, )*) { 23 | #[inline] 24 | fn clear(&mut self) { 25 | $( self.$idx.clear(); )* 26 | } 27 | } 28 | 29 | impl<$( $T, )*> Length for ($( $T, )*) { 30 | #[inline] 31 | fn length(&self) -> usize { 32 | $tuple_len 33 | } 34 | } 35 | 36 | impl<$( $T, )*> SizeHint for ($( $T, )*) { 37 | #[inline] 38 | fn size_hint(&self) -> (usize, Option) { 39 | ($tuple_len, Some($tuple_len)) 40 | } 41 | } 42 | 43 | #[allow(non_snake_case)] 44 | impl<$( $T: Truncate, )*> Truncate for ($( $T, )*) { 45 | type Input = ($( $T::Input, )*); 46 | 47 | #[inline] 48 | fn truncate(&mut self, input: Self::Input) { 49 | $( self.$idx.truncate(input.$idx); )* 50 | } 51 | } 52 | )+ 53 | } 54 | } 55 | 56 | tuple_impls! { 57 | 1 { 58 | (0) -> A 59 | } 60 | 2 { 61 | (0) -> A 62 | (1) -> B 63 | } 64 | 3 { 65 | (0) -> A 66 | (1) -> B 67 | (2) -> C 68 | } 69 | 4 { 70 | (0) -> A 71 | (1) -> B 72 | (2) -> C 73 | (3) -> D 74 | } 75 | 5 { 76 | (0) -> A 77 | (1) -> B 78 | (2) -> C 79 | (3) -> D 80 | (4) -> E 81 | } 82 | 6 { 83 | (0) -> A 84 | (1) -> B 85 | (2) -> C 86 | (3) -> D 87 | (4) -> E 88 | (5) -> F 89 | } 90 | 7 { 91 | (0) -> A 92 | (1) -> B 93 | (2) -> C 94 | (3) -> D 95 | (4) -> E 96 | (5) -> F 97 | (6) -> G 98 | } 99 | 8 { 100 | (0) -> A 101 | (1) -> B 102 | (2) -> C 103 | (3) -> D 104 | (4) -> E 105 | (5) -> F 106 | (6) -> G 107 | (7) -> H 108 | } 109 | 9 { 110 | (0) -> A 111 | (1) -> B 112 | (2) -> C 113 | (3) -> D 114 | (4) -> E 115 | (5) -> F 116 | (6) -> G 117 | (7) -> H 118 | (8) -> I 119 | } 120 | 10 { 121 | (0) -> A 122 | (1) -> B 123 | (2) -> C 124 | (3) -> D 125 | (4) -> E 126 | (5) -> F 127 | (6) -> G 128 | (7) -> H 129 | (8) -> I 130 | (9) -> J 131 | } 132 | 11 { 133 | (0) -> A 134 | (1) -> B 135 | (2) -> C 136 | (3) -> D 137 | (4) -> E 138 | (5) -> F 139 | (6) -> G 140 | (7) -> H 141 | (8) -> I 142 | (9) -> J 143 | (10) -> K 144 | } 145 | 12 { 146 | (0) -> A 147 | (1) -> B 148 | (2) -> C 149 | (3) -> D 150 | (4) -> E 151 | (5) -> F 152 | (6) -> G 153 | (7) -> H 154 | (8) -> I 155 | (9) -> J 156 | (10) -> K 157 | (11) -> L 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /ndstruct-fuzz/Cargo.toml: -------------------------------------------------------------------------------- 1 | [[bin]] 2 | name = "coo" 3 | path = "coo.rs" 4 | required-features = ["libfuzzer-sys/link_libfuzzer"] 5 | 6 | [[bin]] 7 | name = "csl" 8 | path = "csl.rs" 9 | required-features = ["libfuzzer-sys/link_libfuzzer"] 10 | 11 | [[bin]] 12 | name = "random_coo" 13 | path = "random_coo.rs" 14 | required-features = ["libfuzzer-sys/link_libfuzzer"] 15 | 16 | [[bin]] 17 | name = "random_csl" 18 | path = "random_csl.rs" 19 | required-features = ["libfuzzer-sys/link_libfuzzer"] 20 | 21 | [dependencies] 22 | arbitrary = { default-features = false, features = ["derive"], version = "1.0" } 23 | libfuzzer-sys = { default-features = false, version = "0.4" } 24 | ndstruct = { default-features = false, features = ["alloc", "rand", "rayon"], path = "../ndstruct" } 25 | rand = { default-features = false, version = "0.8" } 26 | rayon = { default-features = false, version = "1.0" } 27 | 28 | [package] 29 | authors = ["Automatically generated"] 30 | edition = "2021" 31 | license = "Apache-2.0" 32 | name = "ndstruct-fuzz" 33 | publish = false 34 | version = "0.0.0" 35 | 36 | [package.metadata] 37 | cargo-fuzz = true 38 | -------------------------------------------------------------------------------- /ndstruct-fuzz/coo.rs: -------------------------------------------------------------------------------- 1 | //! COO 2 | 3 | #![no_main] 4 | 5 | use rand as _; 6 | use rayon as _; 7 | 8 | use libfuzzer_sys::fuzz_target; 9 | use ndstruct::coo::CooVec; 10 | 11 | type Array = [usize; 3]; 12 | 13 | #[derive(Debug, arbitrary::Arbitrary)] 14 | struct Values { 15 | data: Vec<(Array, i32)>, 16 | dims: Array, 17 | value: Array, 18 | } 19 | 20 | fuzz_target!(|values: Values| { 21 | let real_data = values.data.into_iter().collect::>(); 22 | 23 | let coo: CooVec = if let Ok(r) = CooVec::new(values.dims, real_data) { 24 | r 25 | } else { 26 | return; 27 | }; 28 | 29 | let _ = coo.value(values.value); 30 | }); 31 | -------------------------------------------------------------------------------- /ndstruct-fuzz/csl.rs: -------------------------------------------------------------------------------- 1 | //! CSL 2 | 3 | #![no_main] 4 | 5 | use rand as _; 6 | 7 | use libfuzzer_sys::fuzz_target; 8 | use ndstruct::csl::CslVec; 9 | use rayon::prelude::*; 10 | 11 | type Array = [usize; 3]; 12 | 13 | #[derive(Debug, arbitrary::Arbitrary)] 14 | struct Values { 15 | data: Vec, 16 | dims: Array, 17 | indcs: Vec, 18 | line: Array, 19 | offs: Vec, 20 | value: Array, 21 | } 22 | 23 | fuzz_target!(|values: Values| { 24 | let Ok(csl) = CslVec::new(values.dims, values.data, values.indcs, values.offs) else { 25 | return; 26 | }; 27 | 28 | let _ = csl.line(values.line); 29 | 30 | let _ = csl.value(values.value); 31 | 32 | if let Ok(r) = csl.outermost_line_iter() { 33 | r.for_each(|_| {}); 34 | } else { 35 | return; 36 | }; 37 | 38 | if let Ok(r) = csl.outermost_line_rayon_iter() { 39 | r.enumerate().for_each(|(_, _)| {}); 40 | } 41 | }); 42 | -------------------------------------------------------------------------------- /ndstruct-fuzz/random_coo.rs: -------------------------------------------------------------------------------- 1 | //! Random COO 2 | 3 | #![no_main] 4 | 5 | use arbitrary as _; 6 | use rayon as _; 7 | 8 | use libfuzzer_sys::fuzz_target; 9 | use ndstruct::csl::CslVec; 10 | use rand::rngs::mock::StepRng; 11 | 12 | fuzz_target!(|values: ([usize; 2], usize)| { 13 | let (dims, nnz) = values; 14 | let _rslt = CslVec::new_controlled_random_rand(dims, nnz, &mut StepRng::new(0, 0), |_, _| 0); 15 | }); 16 | -------------------------------------------------------------------------------- /ndstruct-fuzz/random_csl.rs: -------------------------------------------------------------------------------- 1 | //! Random CSL 2 | 3 | #![no_main] 4 | 5 | use arbitrary as _; 6 | use rayon as _; 7 | 8 | use libfuzzer_sys::fuzz_target; 9 | use ndstruct::coo::CooVec; 10 | use rand::rngs::mock::StepRng; 11 | 12 | fuzz_target!(|values: ([usize; 2], usize)| { 13 | let (dims, nnz) = values; 14 | let _rslt = CooVec::new_controlled_random_rand(dims, nnz, &mut StepRng::new(0, 0), |_, _| 0); 15 | }); 16 | -------------------------------------------------------------------------------- /ndstruct/Cargo.toml: -------------------------------------------------------------------------------- 1 | [dependencies] 2 | cl-aux = { default-features = false, features = ["serde"], path = "../cl-aux", version = "5.0" } 3 | rand = { default-features = false, optional = true, version = "0.8" } 4 | rayon = { default-features = false, optional = true, version = "1.10" } 5 | serde = { default-features = false, features = ["derive"], optional = true, version = "1.0" } 6 | 7 | [features] 8 | alloc = ["cl-aux/alloc"] 9 | default = [] 10 | std = ["alloc"] 11 | 12 | [package] 13 | authors = ["Caio Fernandes "] 14 | categories = ["data-structures", "concurrency", "science", "no-std"] 15 | description = "Structures for N-dimensions" 16 | edition = "2021" 17 | keywords = ["collection", "dense", "dimension", "sparse", "structure"] 18 | license = "Apache-2.0" 19 | name = "ndstruct" 20 | readme = "README.md" 21 | repository = "https://github.com/c410-f3r/regular-crates" 22 | version = "2.2.0" 23 | 24 | [package.metadata.docs.rs] 25 | all-features = true 26 | -------------------------------------------------------------------------------- /ndstruct/LICENSE: -------------------------------------------------------------------------------- 1 | ../LICENSE -------------------------------------------------------------------------------- /ndstruct/README.md: -------------------------------------------------------------------------------- 1 | # ndstruct 2 | 3 | [![CI](https://github.com/c410-f3r/ndstruct/workflows/CI/badge.svg)](https://github.com/c410-f3r/ndstruct/actions?query=workflow%3ACI) 4 | [![crates.io](https://img.shields.io/crates/v/ndstruct.svg)](https://crates.io/crates/ndstruct) 5 | [![Documentation](https://docs.rs/ndstruct/badge.svg)](https://docs.rs/ndstruct) 6 | [![License](https://img.shields.io/badge/license-APACHE2-blue.svg)](./LICENSE) 7 | [![Rustc](https://img.shields.io/badge/rustc-1.52-lightgray")](https://blog.rust-lang.org/2020/03/12/Rust-1.52.html) 8 | 9 | Structures to store and retrieve N-dimensional data. Well, not any `N ∈ ℕ` but any natural number that fits into the pointer size of the machine that you are using. E.g., an 8-bit microcontroller can manipulate any structure with up to 255 dimensions. 10 | 11 | For those that might be wondering about why this crate should be used, it generally comes down to space-efficiency, ergometrics and retrieving speed. The following snippet shows some use-cases for potential replacement with `_cube_of_vecs` being the most inefficient of all. 12 | 13 | ```rust 14 | let _vec_of_options: Vec> = Default::default(); 15 | let _matrix_of_options: [Option<[Option; 8]>; 16] = Default::default(); 16 | let _cube_of_vecs: Vec>> = Default::default(); 17 | // The list worsens exponentially for higher dimensions 18 | ``` 19 | 20 | ## Example 21 | 22 | ```rust 23 | use ndstruct::{coo::CooArray, csl::CslVec}; 24 | 25 | fn main() -> ndstruct::Result<()> { 26 | // A CSL and COO cube. 27 | // 28 | // ___ ___ 29 | // / / /\ 30 | // /___/___/ /\ 31 | // / 1 / /\/2/ 32 | // /_1_/___/ /\/ 33 | // \_1_\___\/ / 34 | // \___\___\/ 35 | let coo = CooArray::new([2, 2, 2], [([0, 0, 0], 1.0), ([1, 1, 1], 2.0)])?; 36 | let mut csl = CslVec::default(); 37 | csl 38 | .constructor()? 39 | .next_outermost_dim(2)? 40 | .push_line([(0, 1.0)].iter().copied())? 41 | .next_outermost_dim(2)? 42 | .push_empty_line()? 43 | .next_outermost_dim(2)? 44 | .push_empty_line()? 45 | .push_line([(1, 2.0)].iter().copied())?; 46 | assert_eq!(coo.value([0, 0, 0]), csl.value([0, 0, 0])); 47 | assert_eq!(coo.value([1, 1, 1]), csl.value([1, 1, 1])); 48 | Ok(()) 49 | } 50 | ``` 51 | 52 | ## Supported structures 53 | 54 | - Compressed Sparse Line (CSL) 55 | - Coordinate format (COO) 56 | - Dense 57 | 58 | ## Features 59 | 60 | - `no_std` 61 | - Different storages (Array, Vec, Slice and more!) 62 | - Fully documented 63 | - Fuzz testing 64 | - No unsafe 65 | 66 | ## Optional features 67 | 68 | - `alloc` and `std` 69 | - Deserialization/Serialization (serde) 70 | - Parallel iterators (rayon) 71 | - Random instances (rand) 72 | 73 | ## Future 74 | 75 | Although CSR and COO are general sparse structures, they aren't good enough for certain situations, therefore, the existence of DIA, JDS, ELL, LIL, DOK and many others. 76 | 77 | If there are enough interest, the mentioned sparse storages might be added at some point in the future. 78 | 79 | ## Algebra library 80 | 81 | This project isn't and will never be an algebra library because of its own self-contained responsibility and complexity. Futhermore, a good implementation of such library would require a titanic amount of work and research for different algorithms, operations, decompositions, solvers and hardwares. 82 | 83 | ## Alternatives 84 | 85 | One of these libraries might suit you better: 86 | 87 | * [`sprs`][sprs]: Sparse linear algebra. 88 | * [`ndarray`][ndarray]: Dense N-dimensional operations. 89 | * [`nalgebra`][nalgebra]: Dense linear algebra. 90 | 91 | [nalgebra]: https://github.com/rustsim/nalgebra 92 | [ndarray]: https://github.com/rust-ndarray/ndarray 93 | [sprs]: https://github.com/vbarrielle/sprs -------------------------------------------------------------------------------- /ndstruct/src/coo.rs: -------------------------------------------------------------------------------- 1 | //! COO (Coordinate) format for N-dimensions. 2 | 3 | mod coo_error; 4 | mod coo_utils; 5 | 6 | #[cfg(feature = "alloc")] 7 | use alloc::vec::Vec; 8 | use cl_aux::{ArrayWrapper, SingleTypeStorage}; 9 | pub use coo_error::*; 10 | use coo_utils::{does_not_have_duplicates_sorted, value, value_mut}; 11 | 12 | /// COO backed by a static array. 13 | pub type CooArray = Coo<[([usize; D], DATA); DN], D>; 14 | /// COO backed by a mutable slice 15 | pub type CooMut<'data, DATA, const D: usize> = Coo<&'data mut [([usize; D], DATA)], D>; 16 | /// COO backed by a slice 17 | pub type CooRef<'data, DATA, const D: usize> = Coo<&'data [([usize; D], DATA)], D>; 18 | #[cfg(feature = "alloc")] 19 | /// COO backed by a dynamic vector. 20 | pub type CooVec = Coo, D>; 21 | 22 | /// Base structure for all [Coo] variants. 23 | /// 24 | /// # Types 25 | /// 26 | /// * `D`: Number of dimensions 27 | /// * `DS`: Data Storage 28 | #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] 29 | #[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd)] 30 | pub struct Coo { 31 | pub(crate) data: DS, 32 | pub(crate) dims: ArrayWrapper, 33 | } 34 | 35 | impl Coo { 36 | /// The definitions of all dimensions. 37 | /// 38 | /// # Example 39 | /// 40 | /// ```rust 41 | /// use ndstruct::doc_tests::coo_array_5; 42 | /// assert_eq!(coo_array_5().dims(), &[2, 3, 4, 3, 3]); 43 | /// ``` 44 | #[inline] 45 | pub fn dims(&self) -> &[usize; D] { 46 | &self.dims 47 | } 48 | } 49 | 50 | impl Coo 51 | where 52 | DS: AsRef<[::Item]> + SingleTypeStorage, 53 | { 54 | /// Creates a valid COO instance. 55 | /// 56 | /// # Arguments 57 | /// 58 | /// * `dims`: Array of dimensions 59 | /// * `data`: Data collection 60 | /// 61 | /// # Example 62 | #[cfg_attr(feature = "alloc", doc = "```rust")] 63 | #[cfg_attr(not(feature = "alloc"), doc = "```ignore")] 64 | /// use ndstruct::coo::{CooArray, CooVec}; 65 | /// // Sparse array ([8, _, _, _, _, 9, _, _, _, _]) 66 | /// let mut _sparse_array = CooArray::new([10], [([0], 8.0), ([5], 9.0)]); 67 | /// // A bunch of nothing for your overflow needs 68 | /// let mut _over_nine: ndstruct::Result>; 69 | /// _over_nine = CooVec::new([0; 9001], vec![]); 70 | /// ``` 71 | #[inline] 72 | pub fn new(dims: [usize; D], data: DS) -> crate::Result { 73 | if !crate::utils::are_in_ascending_order(data.as_ref(), |a, b| [&a.0, &b.0]) { 74 | return Err(CooError::InvalidIndcsOrder.into()); 75 | } 76 | let has_invalid_indcs = !data.as_ref().iter().all(|&(indcs, _)| { 77 | indcs.iter().zip(dims.iter()).all( 78 | |(data_idx, dim)| { 79 | if dim == &0 { 80 | true 81 | } else { 82 | data_idx < dim 83 | } 84 | }, 85 | ) 86 | }); 87 | if has_invalid_indcs { 88 | return Err(CooError::InvalidIndcs.into()); 89 | } 90 | if !does_not_have_duplicates_sorted(data.as_ref(), |a, b| a.0[..] != b.0[..]) { 91 | return Err(CooError::DuplicatedIndices.into()); 92 | } 93 | Ok(Self { data, dims: dims.into() }) 94 | } 95 | 96 | /// The data that is being stored. 97 | /// 98 | /// # Example 99 | /// 100 | /// ```rust 101 | /// use ndstruct::doc_tests::coo_array_5; 102 | /// assert_eq!(coo_array_5().data().first(), Some(&([0, 0, 1, 1, 2].into(), 1))); 103 | /// ``` 104 | #[inline] 105 | pub fn data(&self) -> &[([usize; D], DATA)] { 106 | self.data.as_ref() 107 | } 108 | 109 | /// If any, retrieves an immutable data reference of a given set of indices. 110 | /// 111 | /// # Arguments 112 | /// 113 | /// * `indcs`: Indices of the desired data location 114 | /// 115 | /// # Example 116 | /// 117 | /// ```rust 118 | /// use ndstruct::doc_tests::coo_array_5; 119 | /// let coo = coo_array_5(); 120 | /// assert_eq!(coo.value([0, 0, 0, 0, 0]), None); 121 | /// assert_eq!(coo.value([0, 2, 2, 0, 1]), Some(&4)); 122 | /// ``` 123 | #[inline] 124 | pub fn value(&self, indcs: [usize; D]) -> Option<&DATA> { 125 | value(indcs, self.data.as_ref()) 126 | } 127 | } 128 | 129 | impl Coo 130 | where 131 | DS: AsMut<[::Item]> + SingleTypeStorage, 132 | { 133 | /// Mutable version of [`value`](#method.value). 134 | #[inline] 135 | pub fn value_mut(&mut self, indcs: [usize; D]) -> Option<&mut DATA> { 136 | value_mut(indcs, self.data.as_mut()) 137 | } 138 | } 139 | 140 | #[cfg(feature = "rand")] 141 | impl Coo 142 | where 143 | DS: AsMut<[::Item]> 144 | + AsRef<[::Item]> 145 | + Default 146 | + SingleTypeStorage 147 | + cl_aux::CapacityUpperBound 148 | + cl_aux::Push<::Item>, 149 | { 150 | /// Creates a new random and valid instance delimited by the passed arguments. 151 | /// 152 | /// # Arguments 153 | /// 154 | /// * `dims`: Array of dimensions 155 | /// * `nnz`: Number of Non-Zero elements 156 | /// * `rng`: `rand::Rng` trait 157 | /// * `cb`: Callback to control data creation 158 | /// 159 | /// # Example 160 | #[cfg_attr(feature = "alloc", doc = "```rust")] 161 | #[cfg_attr(not(feature = "alloc"), doc = "```ignore")] 162 | /// use ndstruct::coo::CooVec; 163 | /// use rand::{Rng, rngs::mock::StepRng}; 164 | /// let mut rng = StepRng::new(0, 1); 165 | /// let dims = [1, 2, 3]; 166 | /// let mut _random: ndstruct::Result>; 167 | /// _random = CooVec::new_controlled_random_rand(dims, 3, &mut rng, |r, _| r.gen()); 168 | /// ``` 169 | #[inline] 170 | pub fn new_controlled_random_rand( 171 | dims: [usize; D], 172 | nnz: usize, 173 | rng: &mut R, 174 | mut cb: impl FnMut(&mut R, &[usize; D]) -> DATA, 175 | ) -> crate::Result 176 | where 177 | R: rand::Rng, 178 | { 179 | use rand::distributions::Distribution; 180 | if nnz > crate::utils::max_nnz(&dims) { 181 | return Err(CooError::NnzGreaterThanMaximumNnz.into()); 182 | } 183 | let mut data: DS = Default::default(); 184 | if nnz > data.as_ref().len() { 185 | return Err(crate::Error::InsufficientCapacity); 186 | } 187 | for _ in 0..nnz { 188 | let indcs: [usize; D] = ArrayWrapper::from_fn(|idx| { 189 | let dim = *dims.get(idx).unwrap_or(&0); 190 | if dim == 0 { 191 | 0 192 | } else { 193 | rand::distributions::Uniform::from(0..dim).sample(rng) 194 | } 195 | }) 196 | .0; 197 | if data.as_ref().iter().all(|value| value.0 != indcs) { 198 | data 199 | .push({ 200 | let element = cb(rng, &indcs); 201 | (indcs, element) 202 | }) 203 | .map_err(|_err| crate::Error::InsufficientCapacity)?; 204 | } 205 | } 206 | data.as_mut().sort_unstable_by(|a, b| a.0.cmp(&b.0)); 207 | Coo::new(dims, data) 208 | } 209 | 210 | /// Creates a new random and valid instance. 211 | /// 212 | /// # Arguments 213 | /// 214 | /// * `rng`: `rand::Rng` trait 215 | /// * `upper_bound`: The maximum allowed exclusive dimension 216 | /// 217 | /// # Example 218 | #[cfg_attr(feature = "alloc", doc = "```rust")] 219 | #[cfg_attr(not(feature = "alloc"), doc = "```ignore")] 220 | /// # fn main() -> ndstruct::Result<()> { 221 | /// use ndstruct::coo::CooVec; 222 | /// use rand::{rngs::mock::StepRng, seq::SliceRandom}; 223 | /// let mut rng = StepRng::new(0, 1); 224 | /// let upper_bound = 5; 225 | /// let random: ndstruct::Result>; 226 | /// random = CooVec::new_random_rand(&mut rng, upper_bound); 227 | /// assert!(random?.dims().choose(&mut rng).unwrap() < &upper_bound); 228 | /// # Ok(()) } 229 | #[inline] 230 | pub fn new_random_rand(rng: &mut R, upper_bound: usize) -> crate::Result 231 | where 232 | R: rand::Rng, 233 | rand::distributions::Standard: rand::distributions::Distribution, 234 | { 235 | let dims = crate::utils::valid_random_dims(rng, upper_bound); 236 | let max_nnz = crate::utils::max_nnz(&dims); 237 | let nnz = if max_nnz == 0 { 0 } else { rng.gen_range(0..max_nnz) }; 238 | Self::new_controlled_random_rand(dims, nnz, rng, |r, _| r.r#gen()) 239 | } 240 | } 241 | -------------------------------------------------------------------------------- /ndstruct/src/coo/coo_error.rs: -------------------------------------------------------------------------------- 1 | use core::fmt::{Debug, Display, Formatter}; 2 | 3 | /// Any error related to `Coo` operations 4 | #[derive(Debug, Eq, PartialEq)] 5 | #[non_exhaustive] 6 | pub enum CooError { 7 | /// Some index isn't in asceding order 8 | /// 9 | /// ```rust 10 | /// use ndstruct::coo::{CooArray, CooError}; 11 | /// let coo = CooArray::new([2, 2], [([1, 1], 8), ([0, 0], 9)]); 12 | /// assert_eq!(coo, Err(ndstruct::Error::Coo(CooError::InvalidIndcsOrder))); 13 | /// ``` 14 | InvalidIndcsOrder, 15 | 16 | /// Some index is greater than the defined dimensions 17 | /// 18 | /// ```rust 19 | /// use ndstruct::coo::{CooArray, CooError}; 20 | /// let coo = CooArray::new([2, 2], [([0, 1], 8), ([9, 9], 9)]); 21 | /// assert_eq!(coo, Err(ndstruct::Error::Coo(CooError::InvalidIndcs))); 22 | /// ``` 23 | InvalidIndcs, 24 | 25 | /// There are duplicated indices 26 | /// 27 | /// ```rust 28 | /// use ndstruct::coo::{CooArray, CooError}; 29 | /// let coo = CooArray::new([2, 2], [([0, 0], 8), ([0, 0], 9)]); 30 | /// assert_eq!(coo, Err(ndstruct::Error::Coo(CooError::DuplicatedIndices))); 31 | DuplicatedIndices, 32 | 33 | /// nnz is greater than the maximum permitted number of nnz 34 | /// 35 | #[cfg_attr(all(feature = "alloc", feature = "rand"), doc = "```rust")] 36 | #[cfg_attr(not(all(feature = "alloc", feature = "rand")), doc = "```ignore")] 37 | /// use ndstruct::coo::{CooError, CooVec}; 38 | /// use rand::{Rng, rngs::mock::StepRng}; 39 | /// let mut rng = StepRng::new(0, 1); 40 | /// let dims = [1, 2, 3]; // Max of 6 elements (1 * 2 * 3) 41 | /// let coo: ndstruct::Result>; 42 | /// coo = CooVec::new_controlled_random_rand(dims, 10, &mut rng, |r, _| r.gen()); 43 | /// assert_eq!(coo, Err(ndstruct::Error::Coo(CooError::NnzGreaterThanMaximumNnz))); 44 | /// ``` 45 | #[cfg(feature = "rand")] 46 | NnzGreaterThanMaximumNnz, 47 | } 48 | 49 | impl Display for CooError { 50 | #[inline] 51 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> { 52 | Debug::fmt(self, f) 53 | } 54 | } 55 | 56 | impl core::error::Error for CooError {} 57 | -------------------------------------------------------------------------------- /ndstruct/src/coo/coo_utils.rs: -------------------------------------------------------------------------------- 1 | use crate::utils::windows2; 2 | 3 | macro_rules! create_value { 4 | ($get:ident $fn_name:ident $([$mut:tt])?) => { 5 | #[inline] 6 | pub(crate) fn $fn_name( 7 | indcs: [usize; D], 8 | data: &$($mut)? [([usize; D], DATA)], 9 | ) -> Option<&$($mut)? DATA> { 10 | if let Ok(idx) = data.binary_search_by(|value| value.0.cmp(&indcs)) { 11 | Some(&$($mut)? data.$get(idx)?.1) 12 | } else { 13 | None 14 | } 15 | } 16 | } 17 | } 18 | 19 | create_value!(get value); 20 | create_value!(get_mut value_mut [mut]); 21 | 22 | #[inline] 23 | pub(crate) fn does_not_have_duplicates_sorted( 24 | slice: &[T], 25 | mut cb: impl FnMut(&T, &T) -> bool, 26 | ) -> bool { 27 | windows2(slice).all(|[a, b]| cb(a, b)) 28 | } 29 | -------------------------------------------------------------------------------- /ndstruct/src/csl/csl_error.rs: -------------------------------------------------------------------------------- 1 | use core::fmt::{Debug, Display, Formatter}; 2 | 3 | /// Any error related to Csl operations 4 | #[derive(Debug, Eq, PartialEq)] 5 | #[non_exhaustive] 6 | pub enum CslError { 7 | /// Data or indices length is greater than the product of all dimensions length 8 | /// 9 | #[cfg_attr(feature = "alloc", doc = "```rust")] 10 | #[cfg_attr(not(feature = "alloc"), doc = "```ignore")] 11 | /// use ndstruct::csl::{CslError, CslVec}; 12 | /// let csl = CslVec::new([3], vec![8, 9, 9, 9, 9], vec![0, 5, 5, 5, 5], vec![0, 2]); 13 | /// assert_eq!(csl, Err(ndstruct::Error::Csl(CslError::DataIndcsLengthGreaterThanDimsLength))); 14 | /// ``` 15 | DataIndcsLengthGreaterThanDimsLength, 16 | 17 | /// The data length is different than the indices length 18 | /// 19 | #[cfg_attr(feature = "alloc", doc = "```rust")] 20 | #[cfg_attr(not(feature = "alloc"), doc = "```ignore")] 21 | /// use ndstruct::csl::{ CslError, CslVec}; 22 | /// let csl = CslVec::new([10], vec![8, 9], vec![0], vec![0, 2]); 23 | /// assert_eq!(csl, Err(ndstruct::Error::Csl(CslError::DiffDataIndcsLength))); 24 | /// ``` 25 | DiffDataIndcsLength, 26 | 27 | /// Duplicated indices in a line 28 | /// ```rust 29 | /// use ndstruct::csl::{CslArray, CslError}; 30 | /// let csl = CslArray::new([10], [8, 9], [0, 0], [0, 2]); 31 | /// assert_eq!(csl, Err(ndstruct::Error::Csl(CslError::DuplicatedIndices))); 32 | /// ``` 33 | DuplicatedIndices, 34 | 35 | /// A index is greater or equal to the innermost dimension length 36 | /// 37 | /// ```rust 38 | /// use ndstruct::csl::{CslArray, CslError}; 39 | /// let csl = CslArray::new([10], [8, 9], [0, 10], [0, 2]); 40 | /// assert_eq!(csl, Err(ndstruct::Error::Csl(CslError::IndcsGreaterThanEqualDimLength))); 41 | /// ``` 42 | IndcsGreaterThanEqualDimLength, 43 | 44 | /// Some innermost dimension length is equal to zero 45 | #[cfg_attr(feature = "alloc", doc = "```rust")] 46 | #[cfg_attr(not(feature = "alloc"), doc = "```ignore")] 47 | /// use ndstruct::csl::{CslError, CslVec}; 48 | /// let csl: ndstruct::Result>; 49 | /// csl = CslVec::new([1, 2, 3, 0, 5], vec![], vec![], vec![]); 50 | /// assert_eq!(csl, Err(ndstruct::Error::Csl(CslError::InnermostDimsZero))); 51 | /// ``` 52 | InnermostDimsZero, 53 | 54 | /// Line iterator must deal with non-empty dimensions 55 | #[cfg_attr(feature = "alloc", doc = "```rust")] 56 | #[cfg_attr(not(feature = "alloc"), doc = "```ignore")] 57 | /// use ndstruct::csl::{CslVec, CslError}; 58 | /// let csl = CslVec::::default(); 59 | /// assert_eq!(csl.outermost_line_iter(), Err(ndstruct::Error::Csl(CslError::InvalidIterDim))); 60 | /// ``` 61 | InvalidIterDim, 62 | 63 | /// Offsets length is different than the dimensions product 64 | /// (without the innermost dimension) plus one. 65 | /// This rule doesn't not apply to an empty dimension. 66 | #[cfg_attr(feature = "alloc", doc = "```rust")] 67 | #[cfg_attr(not(feature = "alloc"), doc = "```ignore")] 68 | /// use ndstruct::csl::{CslError, CslVec}; 69 | /// let csl = CslVec::new([10], vec![8, 9], vec![0, 5], vec![0, 2, 4]); 70 | /// assert_eq!(csl, Err(ndstruct::Error::Csl(CslError::InvalidOffsetsLength))); 71 | /// ``` 72 | InvalidOffsetsLength, 73 | 74 | /// Offsets aren't in ascending order 75 | /// 76 | /// ```rust 77 | /// use ndstruct::csl::{CslArray, CslError}; 78 | /// let csl = CslArray::new([10], [8, 9], [0, 5], [2, 0]); 79 | /// assert_eq!(csl, Err(ndstruct::Error::Csl(CslError::InvalidOffsetsOrder))); 80 | /// ``` 81 | InvalidOffsetsOrder, 82 | 83 | /// Last offset is not equal to the nnz 84 | /// 85 | /// ```rust 86 | /// use ndstruct::csl::{CslArray, CslError}; 87 | /// let csl = CslArray::new([10], [8, 9], [0, 5], [0, 4]); 88 | /// assert_eq!(csl, Err(ndstruct::Error::Csl(CslError::LastOffsetDifferentNnz))); 89 | /// ``` 90 | LastOffsetDifferentNnz, 91 | 92 | /// nnz is greater than the maximum permitted number of nnz 93 | #[cfg_attr(all(feature = "alloc", feature = "rand"), doc = "```rust")] 94 | #[cfg_attr(not(all(feature = "alloc", feature = "rand")), doc = "```ignore")] 95 | /// use ndstruct::csl::CslVec; 96 | /// use rand::{Rng, rngs::mock::StepRng}; 97 | /// let mut rng = StepRng::new(0, 1); 98 | /// let dims = [1, 2, 3]; // Max of 6 elements (1 * 2 * 3) 99 | /// let csl: ndstruct::Result>; 100 | /// csl = CslVec::new_controlled_random_rand(dims, 7, &mut rng, |r, _| r.gen()); 101 | /// assert_eq!(csl, Err(ndstruct::Error::Csl(ndstruct::csl::CslError::NnzGreaterThanMaximumNnz))); 102 | /// ``` 103 | #[cfg(feature = "rand")] 104 | NnzGreaterThanMaximumNnz, 105 | 106 | /// It isn't possible to have more lines than [`usize::MAX`] - 2 107 | /// 108 | /// ```rust 109 | /// use ndstruct::csl::{CslArray, CslError}; 110 | /// let csl = CslArray::new([18446744073709551295, 255, 3026418949592973312], [0], [0], [0, 1]); 111 | /// assert_eq!(csl, Err(ndstruct::Error::Csl(CslError::OffsLengthOverflow))); 112 | /// ``` 113 | OffsLengthOverflow, 114 | } 115 | 116 | impl Display for CslError { 117 | #[inline] 118 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> { 119 | Debug::fmt(self, f) 120 | } 121 | } 122 | 123 | impl core::error::Error for CslError {} 124 | -------------------------------------------------------------------------------- /ndstruct/src/csl/csl_line_constructor.rs: -------------------------------------------------------------------------------- 1 | use crate::csl::{csl_utils::manage_last_offset, Csl}; 2 | use cl_aux::{Push, SingleTypeStorage}; 3 | use core::fmt::{Debug, Display, Formatter}; 4 | 5 | /// Constructs valid lines in a easy and interactive manner, abstracting away the complexity 6 | /// of the compressed sparse format. 7 | #[derive(Debug, Eq, PartialEq)] 8 | pub struct CslLineConstructor<'csl, DS, IS, OS, const D: usize> { 9 | csl: &'csl mut Csl, 10 | curr_dim_idx: usize, 11 | last_off: usize, 12 | } 13 | 14 | impl<'csl, DATA, DS, IS, OS, const D: usize> CslLineConstructor<'csl, DS, IS, OS, D> 15 | where 16 | DS: AsRef<[DATA]> + Push + SingleTypeStorage, 17 | IS: AsRef<[usize]> + Push, 18 | OS: AsRef<[usize]> + Push, 19 | { 20 | #[inline] 21 | pub(crate) fn new(csl: &'csl mut Csl) -> crate::Result { 22 | if D == 0 { 23 | return Err(CslLineConstructorError::EmptyDimension.into()); 24 | } 25 | let curr_dim_idx = if let Some(idx) = csl.dims.iter().copied().position(|x| x != 0) { 26 | idx 27 | } else { 28 | csl.dims.len() 29 | }; 30 | let last_off = manage_last_offset(&mut csl.offs)?; 31 | Ok(Self { csl, curr_dim_idx, last_off }) 32 | } 33 | 34 | /// Jumps to the next outermost dimension, i.e., from right to left. 35 | /// 36 | /// # Example 37 | #[cfg_attr(feature = "alloc", doc = "```rust")] 38 | #[cfg_attr(not(feature = "alloc"), doc = "```ignore")] 39 | /// # fn main() -> ndstruct::Result<()> { 40 | /// use ndstruct::csl::{CslRef, CslVec}; 41 | /// let mut csl = CslVec::::default(); 42 | /// csl 43 | /// .constructor()? 44 | /// .next_outermost_dim(3)? 45 | /// .push_line([(0, 1)].iter().copied())? 46 | /// .next_outermost_dim(4)? 47 | /// .push_line([(1, 2)].iter().copied())? 48 | /// .push_empty_line()? 49 | /// .push_line([(0, 3), (1,4)].iter().copied())?; 50 | /// assert_eq!( 51 | /// csl.sub_dim(0..4), 52 | /// CslRef::new([4, 3], &[1, 2, 3, 4][..], &[0, 1, 0, 1][..], &[0, 1, 2, 2, 4][..]).ok() 53 | /// ); 54 | /// # Ok(()) } 55 | #[inline] 56 | pub fn next_outermost_dim(mut self, len: usize) -> crate::Result { 57 | self.curr_dim_idx = 58 | self.curr_dim_idx.checked_sub(1).ok_or(CslLineConstructorError::DimsOverflow)?; 59 | *self.curr_dim() = len; 60 | Ok(self) 61 | } 62 | 63 | /// This is the same as `push_line([].iter(), [].iter())`. 64 | /// 65 | /// # Example 66 | #[cfg_attr(feature = "alloc", doc = "```rust")] 67 | #[cfg_attr(not(feature = "alloc"), doc = "```ignore")] 68 | /// # fn main() -> ndstruct::Result<()> { 69 | /// use ndstruct::csl::{CslRef, CslVec}; 70 | /// let mut csl = CslVec::::default(); 71 | /// let constructor = csl.constructor()?.next_outermost_dim(3)?; 72 | /// constructor.push_empty_line()?.next_outermost_dim(2)?.push_empty_line()?; 73 | /// assert_eq!(csl.line([0, 0, 0]), CslRef::new([3], &[][..], &[][..], &[0, 0][..]).ok()); 74 | /// # Ok(()) } 75 | #[inline] 76 | pub fn push_empty_line(self) -> crate::Result { 77 | self.csl.offs.push(self.last_off).map_err(|_err| crate::Error::InsufficientCapacity)?; 78 | Ok(self) 79 | } 80 | 81 | /// Pushes a new compressed line, modifying the internal structure and if applicable, 82 | /// increases the current dimension length. 83 | /// 84 | /// The iterator will be truncated to (usize::Max - last offset value + 1) or (last dimension value) 85 | /// and it can lead to a situation where no values will be inserted. 86 | /// 87 | /// # Arguments 88 | /// 89 | /// * `data`: Iterator of cloned items. 90 | /// * `indcs`: Iterator of the respective indices of each item. 91 | /// 92 | /// # Example 93 | #[cfg_attr(feature = "alloc", doc = "```rust")] 94 | #[cfg_attr(not(feature = "alloc"), doc = "```ignore")] 95 | /// # fn main() -> ndstruct::Result<()> { 96 | /// use ndstruct::csl::{CslRef, CslVec}; 97 | /// let mut csl = CslVec::::default(); 98 | /// csl.constructor()?.next_outermost_dim(50)?.push_line([(1, 1), (40, 2)].iter().copied())?; 99 | /// let line = csl.line([0, 0, 0]); 100 | /// assert_eq!(line, CslRef::new([50], &[1, 2][..], &[1, 40][..], &[0, 2][..]).ok()); 101 | /// # Ok(()) } 102 | #[inline] 103 | pub fn push_line(mut self, di: impl Iterator) -> crate::Result { 104 | let nnz_iter = 1..self.last_dim().saturating_add(1); 105 | let off_iter = self.last_off.saturating_add(1)..; 106 | let mut iter = off_iter.zip(nnz_iter.zip(di)); 107 | let mut last_off = self.last_off; 108 | let mut nnz = 0; 109 | 110 | let mut push = |curr_last_off, curr_nnz, idx, value| { 111 | self.csl.indcs.push(idx).map_err(|_err| crate::Error::InsufficientCapacity)?; 112 | self.csl.data.push(value).map_err(|_err| crate::Error::InsufficientCapacity)?; 113 | nnz = curr_nnz; 114 | last_off = curr_last_off; 115 | Ok::<(), crate::Error>(()) 116 | }; 117 | 118 | let mut last_line_idx = if let Some((curr_last_off, (curr_nnz, (idx, value)))) = iter.next() { 119 | push(curr_last_off, curr_nnz, idx, value)?; 120 | idx 121 | } else { 122 | return self.push_empty_line(); 123 | }; 124 | 125 | for (curr_last_off, (curr_nnz, (idx, value))) in iter { 126 | if idx <= last_line_idx { 127 | return Err(CslLineConstructorError::UnsortedIndices.into()); 128 | } 129 | push(curr_last_off, curr_nnz, idx, value)?; 130 | last_line_idx = idx; 131 | } 132 | 133 | if nnz == 0 { 134 | return self.push_empty_line(); 135 | } 136 | self.csl.offs.push(last_off).map_err(|_err| crate::Error::InsufficientCapacity)?; 137 | self.last_off = last_off; 138 | Ok(self) 139 | } 140 | 141 | #[expect(clippy::unwrap_used, reason = "`self.curr_dim_idx` always points to a valid reference")] 142 | fn curr_dim(&mut self) -> &mut usize { 143 | self.csl.dims.get_mut(self.curr_dim_idx).unwrap() 144 | } 145 | 146 | #[expect(clippy::unwrap_used, reason = "Constructor doesn't contain empty dimensions")] 147 | fn last_dim(&mut self) -> usize { 148 | *self.csl.dims.last().unwrap() 149 | } 150 | } 151 | 152 | /// Contains all errors related to [`CslLineConstructor`]. 153 | #[derive(Debug, Eq, PartialEq)] 154 | #[non_exhaustive] 155 | pub enum CslLineConstructorError { 156 | /// The maximum number of dimenstions has been reached 157 | DimsOverflow, 158 | /// All indices must be in ascending order 159 | UnsortedIndices, 160 | /// It isn't possible to construct new elements in an empty dimension 161 | EmptyDimension, 162 | /// The maximum number of lines for the currention dimension has been reached 163 | MaxNumOfLines, 164 | } 165 | 166 | impl Display for CslLineConstructorError { 167 | #[inline] 168 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> { 169 | Debug::fmt(self, f) 170 | } 171 | } 172 | 173 | impl core::error::Error for CslLineConstructorError {} 174 | -------------------------------------------------------------------------------- /ndstruct/src/csl/csl_line_iter.rs: -------------------------------------------------------------------------------- 1 | use crate::csl::{csl_utils::outermost_offs, CslError, CslMut, CslRef}; 2 | use core::mem; 3 | 4 | macro_rules! impl_iter { 5 | ($csl_iter:ident, $data_type:ty, $split_at:ident, $ref:ident) => { 6 | /// Iterator of a CSL dimension. 7 | #[derive(Debug, Eq, PartialEq)] 8 | pub struct $csl_iter<'slices, T, const D: usize> { 9 | curr_idx: usize, 10 | data: $data_type, 11 | dims: [usize; D], 12 | indcs: &'slices [usize], 13 | max_idx: usize, 14 | offs: &'slices [usize], 15 | } 16 | 17 | impl<'slices, T, const D: usize> $csl_iter<'slices, T, D> { 18 | pub(crate) fn new( 19 | mut dims: [usize; D], 20 | data: $data_type, 21 | indcs: &'slices [usize], 22 | offs: &'slices [usize], 23 | ) -> crate::Result { 24 | if let Some(r) = dims.first_mut() { 25 | let max_idx = *r; 26 | *r = 1; 27 | Ok($csl_iter { curr_idx: 0, data, dims, indcs, max_idx, offs }) 28 | } else { 29 | Err(CslError::InvalidIterDim.into()) 30 | } 31 | } 32 | 33 | #[cfg(feature = "rayon")] 34 | pub(crate) fn split_at(self, idx: usize) -> Option<[Self; 2]> { 35 | let cut_point = self.curr_idx.checked_add(idx)?; 36 | let [_, values] = outermost_offs(&self.dims, self.offs, self.curr_idx..cut_point); 37 | let values_diff = values.end.checked_sub(values.start)?; 38 | let (data_head, data_tail) = self.data.$split_at(values_diff); 39 | let (indcs_head, indcs_tail) = self.indcs.split_at(values_diff); 40 | Some([ 41 | $csl_iter { 42 | curr_idx: self.curr_idx, 43 | data: data_head, 44 | dims: self.dims, 45 | indcs: indcs_head, 46 | max_idx: cut_point, 47 | offs: self.offs, 48 | }, 49 | $csl_iter { 50 | curr_idx: cut_point, 51 | data: data_tail, 52 | dims: self.dims, 53 | indcs: indcs_tail, 54 | max_idx: self.max_idx, 55 | offs: self.offs, 56 | }, 57 | ]) 58 | } 59 | } 60 | 61 | impl DoubleEndedIterator for $csl_iter<'_, T, D> { 62 | #[inline] 63 | fn next_back(&mut self) -> Option { 64 | if self.curr_idx == 0 { 65 | return None; 66 | } 67 | let curr_idx_less_one = self.curr_idx.checked_sub(1)?; 68 | let range = curr_idx_less_one..self.curr_idx; 69 | self.curr_idx = curr_idx_less_one; 70 | let [indcs, values] = outermost_offs(&self.dims, self.offs, range); 71 | let data = mem::take(&mut self.data); 72 | let values_diff = values.end.checked_sub(values.start)?; 73 | let (data_head, data_tail) = data.$split_at(values_diff); 74 | let (indcs_head, indcs_tail) = self.indcs.split_at(values_diff); 75 | self.data = data_tail; 76 | self.indcs = indcs_tail; 77 | Some($ref { 78 | data: data_head, 79 | dims: self.dims.into(), 80 | indcs: indcs_head, 81 | offs: self.offs.get(indcs)?, 82 | }) 83 | } 84 | } 85 | 86 | impl ExactSizeIterator for $csl_iter<'_, T, D> {} 87 | 88 | impl<'slices, T, const D: usize> Iterator for $csl_iter<'slices, T, D> { 89 | type Item = $ref<'slices, T, D>; 90 | 91 | #[inline] 92 | fn next(&mut self) -> Option { 93 | if self.curr_idx >= self.max_idx { 94 | return None; 95 | } 96 | let curr_idx_plus_one = self.curr_idx.checked_add(1)?; 97 | let range = self.curr_idx..curr_idx_plus_one; 98 | self.curr_idx = curr_idx_plus_one; 99 | let [indcs, values] = outermost_offs(&self.dims, self.offs, range); 100 | let data = mem::take(&mut self.data); 101 | let values_diff = values.end.checked_sub(values.start)?; 102 | let (data_head, data_tail) = data.$split_at(values_diff); 103 | let (indcs_head, indcs_tail) = self.indcs.split_at(values_diff); 104 | self.data = data_tail; 105 | self.indcs = indcs_tail; 106 | Some($ref { 107 | data: data_head, 108 | dims: self.dims.into(), 109 | indcs: indcs_head, 110 | offs: self.offs.get(indcs)?, 111 | }) 112 | } 113 | 114 | #[inline] 115 | fn size_hint(&self) -> (usize, Option) { 116 | (self.max_idx, Some(self.max_idx)) 117 | } 118 | } 119 | }; 120 | } 121 | 122 | impl_iter!(CslLineIterMut, &'slices mut [T], split_at_mut, CslMut); 123 | impl_iter!(CslLineIterRef, &'slices [T], split_at, CslRef); 124 | -------------------------------------------------------------------------------- /ndstruct/src/csl/csl_rayon.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | csl::{CslLineIterMut, CslLineIterRef, CslMut, CslRef}, 3 | ParallelIteratorWrapper, ParallelProducerWrapper, 4 | }; 5 | use rayon::iter::{ 6 | plumbing::{bridge, Consumer, Producer, ProducerCallback, UnindexedConsumer}, 7 | IndexedParallelIterator, ParallelIterator, 8 | }; 9 | 10 | macro_rules! create_rayon_iter { 11 | ($csl_rayon_iter:ident, $ref:ident) => { 12 | impl<'slices, T, const D: usize> ParallelIterator 13 | for ParallelIteratorWrapper<$csl_rayon_iter<'slices, T, D>> 14 | where 15 | T: Send + Sync + 'slices, 16 | { 17 | type Item = $ref<'slices, T, D>; 18 | 19 | #[inline] 20 | fn drive_unindexed(self, consumer: C) -> C::Result 21 | where 22 | C: UnindexedConsumer, 23 | { 24 | bridge(self, consumer) 25 | } 26 | 27 | #[inline] 28 | fn opt_len(&self) -> Option { 29 | Some(self.0.len()) 30 | } 31 | } 32 | 33 | impl<'slices, T, const D: usize> IndexedParallelIterator 34 | for ParallelIteratorWrapper<$csl_rayon_iter<'slices, T, D>> 35 | where 36 | T: Send + Sync + 'slices, 37 | { 38 | #[inline] 39 | fn drive(self, consumer: C) -> C::Result 40 | where 41 | C: Consumer, 42 | { 43 | bridge(self, consumer) 44 | } 45 | 46 | #[inline] 47 | fn len(&self) -> usize { 48 | ExactSizeIterator::len(&self.0) 49 | } 50 | 51 | #[inline] 52 | fn with_producer(self, callback: Cb) -> Cb::Output 53 | where 54 | Cb: ProducerCallback, 55 | { 56 | callback.callback(ParallelProducerWrapper(self.0)) 57 | } 58 | } 59 | 60 | impl<'slices, T, const D: usize> IntoIterator 61 | for ParallelProducerWrapper<$csl_rayon_iter<'slices, T, D>> 62 | where 63 | T: 'slices, 64 | { 65 | type IntoIter = $csl_rayon_iter<'slices, T, D>; 66 | type Item = ::Item; 67 | 68 | #[inline] 69 | fn into_iter(self) -> Self::IntoIter { 70 | self.0 71 | } 72 | } 73 | 74 | impl<'slices, T, const D: usize> Producer 75 | for ParallelProducerWrapper<$csl_rayon_iter<'slices, T, D>> 76 | where 77 | T: Send + Sync + 'slices, 78 | { 79 | type IntoIter = $csl_rayon_iter<'slices, T, D>; 80 | type Item = ::Item; 81 | 82 | #[inline] 83 | fn into_iter(self) -> Self::IntoIter { 84 | self.0 85 | } 86 | 87 | #[inline] 88 | fn split_at(self, i: usize) -> (Self, Self) { 89 | let [a, b] = self.0.split_at(i).unwrap(); 90 | (ParallelProducerWrapper(a), ParallelProducerWrapper(b)) 91 | } 92 | } 93 | }; 94 | } 95 | 96 | create_rayon_iter!(CslLineIterRef, CslRef); 97 | create_rayon_iter!(CslLineIterMut, CslMut); 98 | -------------------------------------------------------------------------------- /ndstruct/src/csl/csl_rnd.rs: -------------------------------------------------------------------------------- 1 | use crate::csl::{ 2 | csl_utils::{correct_offs_len, manage_last_offset, outermost_stride}, 3 | Csl, CslError, 4 | }; 5 | use cl_aux::{Push, SingleTypeStorage}; 6 | use core::cmp::Ordering; 7 | use rand::{ 8 | distributions::{Distribution, Uniform}, 9 | Rng, 10 | }; 11 | 12 | #[derive(Debug)] 13 | pub(crate) struct CslRnd<'csl, DS, IS, OS, R, const D: usize> { 14 | csl: &'csl mut Csl, 15 | nnz: usize, 16 | rng: &'csl mut R, 17 | } 18 | 19 | impl<'csl, DATA, DS, IS, OS, R, const D: usize> CslRnd<'csl, DS, IS, OS, R, D> 20 | where 21 | DS: AsMut<[DATA]> + AsRef<[DATA]> + Push + SingleTypeStorage, 22 | IS: AsMut<[usize]> + AsRef<[usize]> + Push, 23 | R: Rng, 24 | OS: AsMut<[usize]> + AsRef<[usize]> + Push, 25 | { 26 | #[inline] 27 | pub(crate) fn new( 28 | csl: &'csl mut Csl, 29 | nnz: usize, 30 | rng: &'csl mut R, 31 | ) -> crate::Result { 32 | if nnz > crate::utils::max_nnz(&csl.dims) { 33 | return Err(CslError::NnzGreaterThanMaximumNnz.into()); 34 | } 35 | let _ = manage_last_offset(&mut csl.offs)?; 36 | Ok(Self { csl, nnz, rng }) 37 | } 38 | 39 | #[inline] 40 | pub(crate) fn fill(mut self, cb: impl FnMut(&mut R, [usize; D]) -> DATA) -> Option<()> { 41 | let last_dim_idx = if self.csl.dims.is_empty() { 42 | return Some(()); 43 | } else { 44 | self.csl.dims.len().checked_sub(1)? 45 | }; 46 | self.fill_offs(last_dim_idx)?; 47 | self.fill_indcs(last_dim_idx)?; 48 | self.fill_data(cb, last_dim_idx)?; 49 | Some(()) 50 | } 51 | 52 | fn fill_data( 53 | &mut self, 54 | mut cb: impl FnMut(&mut R, [usize; D]) -> DATA, 55 | last_dim_idx: usize, 56 | ) -> Option<()> { 57 | let data = &mut self.csl.data; 58 | let indcs = self.csl.indcs.as_ref(); 59 | let orig_dims = self.csl.dims.0; 60 | let outermost_stride = outermost_stride(&orig_dims); 61 | 62 | for (line_idx, offset) in self.csl.offs.as_ref().windows(2).enumerate() { 63 | let mut dims = orig_dims; 64 | *dims.first_mut()? = 65 | if outermost_stride == 0 { 0 } else { line_idx.checked_rem(outermost_stride)? }; 66 | let iter = dims.iter_mut().zip(orig_dims.iter()).skip(1).rev().skip(1); 67 | for (dim, &orig_dim) in iter { 68 | *dim = if orig_dim == 0 { 0 } else { line_idx.checked_rem(orig_dim)? }; 69 | } 70 | let range = *offset.first()?..*offset.get(1)?; 71 | for innermost_idx in indcs.get(range)?.iter().copied() { 72 | *dims.get_mut(last_dim_idx)? = innermost_idx; 73 | data.push(cb(self.rng, dims)).ok()?; 74 | } 75 | } 76 | 77 | Some(()) 78 | } 79 | 80 | fn fill_indcs(&mut self, last_dim_idx: usize) -> Option<()> { 81 | let dims = &self.csl.dims; 82 | let indcs = &mut self.csl.indcs; 83 | for offset in self.csl.offs.as_ref().windows(2) { 84 | let mut counter = 0; 85 | let line_nnz = offset.get(1)?.checked_sub(*offset.first()?)?; 86 | while counter < line_nnz { 87 | let rnd = self.rng.gen_range(0..*dims.get(last_dim_idx)?); 88 | if !indcs.as_ref().get(*offset.first()?..)?.contains(&rnd) { 89 | indcs.push(rnd).ok()?; 90 | counter = counter.checked_add(1)?; 91 | } 92 | } 93 | indcs.as_mut().get_mut(*offset.first()?..)?.sort_unstable(); 94 | } 95 | Some(()) 96 | } 97 | 98 | fn fill_offs(&mut self, last_dim_idx: usize) -> Option<()> { 99 | let nnz = self.nnz; 100 | for _ in 1..correct_offs_len(&self.csl.dims).ok()? { 101 | self.csl.offs.push(0).ok()?; 102 | } 103 | let fun = |idl, _, s: &mut Self| Some(Uniform::from(0..=idl).sample(s.rng)); 104 | let mut last_visited_off = self.do_fill_offs(last_dim_idx, fun)?; 105 | loop { 106 | if *self.csl.offs.as_ref().get(last_visited_off)? >= nnz { 107 | if let Some(slice) = self.csl.offs.as_mut().get_mut(last_visited_off..) { 108 | slice.iter_mut().for_each(|off| *off = nnz); 109 | } 110 | break; 111 | } 112 | let mut offs_adjustment = 0; 113 | last_visited_off = self.do_fill_offs(last_dim_idx, |idl, idx, s| { 114 | let offs = s.csl.offs.as_mut(); 115 | let curr = offs.get(idx)?.checked_add(offs_adjustment)?; 116 | let prev = *offs.get(idx.checked_sub(1)?)?; 117 | let start = curr.checked_sub(prev)?; 118 | let line_nnz = Uniform::from(start..=idl).sample(s.rng); 119 | let offs_adjustment_addition = line_nnz.checked_add(prev)?.checked_sub(curr)?; 120 | offs_adjustment = offs_adjustment.checked_add(offs_adjustment_addition)?; 121 | Some(line_nnz) 122 | })?; 123 | } 124 | Some(()) 125 | } 126 | 127 | fn do_fill_offs( 128 | &mut self, 129 | last_dim_idx: usize, 130 | mut f: impl FnMut(usize, usize, &mut Self) -> Option, 131 | ) -> Option { 132 | let nnz = self.nnz; 133 | let mut idx = 1; 134 | let mut previous_nnz = *self.csl.offs.as_ref().first()?; 135 | loop { 136 | if idx >= self.csl.offs.as_ref().len() { 137 | break; 138 | } 139 | match previous_nnz.cmp(&nnz) { 140 | Ordering::Equal => { 141 | break; 142 | } 143 | Ordering::Greater => { 144 | let idx_minus_one = idx.checked_sub(1)?; 145 | *self.csl.offs.as_mut().get_mut(idx_minus_one)? = nnz; 146 | break; 147 | } 148 | Ordering::Less => { 149 | let innermost_dim_len = *self.csl.dims.get(last_dim_idx)?; 150 | let line_nnz = f(innermost_dim_len, idx, self)?; 151 | let new_nnz = previous_nnz.checked_add(line_nnz)?; 152 | *self.csl.offs.as_mut().get_mut(idx)? = new_nnz; 153 | previous_nnz = new_nnz; 154 | } 155 | } 156 | idx = idx.checked_add(1)?; 157 | } 158 | idx.checked_sub(1) 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /ndstruct/src/csl/csl_utils.rs: -------------------------------------------------------------------------------- 1 | use crate::csl::{Csl, CslError, CslMut, CslRef}; 2 | use cl_aux::{ArrayWrapper, Push}; 3 | use core::ops::Range; 4 | 5 | macro_rules! create_sub_dim { 6 | ( 7 | $trait:ident 8 | $trait_fn:ident 9 | $ref:ident 10 | $get:ident 11 | $line_fn:ident 12 | $sub_dim_fn:ident 13 | $([$mut:tt])? 14 | ) => { 15 | 16 | #[inline] 17 | pub(crate) fn $line_fn<'csl, 'ret, DATA, DS, IS, OS, const D: usize>( 18 | csl: &'csl $($mut)? Csl, 19 | indcs: [usize; D] 20 | ) -> Option<$ref<'ret, DATA, 1>> 21 | where 22 | 'csl: 'ret, 23 | DATA: 'csl, 24 | DS: $trait<[DATA]>, 25 | IS: AsRef<[usize]>, 26 | OS: AsRef<[usize]>, 27 | { 28 | let last_dim = if let Some(r) = csl.dims.last() { 29 | *r 30 | } 31 | else { 32 | return None; 33 | }; 34 | let [offs_indcs, offs_values] = line_offs(&csl.dims, &indcs, csl.offs.as_ref())?; 35 | Some($ref { 36 | data: csl.data.$trait_fn().$get(offs_values.clone())?, 37 | dims: [last_dim].into(), 38 | indcs: &csl.indcs.as_ref().get(offs_values)?, 39 | offs: &csl.offs.as_ref().get(offs_indcs)?, 40 | }) 41 | } 42 | 43 | #[inline] 44 | pub(crate) fn $sub_dim_fn<'csl, 'ret, DATA: 'csl, DS, IS, OS, const FD: usize, const TD: usize>( 45 | csl: &'csl $($mut)? Csl, 46 | range: Range, 47 | ) -> Option<$ref<'ret, DATA, TD>> 48 | where 49 | 'csl: 'ret, 50 | DS: $trait<[DATA]>, 51 | IS: AsRef<[usize]>, 52 | OS: AsRef<[usize]>, 53 | { 54 | if range.start > range.end || TD > FD { 55 | return None; 56 | } 57 | let data_ref = csl.data.$trait_fn(); 58 | let dims_ref = &csl.dims; 59 | let indcs_ref = csl.indcs.as_ref(); 60 | let offs_ref = csl.offs.as_ref(); 61 | match TD { 62 | 0 => None, 63 | 1 => { 64 | let first = *offs_ref.first()?; 65 | let second = offs_ref.get(1)?; 66 | let [start_off_value, end_off_value] = [0, second.checked_sub(first)?]; 67 | let indcs = indcs_ref.get(start_off_value..end_off_value)?; 68 | let start = indcs.binary_search(&range.start).unwrap_or_else(|x| x); 69 | let end = indcs.get(start..)?.binary_search(&range.end).unwrap_or_else(|x| x); 70 | let dims_ref_idx = FD.checked_sub(TD)?; 71 | let dims_array = ArrayWrapper::try_from_fn(|_| { 72 | dims_ref.get(dims_ref_idx).copied().ok_or(()) 73 | }).ok()?; 74 | Some($ref { 75 | data: data_ref.$get(start..)?.$get(..end)?, 76 | dims: dims_array.into(), 77 | indcs: &indcs_ref.get(start..)?.get(..end)?, 78 | offs: &offs_ref.get(0..2)? 79 | }) 80 | }, 81 | _ => { 82 | let dims_ref_lower_bound = FD.checked_sub(TD)?; 83 | let mut dims = ArrayWrapper::try_from_fn(|idx| { 84 | let fun = || Some(*dims_ref.get(dims_ref_lower_bound..)?.get(idx)?); 85 | fun().ok_or(()) 86 | }).ok()?; 87 | *dims.first_mut()? = range.end.checked_sub(range.start)?; 88 | let [offs_indcs, offs_values] = outermost_offs(&dims, offs_ref, range); 89 | Some($ref { 90 | data: data_ref.$get(offs_values.clone())?, 91 | dims, 92 | indcs: &indcs_ref.get(offs_values)?, 93 | offs: &offs_ref.get(offs_indcs)?, 94 | }) 95 | }, 96 | } 97 | } 98 | 99 | }; 100 | } 101 | 102 | create_sub_dim!(AsMut as_mut CslMut get_mut line_mut sub_dim_mut [mut]); 103 | create_sub_dim!(AsRef as_ref CslRef get line sub_dim); 104 | 105 | // Max offset length is usize::MAX - 1 106 | #[inline] 107 | pub(crate) fn correct_offs_len(dims: &[usize; D]) -> crate::Result { 108 | match D { 109 | 0 => Ok(1), 110 | 1 => Ok(2), 111 | _ if dims == &ArrayWrapper::default().0 => Ok(1), 112 | _ => { 113 | let mut offs_len: usize = 1; 114 | for dim in dims.iter().copied().rev().skip(1).filter(|dim| dim != &0) { 115 | offs_len = offs_len.saturating_mul(dim); 116 | } 117 | offs_len.checked_add(1).ok_or_else(|| CslError::OffsLengthOverflow.into()) 118 | } 119 | } 120 | } 121 | 122 | #[inline] 123 | pub(crate) fn data_idx( 124 | csl: &Csl, 125 | indcs: [usize; D], 126 | ) -> Option 127 | where 128 | DS: AsRef<[DATA]>, 129 | IS: AsRef<[usize]>, 130 | OS: AsRef<[usize]>, 131 | { 132 | let innermost_idx = indcs.last()?; 133 | let [_, offs_values] = line_offs(&csl.dims, &indcs, csl.offs.as_ref())?; 134 | let start = offs_values.start; 135 | if let Ok(x) = csl.indcs.as_ref().get(offs_values)?.binary_search(innermost_idx) { 136 | start.checked_add(x) 137 | } else { 138 | None 139 | } 140 | } 141 | 142 | #[inline] 143 | pub(crate) fn line_offs( 144 | dims: &[usize; D], 145 | indcs: &[usize; D], 146 | offs: &[usize], 147 | ) -> Option<[Range; 2]> { 148 | match D { 149 | 0 => None, 150 | 1 => Some({ 151 | let off_end = offs.get(1)?.saturating_sub(*offs.first()?); 152 | [0..2, 0..off_end] 153 | }), 154 | _ => { 155 | let diff = indcs.len().saturating_sub(2); 156 | let mut lines: usize = 0; 157 | for (idx, curr_idx) in indcs.iter().copied().enumerate().take(diff) { 158 | let skip = idx.checked_add(1)?; 159 | let product = dims.iter().skip(skip).rev().skip(1).product::(); 160 | lines = lines.saturating_add(product.saturating_mul(curr_idx)); 161 | } 162 | let line_idx = dims.len().checked_sub(2)?; 163 | lines = lines.saturating_add(*indcs.get(line_idx)?); 164 | if lines > usize::MAX.saturating_sub(2) { 165 | return None; 166 | } 167 | let first = *offs.first()?; 168 | let off_start = offs.get(lines)?.saturating_sub(first); 169 | let lines_plus_one = lines.checked_add(1)?; 170 | let off_end = offs.get(lines_plus_one)?.saturating_sub(first); 171 | Some([lines..lines.saturating_add(2), off_start..off_end]) 172 | } 173 | } 174 | } 175 | 176 | #[inline] 177 | pub(crate) fn outermost_offs( 178 | dims: &[usize; D], 179 | offs: &[usize], 180 | range: Range, 181 | ) -> [Range; 2] { 182 | let outermost_stride = outermost_stride(dims); 183 | let start_off_idx = outermost_stride.saturating_mul(range.start); 184 | let end_off_idx = outermost_stride.saturating_mul(range.end); 185 | let off_start = *offs.get(start_off_idx).unwrap_or(&0); 186 | let off_end = *offs.get(end_off_idx).unwrap_or(&0); 187 | [start_off_idx..end_off_idx.saturating_add(1), off_start..off_end] 188 | } 189 | 190 | #[inline] 191 | pub(crate) fn outermost_stride(dims: &[usize; D]) -> usize { 192 | dims.iter().skip(1).rev().skip(1).product::() 193 | } 194 | 195 | #[inline] 196 | pub(crate) fn manage_last_offset(offs: &mut OS) -> crate::Result 197 | where 198 | OS: AsRef<[usize]> + Push, 199 | { 200 | Ok(if let Some(rslt) = offs.as_ref().last() { 201 | *rslt 202 | } else { 203 | offs.push(0).map_err(|_err| crate::Error::InsufficientCapacity)?; 204 | 0 205 | }) 206 | } 207 | -------------------------------------------------------------------------------- /ndstruct/src/dense.rs: -------------------------------------------------------------------------------- 1 | //! Dense 2 | //! 3 | //! A fully filled contiguous space of memory. If 1d, then this structure is the same as a vector; 4 | //! if 2d, then this structure is the same as a matrix; if 3d, then this structure is the same as 5 | //! a cube and so on for higher dimensions. 6 | 7 | mod dense_error; 8 | 9 | #[cfg(feature = "alloc")] 10 | use alloc::vec::Vec; 11 | use cl_aux::{ArrayWrapper, SingleTypeStorage}; 12 | pub use dense_error::*; 13 | 14 | /// Dense backed by a static array. 15 | pub type DenseArray = Dense<[DATA; DN], D>; 16 | /// Dense backed by a mutable slice 17 | pub type DenseMut<'data, DATA, const D: usize> = Dense<&'data mut [DATA], D>; 18 | /// Dense backed by a slice 19 | pub type DenseRef<'data, DATA, const D: usize> = Dense<&'data [DATA], D>; 20 | #[cfg(feature = "alloc")] 21 | /// Dense backed by a dynamic vector. 22 | pub type DenseVec = Dense, D>; 23 | 24 | /// Base structure for all [Dense] variants. 25 | /// 26 | /// # Types 27 | /// 28 | /// * `D`: Number of dimensions 29 | /// * `DS`: Data Storage 30 | #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] 31 | #[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd)] 32 | pub struct Dense { 33 | pub(crate) data: DS, 34 | pub(crate) dims: ArrayWrapper, 35 | } 36 | 37 | impl Dense { 38 | /// The definitions of all dimensions. 39 | /// 40 | /// # Example 41 | /// 42 | /// ```rust 43 | /// use ndstruct::doc_tests::dense_array_3; 44 | /// assert_eq!(dense_array_3().dims(), &[4, 3, 3]); 45 | /// ``` 46 | #[inline] 47 | pub fn dims(&self) -> &[usize; D] { 48 | &self.dims 49 | } 50 | } 51 | 52 | impl Dense 53 | where 54 | DS: AsRef<[::Item]> + SingleTypeStorage, 55 | { 56 | /// Creates a valid [Dense] instance. 57 | /// 58 | /// # Arguments 59 | /// 60 | /// * `dims`: Array of dimensions 61 | /// * `data`: Data collection 62 | /// 63 | /// # Example 64 | #[cfg_attr(feature = "alloc", doc = "```rust")] 65 | #[cfg_attr(not(feature = "alloc"), doc = "```ignore")] 66 | /// use ndstruct::dense::{DenseArray, DenseVec}; 67 | /// // Matrix ([1, 2, 3], [4, 5, 6]) 68 | /// let mut _matrix = DenseArray::new([2, 3], [1, 2, 3, 4, 5, 6]); 69 | /// // A bunch of nothing for your overflow needs 70 | /// let _over_nine: ndstruct::Result>; 71 | /// _over_nine = DenseVec::new([0; 9001], vec![]); 72 | /// ``` 73 | #[inline] 74 | pub fn new(dims: [usize; D], data: DS) -> crate::Result { 75 | if dims.iter().copied().any(|elem| elem >= D) { 76 | return Err(DenseError::InvalidIndcs.into()); 77 | } 78 | Ok(Self { data, dims: dims.into() }) 79 | } 80 | 81 | /// The data that is being stored. 82 | /// 83 | /// # Example 84 | /// 85 | /// ```rust 86 | /// use ndstruct::doc_tests::dense_array_3; 87 | /// assert_eq!(dense_array_3().data(), &[ 88 | /// 1, 2, 3, 4, 5, 6, 7, 8, 9, 89 | /// 10, 11, 12, 13, 14, 15, 16, 17, 18, 90 | /// 19, 20, 21, 22, 23, 24, 25, 26, 27, 91 | /// 28, 29, 30, 31, 32, 33, 34, 35, 36, 92 | /// ]); 93 | /// ``` 94 | #[inline] 95 | pub fn data(&self) -> &[DATA] { 96 | self.data.as_ref() 97 | } 98 | 99 | /// If any, retrieves an immutable data reference of a given set of indices. 100 | /// 101 | /// # Arguments 102 | /// 103 | /// * `indcs`: Indices of the desired data location 104 | /// 105 | /// # Example 106 | /// 107 | /// ```rust 108 | /// use ndstruct::doc_tests::dense_array_3; 109 | /// let elem = dense_array_3(); 110 | /// assert_eq!(elem.value([0, 0, 0]), Some(&1)); 111 | /// assert_eq!(elem.value([0, 0, 2]), Some(&3)); 112 | /// assert_eq!(elem.value([0, 2, 2]), Some(&9)); 113 | /// assert_eq!(elem.value([3, 2, 2]), Some(&36)); 114 | /// assert_eq!(elem.value([3, 2, 3]), None); 115 | /// ``` 116 | #[inline] 117 | pub fn value(&self, indcs: [usize; D]) -> Option<&DATA> { 118 | self.data().get(self.idx(indcs)) 119 | } 120 | 121 | // 1 * rows * cols * z 122 | // 1 * rows * y 123 | // 1 * x 124 | fn dim_stride(&self, dim_idx: usize, target_dim_idx: usize) -> usize { 125 | self.dims.iter().copied().skip(1).rev().skip(dim_idx).chain([target_dim_idx]).product() 126 | } 127 | 128 | fn idx(&self, indcs: [usize; D]) -> usize { 129 | let mut rslt: usize = 0; 130 | for (dim_idx, target_dim_idx) in (0..self.dims.len()).zip(indcs) { 131 | rslt = rslt.wrapping_add(self.dim_stride(dim_idx, target_dim_idx)); 132 | } 133 | rslt 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /ndstruct/src/dense/dense_error.rs: -------------------------------------------------------------------------------- 1 | use core::fmt::{Debug, Display, Formatter}; 2 | 3 | /// Any error related to `Coo` operations 4 | #[derive(Debug, Eq, PartialEq)] 5 | #[non_exhaustive] 6 | pub enum DenseError { 7 | /// Some index overflows the maximum number of dimensions. 8 | /// 9 | /// ```rust 10 | /// use ndstruct::dense::{DenseArray, DenseError}; 11 | /// let dense = DenseArray::new([2, 3], [1, 2, 3, 4]); 12 | /// assert_eq!(dense, Err(ndstruct::Error::Dense(DenseError::InvalidIndcs))); 13 | /// ``` 14 | InvalidIndcs, 15 | } 16 | 17 | impl Display for DenseError { 18 | #[inline] 19 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> { 20 | Debug::fmt(self, f) 21 | } 22 | } 23 | 24 | impl core::error::Error for DenseError {} 25 | -------------------------------------------------------------------------------- /ndstruct/src/doc_tests.rs: -------------------------------------------------------------------------------- 1 | //! Instances for documentation tests or tests. 2 | 3 | use crate::{coo::CooArray, csl::CslArray, dense::DenseArray}; 4 | #[cfg(feature = "alloc")] 5 | use crate::{coo::CooVec, csl::CslVec}; 6 | 7 | /// As odd as it may seem, this illustration is just a guide to get a grasp of 8 | /// a 5D structure. 9 | /// 10 | /// ```rust 11 | /// // ___ ___ ___ ___ ___ ___ ___ ___ ___ 12 | /// // / / / /\ / 3 / / /\ / / / /\ 13 | /// // /___/___/___/ /\ /_3_/___/___/ /\ /___/___/___/ /\ 14 | /// // / / / /\/ /\ / / / /\/ /\ / / 4 / /\/ /\ 15 | /// // /___/___/___/ /\/ / /___/___/___/ /\/ / /___/_4_/___/ /\/ / 16 | /// // / / / /\/ /\/ / / / /\/ /\/ / / / /\/ /\/ 17 | /// // /___/___/___/ /\/ / /___/___/___/ /\/ / /___/___/___/ /\/ / 18 | /// // / / / /\/1/\/ / / / /\/ /\/ / / / /\/ /\/ 19 | /// // /___/___/___/ /\/ / /___/___/___/ /\/ / /___/___/___/ /\/ / 20 | /// // \___\___\___\/ /\/ \___\___\___\/ /\/ \___\___\___\/ /\/ 21 | /// // \___\___\___\/ / \___\_2_\___\/ / \___\___\___\/ / 22 | /// // \___\___\___\/ \___\___\___\/ \___\___\___\/ 23 | /// // 24 | /// // ___ ___ ___ ___ ___ ___ ___ ___ ___ 25 | /// // / / / /\ / / / /\ / / / 6 /\ 26 | /// // /___/___/___/ /\ /___/___/___/ /\ /___/___/_6_/6/\ 27 | /// // / / / /\/ /\ / / / /\/ /\ / / / /\/ /\ 28 | /// // /___/___/___/ /\/ / /___/___/___/ /\/ / /___/___/___/ /\/7/ 29 | /// // / / / /\/ /\/ / / / /\/ /\/ / / / /\/ /\/ 30 | /// // /___/___/___/ /\/ / /___/___/___/ /\/ / /___/___/___/ /\/ / 31 | /// // / / / /\/ /\/ / / / /\/ /\/ / / / /\/ /\/ 32 | /// // /___/___/___/ /\/ / /___/___/___/ /\/ / /___/___/___/ /\/ / 33 | /// // \___\___\___\/ /\/ \___\___\___\/ /\/ \___\___\___\/ /\/ 34 | /// // \___\___\___\/ / \___\___\___\/ / \___\___\___\/ / 35 | /// // \___\___\___\/ \___\_5_\___\/ \___\___\___\/ 36 | /// use ndstruct::coo::CooArray; 37 | /// let _ = CooArray::new( 38 | /// [2, 3, 4, 3, 3], 39 | /// [ 40 | /// ([0, 0, 1, 1, 2], 1), 41 | /// ([0, 1, 0, 1, 1], 2), 42 | /// ([0, 1, 3, 0, 0], 3), 43 | /// ([0, 2, 2, 0, 1], 4), 44 | /// ([1, 1, 0, 2, 1], 5), 45 | /// ([1, 2, 3, 0, 2], 6), 46 | /// ([1, 2, 3, 2, 2], 7), 47 | /// ], 48 | /// ); 49 | /// ``` 50 | #[inline] 51 | #[must_use] 52 | pub fn coo_array_5() -> CooArray { 53 | CooArray { 54 | dims: [2, 3, 4, 3, 3].into(), 55 | data: [ 56 | ([0, 0, 1, 1, 2], 1), 57 | ([0, 1, 0, 1, 1], 2), 58 | ([0, 1, 3, 0, 0], 3), 59 | ([0, 2, 2, 0, 1], 4), 60 | ([1, 1, 0, 2, 1], 5), 61 | ([1, 2, 3, 0, 2], 6), 62 | ([1, 2, 3, 2, 2], 7), 63 | ], 64 | } 65 | } 66 | 67 | /// [`alloc::vec::Vec`] version of [`coo_array_5`]. 68 | #[cfg(feature = "alloc")] 69 | #[inline] 70 | #[must_use] 71 | pub fn coo_vec_5() -> CooVec { 72 | let coo = coo_array_5(); 73 | CooVec { dims: coo.dims, data: coo.data.to_vec() } 74 | } 75 | 76 | /// Two cuboids illustrating a [2, 3, 4, 5] 4D in a [w, y, z, x] order, i.e., each "line" 77 | /// or 1D representation is a left to right row and each "matrix" or 2D representation 78 | /// is filled in a top-down manner. 79 | /// 80 | /// ```rust 81 | /// // w: left to right 82 | /// // y: top to bottom 83 | /// // z: front to back 84 | /// // x: left to right 85 | /// // 86 | /// // ___ ___ ___ ___ ___ ___ ___ ___ ___ ___ 87 | /// // / / / / 4 / 5 /\ / / / / / /\ 88 | /// // /___/___/___/_4_/_5_/5/\ /___/___/___/___/___/ /\ 89 | /// // / / / / / /\/ /\ / / / 9 / / /\/ /\ 90 | /// // /___/___/___/___/___/ /\/ / /___/___/_9_/___/___/ /\/ / 91 | /// // / / 3 / / / /\/ /\/ / / / / / /\/ /\/ 92 | /// // /___/_3_/___/___/___/ /\/ / /___/_ _/___/___/___/ /\/ / 93 | /// // / 1 / / / 2 / /\/ /\/ / / / / / /\/ /\/ 94 | /// // /_1_/___/___/_2_/___/ /\/8/ /___/___/___/___/___/ /\/ / 95 | /// // \_1_\___\___\_2_\___\/ /\/ \___\___\___\___\___\/ /\/ 96 | /// // \___\___\_6_\___\___\/ / \___\___\___\___\___\/ / 97 | /// // \___\___\_7_\___\___\/ \___\___\___\___\___\/ 98 | /// use ndstruct::csl::CslArray; 99 | /// let _ = CslArray::new( 100 | /// [2, 3, 4, 5], 101 | /// [1, 2, 3, 4, 5, 6, 7, 8, 9], 102 | /// [0, 3, 1, 3, 4, 2, 2, 4, 2], 103 | /// [0, 2, 3, 3, 5, 6, 6, 6, 6, 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9], 104 | /// ); 105 | /// ``` 106 | #[inline] 107 | #[must_use] 108 | pub fn csl_array_4() -> CslArray { 109 | CslArray { 110 | data: [1, 2, 3, 4, 5, 6, 7, 8, 9], 111 | dims: [2, 3, 4, 5].into(), 112 | indcs: [0, 3, 1, 3, 4, 2, 2, 4, 2], 113 | offs: [0, 2, 3, 3, 5, 6, 6, 6, 6, 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9], 114 | } 115 | } 116 | 117 | /// [`alloc::vec::Vec`] version of [`csl_array_4`]. 118 | #[cfg(feature = "alloc")] 119 | #[inline] 120 | #[must_use] 121 | pub fn csl_vec_4() -> CslVec { 122 | let csl = csl_array_4(); 123 | CslVec { 124 | data: csl.data.to_vec(), 125 | dims: csl.dims, 126 | indcs: csl.indcs.to_vec(), 127 | offs: csl.offs.to_vec(), 128 | } 129 | } 130 | 131 | /// A dense cube, i.e., a fully filled cube. 132 | /// 133 | /// ```rust 134 | /// // ___ ___ ___ 135 | /// // / 28/ 29/ 30/\ 136 | /// // /___/___/___/0/\ 137 | /// // / 19/ 20/ 21/\/3/\ 138 | /// // /___/___/___/1/\/6/ 139 | /// // / 10/ 11/ 12/\/4/\/ 140 | /// // /___/___/___/2/\/7/ 141 | /// // / 1 / 2 / 3 /\/5/\/ 142 | /// // /___/___/___/3/\/8/ 143 | /// // \_1_\_2_\_3_\/6/\/ 144 | /// // \_4_\_5_\_6_\/9/ 145 | /// // \_7_\_8_\_9_\/ 146 | /// use ndstruct::dense::DenseArray; 147 | /// let _ = DenseArray::new( 148 | /// [4, 3, 3], 149 | /// [ 150 | /// 1, 2, 3, 4, 5, 6, 7, 8, 9, 151 | /// 10, 11, 12, 13, 14, 15, 16, 17, 18, 152 | /// 19, 20, 21, 22, 23, 24, 25, 26, 27, 153 | /// 28, 29, 30, 31, 32, 33, 34, 35, 36, 154 | /// ] 155 | /// ); 156 | /// ``` 157 | #[inline] 158 | #[must_use] 159 | pub fn dense_array_3() -> DenseArray { 160 | DenseArray { 161 | dims: [4, 3, 3].into(), 162 | data: [ 163 | 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, 164 | 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 165 | ], 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /ndstruct/src/error.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | coo::CooError, 3 | csl::{CslError, CslLineConstructorError}, 4 | dense::DenseError, 5 | }; 6 | use core::fmt::{Debug, Display, Formatter}; 7 | 8 | /// Contains all errors related to ndstruct 9 | #[derive(Debug, Eq, PartialEq)] 10 | #[non_exhaustive] 11 | pub enum Error { 12 | /// See [`cl_aux::Error`]. 13 | ClAux(cl_aux::Error), 14 | /// See [`CooError`] 15 | Coo(CooError), 16 | /// See [`CslError`] 17 | Csl(CslError), 18 | /// [`CslLineConstructorError`] 19 | CslLineConstructor(CslLineConstructorError), 20 | /// See [`DenseError`] 21 | Dense(DenseError), 22 | /// The internal buffer can't store all necessary data 23 | InsufficientCapacity, 24 | /// An Unknown that probably shouldn't have happened 25 | UnknownError, 26 | } 27 | 28 | impl Display for Error { 29 | #[inline] 30 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> { 31 | Debug::fmt(self, f) 32 | } 33 | } 34 | 35 | impl core::error::Error for Error {} 36 | 37 | impl From for Error { 38 | #[inline] 39 | fn from(from: cl_aux::Error) -> Self { 40 | Self::ClAux(from) 41 | } 42 | } 43 | 44 | impl From for Error { 45 | #[inline] 46 | fn from(from: CooError) -> Self { 47 | Self::Coo(from) 48 | } 49 | } 50 | 51 | impl From for Error { 52 | #[inline] 53 | fn from(from: CslError) -> Self { 54 | Self::Csl(from) 55 | } 56 | } 57 | 58 | impl From for Error { 59 | #[inline] 60 | fn from(from: CslLineConstructorError) -> Self { 61 | Self::CslLineConstructor(from) 62 | } 63 | } 64 | 65 | impl From for Error { 66 | #[inline] 67 | fn from(from: DenseError) -> Self { 68 | Self::Dense(from) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /ndstruct/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! # ndstruct 2 | //! 3 | //! This crate provides structures to store and retrieve N-dimensional data. 4 | 5 | #![cfg_attr(not(feature = "std"), no_std)] 6 | 7 | #[cfg(feature = "alloc")] 8 | extern crate alloc; 9 | 10 | pub mod coo; 11 | pub mod csl; 12 | pub mod dense; 13 | pub mod doc_tests; 14 | mod error; 15 | mod utils; 16 | 17 | /// Shorcut of [`core::result::Result`]. 18 | pub type Result = core::result::Result; 19 | 20 | pub use error::*; 21 | #[cfg(feature = "rayon")] 22 | pub use utils::{ParallelIteratorWrapper, ParallelProducerWrapper}; 23 | -------------------------------------------------------------------------------- /ndstruct/src/utils.rs: -------------------------------------------------------------------------------- 1 | use cl_aux::ArrayWrapper; 2 | 3 | #[cfg(feature = "rayon")] 4 | /// Parallel iterator for Rayon implementation. This is mostly an internal detail. 5 | #[derive(Debug)] 6 | pub struct ParallelIteratorWrapper(pub(crate) I); 7 | 8 | #[cfg(feature = "rayon")] 9 | /// Parallel producer for Rayon implementation. This is mostly an internal detail. 10 | #[derive(Debug)] 11 | pub struct ParallelProducerWrapper(pub(crate) I); 12 | 13 | #[inline] 14 | pub(crate) fn are_in_ascending_order<'slice, T, U>( 15 | slice: &'slice [T], 16 | cb: impl Fn(&'slice T, &'slice T) -> [&'slice U; 2], 17 | ) -> bool 18 | where 19 | T: 'slice, 20 | U: PartialOrd + 'slice, 21 | { 22 | windows2(slice).all(|x| { 23 | let [a, b] = cb(x[0], x[1]); 24 | a <= b 25 | }) 26 | } 27 | 28 | #[inline] 29 | pub(crate) fn are_in_upper_bound(slice: &[T], upper_bound: &T) -> bool 30 | where 31 | T: PartialOrd, 32 | { 33 | slice.iter().all(|x| x < upper_bound) 34 | } 35 | 36 | #[inline] 37 | pub(crate) fn has_duplicates(slice: &[T]) -> bool 38 | where 39 | T: PartialEq, 40 | { 41 | for (a_idx, a) in slice.iter().enumerate() { 42 | for b in slice.iter().skip(a_idx.saturating_add(1)) { 43 | if a == b { 44 | return true; 45 | } 46 | } 47 | } 48 | false 49 | } 50 | 51 | #[inline] 52 | pub(crate) fn max_nnz(dims: &[usize; D]) -> usize { 53 | if dims == &ArrayWrapper::default().0 { 54 | return 0; 55 | } 56 | if let Some(first) = dims.first().copied() { 57 | if D == 1 { 58 | return first; 59 | } 60 | 61 | let mut product: usize = 1; 62 | for dim in dims.iter().copied().filter(|dim| dim != &0) { 63 | product = product.saturating_mul(dim); 64 | } 65 | return product; 66 | } 67 | 0 68 | } 69 | 70 | #[cfg(feature = "rand")] 71 | #[inline] 72 | pub(crate) fn valid_random_dims(rng: &mut R, upper_bound: usize) -> [usize; D] 73 | where 74 | R: rand::Rng, 75 | { 76 | let dims = ArrayWrapper::default().0; 77 | if D == 0 { 78 | return dims; 79 | } 80 | let cut_point = rng.gen_range(0..D); 81 | let mut array = dims; 82 | let iter = if let Some(r) = array.get_mut(cut_point..) { 83 | r.iter_mut() 84 | } else { 85 | return dims; 86 | }; 87 | match upper_bound { 88 | 0 => {} 89 | 1 => iter.for_each(|dim| *dim = 1), 90 | _ => iter.for_each(|dim| *dim = rng.gen_range(1..upper_bound)), 91 | } 92 | dims 93 | } 94 | 95 | #[inline] 96 | pub(crate) fn windows2(slice: &[T]) -> impl Iterator { 97 | slice.windows(2).filter_map(|value| Some([value.first()?, value.get(1)?])) 98 | } 99 | -------------------------------------------------------------------------------- /rust-toolchain: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "nightly-2024-09-07" 3 | components = ["clippy", "miri", "rustfmt"] 4 | profile = "minimal" 5 | -------------------------------------------------------------------------------- /rust-tools/Cargo.toml: -------------------------------------------------------------------------------- 1 | [features] 2 | default = [] 3 | 4 | [package] 5 | authors = ["Caio Fernandes "] 6 | categories = ["command-line-interface", "config"] 7 | description = "Rust tools" 8 | edition = "2021" 9 | keywords = ["ci", "tools"] 10 | license = "Apache-2.0" 11 | name = "rust-tools" 12 | readme = "README.md" 13 | repository = "https://github.com/c410-f3r/regular-crates" 14 | rust-version = "1.65" 15 | version = "1.0.3" 16 | -------------------------------------------------------------------------------- /rust-tools/LICENSE: -------------------------------------------------------------------------------- 1 | ../LICENSE -------------------------------------------------------------------------------- /rust-tools/README.md: -------------------------------------------------------------------------------- 1 | [![CI](https://github.com/c410-f3r/rust-tools/workflows/CI/badge.svg)](https://github.com/c410-f3r/rust-tools/actions?query=workflow%3ACI) 2 | [![crates.io](https://img.shields.io/crates/v/rust-tools.svg)](https://crates.io/crates/rust-tools) 3 | [![Documentation](https://docs.rs/rust-tools/badge.svg)](https://docs.rs/rust-tools) 4 | [![License](https://img.shields.io/badge/license-APACHE2-blue.svg)](./LICENSE) 5 | [![Rustc](https://img.shields.io/badge/rustc-stable-lightgray")](https://blog.rust-lang.org/2020/03/12/Rust-stable.html) 6 | 7 | A CLI intended to aid development and CI workflows. This project can be seen as a high-level "orchestrator" or "wrapper" for tools that involve the Rust programing language. 8 | 9 | ## Configurations 10 | 11 | The application will primarily interact with a configuration (collection of rules) that defines how tools should behave and there are three different sources: 12 | 13 | ### Built-in configuration 14 | 15 | Pre-fixed set of rules found within this repository. Feel free to open a PR to create a new configuration. 16 | 17 | ```bash 18 | rust-tools --template you-rust SOME_COMMAND 19 | ``` 20 | 21 | ```txt 22 | YouRust( 23 | Params { 24 | clippy_flags: [ 25 | "-Dclippy::restriction", 26 | "-Dwarnings", 27 | "-Aclippy::implicit_return", 28 | "-Aclippy::missing_docs_in_private_items", 29 | ], 30 | rust_flags: [ 31 | "-Dbad_style", 32 | "-Dfuture_incompatible", 33 | "-Dmissing_debug_implementations", 34 | "-Dmissing_docs", 35 | "-Dnonstandard_style", 36 | "-Drust_2018_compatibility", 37 | "-Drust_2018_idioms", 38 | "-Dtrivial_casts", 39 | "-Dunused_lifetimes", 40 | "-Dunused_qualifications", 41 | "-Dwarnings", 42 | ], 43 | rustfmt_flags: [ 44 | "edition=\"2018", 45 | "tab_spaces=2", 46 | "use_field_init_shorthand=true", 47 | "use_small_heuristics=\"Max", 48 | ], 49 | toolchain: "", 50 | }, 51 | ) 52 | ``` 53 | 54 | ### Configuration file 55 | 56 | Can use a built-in configuration as a template for custom needs. Enables the addition or removal of flags. 57 | 58 | ```bash 59 | rust-tools --file SOME_CONFIGURATION_FILE.cfg SOME_COMMAND 60 | ``` 61 | 62 | ```ini 63 | add_clipy_flags -Aclippy::type_complexity 64 | rm_clippy_flags -Aclippy::implicit_return,-Aclippy::missing_docs_in_private_items 65 | template you-rust 66 | toolchain nightly-2024-09-07 67 | ``` 68 | 69 | ## CLI parameters 70 | 71 | Depending on the selected target, it is possible to define or extend certain rules; 72 | 73 | ```bash 74 | rust-tools rust-flags -Dbad_style,-Dunused_qualifications 75 | ``` 76 | 77 | The final configuration will obey the following order: `built-in` -> `file` -> `CLI`, i.e., built-in parameters are overwritten by file parameters and file parameters are overwritten by cli parameters. 78 | 79 | ## Script example 80 | 81 | ```bash 82 | #!/usr/bin/env bash 83 | 84 | set -euxo pipefail 85 | 86 | cargo install rust-tools 87 | 88 | export RUSTFLAGS="$(rust-tools rust-flags)" 89 | 90 | rust-tools clippy 91 | 92 | rust-tools check-generic SOME_CRATE 93 | rust-tools test-with-features SOME_CRATE FIRST_FEATURE,SECOND_FEATURE 94 | ``` 95 | 96 | ## Supported targets 97 | 98 | - clippy flags 99 | - rust flags 100 | - rust-toolchain file 101 | - rustfmt file and flags 102 | 103 | -------------------------------------------------------------------------------- /rust-tools/src/action_option.rs: -------------------------------------------------------------------------------- 1 | create_enum_with_list! { 2 | crate::Error::UnknownAction; 3 | 4 | #[derive(Debug)] 5 | pub(crate) enum ActionOption { 6 | BuildGeneric, "build-generic"; 7 | BuildWithFeatures, "build-with-features"; 8 | CheckGeneric, "check-generic"; 9 | CheckWithFeatures, "check-with-features"; 10 | Clippy, "clippy"; 11 | RustFlags, "rust-flags"; 12 | Rustfmt, "rustfmt"; 13 | SetUp, "set-up"; 14 | TargetDir, "target-dir"; 15 | TestGeneric, "test-generic"; 16 | TestWithFeatures, "test-with-features"; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /rust-tools/src/actions.rs: -------------------------------------------------------------------------------- 1 | mod cargo; 2 | mod rust_flags; 3 | mod set_up; 4 | mod target_dir; 5 | mod tools; 6 | 7 | use crate::Params; 8 | 9 | pub(crate) struct Actions { 10 | pub(crate) params: Params, 11 | } 12 | 13 | impl Actions { 14 | #[inline] 15 | pub(crate) fn new(params: Params) -> Self { 16 | Self { params } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /rust-tools/src/actions/cargo.rs: -------------------------------------------------------------------------------- 1 | use crate::{handle_cmd_output, Actions}; 2 | use std::process::Command; 3 | 4 | macro_rules! create_fns { 5 | ( 6 | $cargo_action:literal, 7 | $info:literal, 8 | $generic_fn:ident, 9 | $with_features_fn:ident 10 | $(, $additional_arg:expr)? 11 | ) => { 12 | pub(crate) fn $generic_fn(&self, package: String) -> crate::Result<()> { 13 | handle_cmd_output(Command::new("echo").args(&[ 14 | "-e", 15 | &format!( 16 | concat!(r#"\e[0;33m***** "#, $info, r#" "{}" without features *****\e[0m\n"#), 17 | package 18 | ), 19 | ]))?; 20 | handle_cmd_output(Command::new("cargo").args(&[ 21 | $cargo_action, 22 | "--manifest-path", 23 | &format!("{package}/Cargo.toml"), 24 | "--no-default-features", 25 | $($additional_arg)? 26 | ]))?; 27 | 28 | handle_cmd_output(Command::new("echo").args(&[ 29 | "-e", 30 | &format!( 31 | concat!(r#"\e[0;33m***** "#, $info, r#" "{}" with all features *****\e[0m\n"#), 32 | package 33 | ), 34 | ]))?; 35 | handle_cmd_output(Command::new("cargo").args(&[ 36 | $cargo_action, 37 | "--all-features", 38 | "--manifest-path", 39 | &format!("{package}/Cargo.toml"), 40 | $($additional_arg)? 41 | ]))?; 42 | Ok(()) 43 | } 44 | 45 | pub(crate) fn $with_features_fn(&self, package: String, features: String) -> crate::Result<()> { 46 | handle_cmd_output(Command::new("echo").args(&[ 47 | "-e", 48 | &format!( 49 | concat!(r#"\e[0;33m***** "#, $info, r#" "{}" with features "{}" *****\e[0m\n"#), 50 | package, features 51 | ), 52 | ]))?; 53 | handle_cmd_output(Command::new("cargo").args(&[ 54 | $cargo_action, 55 | "--features", 56 | &features, 57 | "--manifest-path", 58 | &format!("{package}/Cargo.toml"), 59 | "--no-default-features", 60 | $($additional_arg)? 61 | ]))?; 62 | Ok(()) 63 | } 64 | }; 65 | } 66 | 67 | impl Actions { 68 | create_fns!("build", "Building", build_generic, build_with_features); 69 | create_fns!("check", "Checking", check_generic, check_with_features, "--tests"); 70 | create_fns!("test", "Testing", test_generic, test_with_features); 71 | } 72 | -------------------------------------------------------------------------------- /rust-tools/src/actions/rust_flags.rs: -------------------------------------------------------------------------------- 1 | use crate::Actions; 2 | use std::io::{stdout, Write}; 3 | 4 | impl Actions { 5 | pub(crate) fn rust_flags(&self) -> crate::Result<()> { 6 | let mut iter = self.params.rust_flags.iter(); 7 | let mut stdout = stdout(); 8 | if let Some(first) = iter.next() { 9 | stdout.write_all(first.as_bytes())?; 10 | } 11 | for element in iter { 12 | stdout.write_all(b" ")?; 13 | stdout.write_all(element.as_bytes())?; 14 | } 15 | stdout.flush()?; 16 | Ok(()) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /rust-tools/src/actions/set_up.rs: -------------------------------------------------------------------------------- 1 | use crate::Actions; 2 | use std::{fs::File, io::Write}; 3 | 4 | impl Actions { 5 | pub(crate) fn set_up(&self) -> crate::Result<()> { 6 | if !self.params.toolchain.is_empty() { 7 | let mut file = File::create("rust-toolchain")?; 8 | file.write_all(self.params.toolchain.as_bytes())?; 9 | } 10 | 11 | if !self.params.rustfmt_flags.is_empty() { 12 | let mut file = File::create("rustfmt.toml")?; 13 | for rustfmt_flag in &self.params.rustfmt_flags { 14 | file.write_all(rustfmt_flag.as_bytes())?; 15 | file.write_all(b"\n")?; 16 | } 17 | } 18 | Ok(()) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /rust-tools/src/actions/target_dir.rs: -------------------------------------------------------------------------------- 1 | use crate::Actions; 2 | use std::io::{stdout, Write}; 3 | 4 | const TARGET_DIR: &str = "target/rust-tools-target"; 5 | 6 | impl Actions { 7 | pub(crate) fn target_dir() -> crate::Result<()> { 8 | let mut stdout = stdout(); 9 | stdout.write_all(TARGET_DIR.as_bytes())?; 10 | stdout.flush()?; 11 | Ok(()) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /rust-tools/src/actions/tools.rs: -------------------------------------------------------------------------------- 1 | use crate::{handle_cmd_output, Actions}; 2 | use std::{env::Args, process::Command}; 3 | 4 | impl Actions { 5 | pub(crate) fn clippy(&self, args: &mut Args) -> crate::Result<()> { 6 | handle_cmd_output( 7 | Command::new("echo").args(["-e", r"\e[0;33m***** Running clippy *****\e[0m\n"]), 8 | )?; 9 | let mut cmd = Command::new("cargo"); 10 | handle_cmd_output( 11 | cmd 12 | .args( 13 | [String::from("clippy"), String::from("--workspace")] 14 | .into_iter() 15 | .chain(args.by_ref()) 16 | .chain([String::from("--")]), 17 | ) 18 | .args(&self.params.clippy_flags), 19 | )?; 20 | Ok(()) 21 | } 22 | 23 | pub(crate) fn rustfmt() -> crate::Result<()> { 24 | handle_cmd_output( 25 | Command::new("echo").args(["-e", r"\e[0;33m***** Running rustfmt *****\e[0m\n"]), 26 | )?; 27 | handle_cmd_output(Command::new("cargo").args(["fmt", "--all", "--", "--check"]))?; 28 | Ok(()) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /rust-tools/src/cfg.rs: -------------------------------------------------------------------------------- 1 | mod you_rust; 2 | 3 | pub(crate) use you_rust::YouRust; 4 | -------------------------------------------------------------------------------- /rust-tools/src/cfg/you_rust.rs: -------------------------------------------------------------------------------- 1 | use crate::Params; 2 | 3 | const CLIPPY_FLAGS: &[&str] = &[ 4 | "-Dclippy::pedantic", 5 | "-Dclippy::restriction", 6 | "-Dwarnings", 7 | "-Aclippy::absolute_paths", 8 | "-Aclippy::allow_attributes", 9 | "-Aclippy::big_endian_bytes", 10 | "-Aclippy::blanket-clippy-restriction-lints", 11 | "-Aclippy::copy_iterator", 12 | "-Aclippy::decimal_literal_representation", 13 | "-Aclippy::default_numeric_fallback", 14 | "-Aclippy::enum_variant_names", 15 | "-Aclippy::error_impl_error", 16 | "-Aclippy::exhaustive_enums", 17 | "-Aclippy::exhaustive_structs", 18 | "-Aclippy::field_scoped_visibility_modifiers", 19 | "-Aclippy::host_endian_bytes", 20 | "-Aclippy::ignored_unit_patterns", 21 | "-Aclippy::impl_trait_in_params", 22 | "-Aclippy::implicit_return", 23 | "-Aclippy::inline_always", 24 | "-Aclippy::integer_division", 25 | "-Aclippy::integer_division_remainder_used", 26 | "-Aclippy::into_iter_without_iter", 27 | "-Aclippy::len_without_is_empty", 28 | "-Aclippy::let_underscore_untyped", 29 | "-Aclippy::many_single_char_names", 30 | "-Aclippy::min_ident_chars", 31 | "-Aclippy::missing_assert_message", 32 | "-Aclippy::missing_docs_in_private_items", 33 | "-Aclippy::missing_errors_doc", 34 | "-Aclippy::missing_trait_methods", 35 | "-Aclippy::module_name_repetitions", 36 | "-Aclippy::multiple_inherent_impl", 37 | "-Aclippy::must_use_candidate", 38 | "-Aclippy::needless_doctest_main", 39 | "-Aclippy::needless_else", 40 | "-Aclippy::pattern_type_mismatch", 41 | "-Aclippy::pub_use", 42 | "-Aclippy::pub_with_shorthand", 43 | "-Aclippy::question_mark_used", 44 | "-Aclippy::same_name_method", 45 | "-Aclippy::self_named_module_files", 46 | "-Aclippy::semicolon_outside_block", 47 | "-Aclippy::similar_names", 48 | "-Aclippy::single_call_fn", 49 | "-Aclippy::struct_field_names", 50 | "-Aclippy::too_long_first_doc_paragraph", 51 | "-Aclippy::unneeded_field_pattern", 52 | "-Aclippy::unseparated_literal_suffix", 53 | "-Aclippy::used_underscore_binding", 54 | "-Aclippy::wildcard_enum_match_arm", 55 | ]; 56 | 57 | const RUST_FLAGS: &[&str] = &[ 58 | "-Ddeprecated_in_future", 59 | "-Ddeprecated_safe", 60 | "-Delided_lifetimes_in_paths", 61 | "-Dexplicit_outlives_requirements", 62 | "-Dffi_unwind_calls", 63 | "-Dkeyword_idents_2018", 64 | "-Dkeyword_idents_2024", 65 | "-Dlet_underscore_drop", 66 | "-Dmacro_use_extern_crate", 67 | "-Dmeta_variable_misuse", 68 | "-Dmissing_abi", 69 | "-Dmissing_debug_implementations", 70 | "-Dmissing_docs", 71 | "-Dmissing_unsafe_on_extern", 72 | "-Dnon_ascii_idents", 73 | "-Dredundant_lifetimes", 74 | "-Drust_2021_incompatible_closure_captures", 75 | "-Drust_2021_incompatible_or_patterns", 76 | "-Drust_2021_prefixes_incompatible_syntax", 77 | "-Drust_2021_prelude_collisions", 78 | "-Dsingle_use_lifetimes", 79 | "-Dtrivial_casts", 80 | "-Dtrivial_numeric_casts", 81 | "-Dunit_bindings", 82 | "-Dunnameable_types", 83 | "-Dunreachable_pub", 84 | "-Dunsafe_code", 85 | "-Dunused_extern_crates", 86 | "-Dunused_import_braces", 87 | "-Dunused_lifetimes", 88 | "-Dunused_macro_rules", 89 | "-Dunused_qualifications", 90 | "-Dunused_results", 91 | "-Dwarnings", 92 | ]; 93 | 94 | const RUSTFMT_FLAGS: &[&str] = 95 | &[r#"edition="2021""#, "tab_spaces=2", r#"use_small_heuristics="Max""#]; 96 | 97 | #[derive(Debug, PartialEq)] 98 | pub(crate) struct YouRust(pub(crate) Params); 99 | 100 | impl Default for YouRust { 101 | fn default() -> Self { 102 | Self(Params { 103 | clippy_flags: CLIPPY_FLAGS.iter().map(|&err| err.into()).collect(), 104 | rust_flags: RUST_FLAGS.iter().map(|&err| err.into()).collect(), 105 | rustfmt_flags: RUSTFMT_FLAGS.iter().map(|&err| err.into()).collect(), 106 | toolchain: String::new(), 107 | }) 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /rust-tools/src/cfg_option.rs: -------------------------------------------------------------------------------- 1 | use crate::{cfg::YouRust, Params}; 2 | 3 | create_enum_with_list! { 4 | crate::Error::UnknownCfg; 5 | 6 | #[derive(Debug)] 7 | pub(crate) enum CfgOption { 8 | YouRust, "you-rust"; 9 | } 10 | } 11 | 12 | impl CfgOption { 13 | pub(crate) fn into_params(self) -> Params { 14 | match self { 15 | Self::YouRust => YouRust::default().0, 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /rust-tools/src/error.rs: -------------------------------------------------------------------------------- 1 | use crate::{ActionOption, CfgOption}; 2 | use core::fmt::{Debug, Display, Formatter}; 3 | 4 | pub(crate) enum Error { 5 | FailedCommand, 6 | Io(std::io::Error), 7 | UnknownAction, 8 | UnknownCfg, 9 | WrongNumberOfArgs { expected: usize, received: usize }, 10 | } 11 | 12 | impl From for Error { 13 | #[inline] 14 | fn from(from: std::io::Error) -> Self { 15 | Self::Io(from) 16 | } 17 | } 18 | 19 | impl Debug for Error { 20 | #[inline] 21 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> { 22 | match self { 23 | Self::FailedCommand => write!(f, "A command wasn't successful"), 24 | Self::Io(err) => write!(f, "IO: {err}"), 25 | Self::UnknownAction => write!( 26 | f, 27 | "Unknown action, please select one of the following possibilities: {}", 28 | ActionOption::list() 29 | ), 30 | Self::UnknownCfg => write!( 31 | f, 32 | "Unknown configuration, please select one of the following possibilities: {}", 33 | CfgOption::list() 34 | ), 35 | Self::WrongNumberOfArgs { expected, received } => { 36 | write!(f, "Wrong number of arguments. Expected {expected} but received {received}") 37 | } 38 | } 39 | } 40 | } 41 | 42 | impl Display for Error { 43 | #[inline] 44 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> { 45 | Debug::fmt(self, f) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /rust-tools/src/macros.rs: -------------------------------------------------------------------------------- 1 | macro_rules! create_enum_with_list { 2 | ( 3 | $err:expr; 4 | 5 | $(#[$mac:meta])* 6 | $v:vis enum $enum_ident:ident { 7 | $first_variant_ident:ident, $first_variant_str:literal; 8 | $($variant_ident:ident, $variant_str:literal;)* 9 | } 10 | ) => { 11 | $(#[$mac])* 12 | $v enum $enum_ident { 13 | $first_variant_ident, 14 | $($variant_ident,)* 15 | } 16 | 17 | impl $enum_ident { 18 | #[inline] 19 | pub(crate) const fn list() -> &'static str { 20 | concat!( 21 | $first_variant_str, 22 | $(", ", $variant_str,)* 23 | ) 24 | } 25 | } 26 | 27 | impl core::str::FromStr for $enum_ident { 28 | type Err = crate::Error; 29 | 30 | #[inline] 31 | fn from_str(str: &str) -> Result { 32 | Ok(match str { 33 | $first_variant_str => Self::$first_variant_ident, 34 | $($variant_str => Self::$variant_ident,)* 35 | _ => return Err($err), 36 | }) 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /rust-tools/src/main.rs: -------------------------------------------------------------------------------- 1 | //! Rust tools 2 | 3 | #[macro_use] 4 | mod macros; 5 | 6 | mod action_option; 7 | mod actions; 8 | mod cfg; 9 | mod cfg_option; 10 | mod error; 11 | mod params; 12 | mod parse_cfg; 13 | mod transforming_params; 14 | 15 | use action_option::ActionOption; 16 | use actions::Actions; 17 | use cfg_option::CfgOption; 18 | use error::Error; 19 | use params::Params; 20 | use parse_cfg::parse_cfg; 21 | use std::{ 22 | env::{args, Args}, 23 | fs::File, 24 | io::{stderr, stdout, BufRead, BufReader, Write}, 25 | process::Command, 26 | }; 27 | use transforming_params::TransformingParams; 28 | 29 | type Result = core::result::Result; 30 | 31 | fn main() -> Result<()> { 32 | let mut args = args(); 33 | let _first_arg = arg(&mut args)?; 34 | let mut maybe_action = arg(&mut args)?; 35 | 36 | let mut param = |name: &str| { 37 | Ok::<_, Error>(if maybe_action == name { 38 | let rslt = arg(&mut args)?; 39 | maybe_action = arg(&mut args)?; 40 | rslt 41 | } else { 42 | <_>::default() 43 | }) 44 | }; 45 | 46 | let file = param("--file")?; 47 | let (mut params, mut tp) = 48 | if file.is_empty() { Default::default() } else { parse_cfg(File::open(file)?)? }; 49 | 50 | let template = param("--template")?; 51 | if !template.is_empty() { 52 | params = template.parse::()?.into_params(); 53 | } 54 | 55 | let toolchain = param("--toolchain")?; 56 | if !toolchain.is_empty() { 57 | tp.toolchain = toolchain; 58 | } 59 | 60 | parse_action(&mut args, &maybe_action, params, tp)?; 61 | 62 | Ok(()) 63 | } 64 | 65 | fn handle_cmd_output(cmd: &mut Command) -> Result<()> { 66 | let mut buffer = String::new(); 67 | let mut child = cmd.spawn()?; 68 | macro_rules! write_stdio { 69 | ($inner:expr, $output:expr) => { 70 | let mut br = BufReader::new($inner); 71 | while br.read_line(&mut buffer)? != 0 { 72 | $output.write_all(buffer.as_bytes())?; 73 | buffer.clear(); 74 | } 75 | }; 76 | } 77 | if let Some(ref mut child_stderr) = child.stderr { 78 | write_stdio!(child_stderr, stderr()); 79 | } 80 | if let Some(ref mut child_stdout) = child.stdout { 81 | write_stdio!(child_stdout, stdout()); 82 | } 83 | if !child.wait()?.success() { 84 | return Err(Error::FailedCommand); 85 | } 86 | Ok(()) 87 | } 88 | 89 | fn opt(args: &mut Args) -> String { 90 | args.next().unwrap_or_default() 91 | } 92 | 93 | fn parse_action( 94 | args: &mut Args, 95 | action_string: &str, 96 | params: Params, 97 | mut tp: TransformingParams, 98 | ) -> Result<()> { 99 | let mut actions = Actions::new(params); 100 | match action_string.parse()? { 101 | ActionOption::BuildGeneric => { 102 | actions.params.modify(&tp); 103 | actions.build_generic(arg(args)?)?; 104 | } 105 | ActionOption::BuildWithFeatures => { 106 | actions.params.modify(&tp); 107 | actions.build_with_features(arg(args)?, opt(args))?; 108 | } 109 | ActionOption::CheckGeneric => { 110 | actions.params.modify(&tp); 111 | actions.check_generic(arg(args)?)?; 112 | } 113 | ActionOption::CheckWithFeatures => { 114 | actions.params.modify(&tp); 115 | actions.check_with_features(arg(args)?, opt(args))?; 116 | } 117 | ActionOption::Clippy => { 118 | tp.add_clippy_flags.extend(opt(args).split(',').map(Into::into)); 119 | tp.rm_clippy_flags.extend(opt(args).split(',').map(Into::into)); 120 | actions.params.modify(&tp); 121 | actions.clippy(args)?; 122 | } 123 | ActionOption::RustFlags => { 124 | tp.add_rust_flags.extend(opt(args).split(',').map(Into::into)); 125 | tp.rm_rust_flags.extend(opt(args).split(',').map(Into::into)); 126 | actions.params.modify(&tp); 127 | actions.rust_flags()?; 128 | } 129 | ActionOption::Rustfmt => { 130 | actions.params.modify(&tp); 131 | Actions::rustfmt()?; 132 | } 133 | ActionOption::SetUp => { 134 | actions.params.modify(&tp); 135 | actions.set_up()?; 136 | } 137 | ActionOption::TargetDir => { 138 | actions.params.modify(&tp); 139 | Actions::target_dir()?; 140 | } 141 | ActionOption::TestGeneric => { 142 | actions.params.modify(&tp); 143 | actions.test_generic(arg(args)?)?; 144 | } 145 | ActionOption::TestWithFeatures => { 146 | actions.params.modify(&tp); 147 | actions.test_with_features(arg(args)?, opt(args))?; 148 | } 149 | }; 150 | Ok(()) 151 | } 152 | 153 | fn arg(args: &mut Args) -> Result { 154 | args.next().ok_or(Error::WrongNumberOfArgs { expected: 1, received: 0 }) 155 | } 156 | -------------------------------------------------------------------------------- /rust-tools/src/params.rs: -------------------------------------------------------------------------------- 1 | use crate::TransformingParams; 2 | 3 | #[derive(Debug, Default, PartialEq)] 4 | pub(crate) struct Params { 5 | pub(crate) clippy_flags: Vec, 6 | pub(crate) rust_flags: Vec, 7 | pub(crate) rustfmt_flags: Vec, 8 | pub(crate) toolchain: String, 9 | } 10 | 11 | impl Params { 12 | pub(crate) fn modify(&mut self, tp: &TransformingParams) { 13 | manage_flags(&mut self.clippy_flags, &tp.add_clippy_flags, &tp.rm_clippy_flags); 14 | manage_flags(&mut self.rust_flags, &tp.add_rust_flags, &tp.rm_rust_flags); 15 | manage_flags(&mut self.rustfmt_flags, &tp.add_rustfmt_flags, &tp.rm_rustfmt_flags); 16 | if !tp.toolchain.is_empty() { 17 | self.toolchain.clone_from(&tp.toolchain); 18 | } 19 | } 20 | } 21 | 22 | fn manage_flags(flags: &mut Vec, to_add: &[String], to_subtract: &[String]) { 23 | let iter = flags 24 | .iter() 25 | .chain(to_add) 26 | .filter(move |flag| !flag.is_empty() && to_subtract.iter().all(|s| s != *flag)); 27 | *flags = iter.cloned().collect(); 28 | } 29 | -------------------------------------------------------------------------------- /rust-tools/src/parse_cfg.rs: -------------------------------------------------------------------------------- 1 | use crate::{CfgOption, Params, TransformingParams}; 2 | use std::io::{BufRead, BufReader, Read}; 3 | 4 | #[allow( 5 | // False positive 6 | clippy::redundant_closure_call 7 | )] 8 | pub(crate) fn parse_cfg(read: R) -> crate::Result<(Params, TransformingParams)> 9 | where 10 | R: Read, 11 | { 12 | let mut br = BufReader::new(read); 13 | let mut overall_buffer = String::with_capacity(16); 14 | let mut params = Params::default(); 15 | let mut tp = TransformingParams::default(); 16 | 17 | iterations(&mut overall_buffer, &mut br, |_| false)?; 18 | macro_rules! push { 19 | (vec: $name:ident) => { 20 | push!($name, |rslt: &str| { 21 | for value in rslt.split(',') { 22 | tp.$name.push(value.trim().into()); 23 | } 24 | Ok(()) 25 | }) 26 | }; 27 | ($name:ident, $cb:expr) => { 28 | let name = stringify!($name); 29 | if let Some(rslt) = overall_buffer.split(name).nth(1) { 30 | let cb: crate::Result<()> = $cb(rslt); 31 | cb?; 32 | iterations(&mut overall_buffer, &mut br, |_| false)?; 33 | } 34 | }; 35 | } 36 | 37 | push!(vec: add_clippy_flags); 38 | push!(vec: rm_clippy_flags); 39 | push!(vec: add_rust_flags); 40 | push!(vec: rm_rust_flags); 41 | push!(vec: add_rustfmt_flags); 42 | push!(vec: rm_rustfmt_flags); 43 | push!(template, |rslt: &str| { 44 | params = rslt.trim().parse::()?.into_params(); 45 | Ok(()) 46 | }); 47 | push!(toolchain, |rslt: &str| { 48 | tp.toolchain = rslt.trim().into(); 49 | Ok(()) 50 | }); 51 | Ok((params, tp)) 52 | } 53 | 54 | fn iterations( 55 | overall_buffer: &mut String, 56 | br: &mut BufReader, 57 | mut cb: impl FnMut(&str) -> bool, 58 | ) -> crate::Result<()> 59 | where 60 | R: Read, 61 | { 62 | overall_buffer.clear(); 63 | let mut bytes_read = 0; 64 | 65 | loop { 66 | let curr_bytes_read = br.read_line(overall_buffer)?; 67 | 68 | if curr_bytes_read == 0 { 69 | break; 70 | } 71 | 72 | let Some(str_read) = overall_buffer.get(bytes_read..) else { 73 | break; 74 | }; 75 | let trimmed = str_read.trim(); 76 | 77 | bytes_read = bytes_read.saturating_add(curr_bytes_read); 78 | 79 | if trimmed.is_empty() || trimmed.starts_with("//") { 80 | continue; 81 | } 82 | 83 | if !cb(trimmed) { 84 | break; 85 | } 86 | } 87 | 88 | Ok(()) 89 | } 90 | 91 | #[cfg(test)] 92 | mod tests { 93 | use crate::{cfg::YouRust, parse_cfg}; 94 | 95 | #[test] 96 | fn parsed_configuration_has_correct_params() { 97 | let cfg = br#" 98 | add_clippy_flags A 99 | rm_clippy_flags B, C 100 | add_rust_flags D 101 | rm_rust_flags E 102 | add_rustfmt_flags F 103 | template you-rust 104 | toolchain nightly-2024-09-07 105 | "#; 106 | let (params, tp) = parse_cfg(&cfg[..]).unwrap(); 107 | assert_eq!(params, YouRust::default().0); 108 | assert_eq!(tp.add_clippy_flags, vec!["A"]); 109 | assert_eq!(tp.rm_clippy_flags, vec!["B", "C"]); 110 | assert_eq!(tp.add_rust_flags, vec!["D"]); 111 | assert_eq!(tp.rm_rust_flags, vec!["E"]); 112 | assert_eq!(tp.add_rustfmt_flags, vec!["F"]); 113 | assert_eq!(tp.rm_rustfmt_flags, Vec::::new()); 114 | assert_eq!(tp.toolchain, "nightly-2024-09-07"); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /rust-tools/src/transforming_params.rs: -------------------------------------------------------------------------------- 1 | #[derive(Default)] 2 | pub(crate) struct TransformingParams { 3 | pub(crate) add_clippy_flags: Vec, 4 | pub(crate) add_rust_flags: Vec, 5 | pub(crate) add_rustfmt_flags: Vec, 6 | pub(crate) rm_clippy_flags: Vec, 7 | pub(crate) rm_rust_flags: Vec, 8 | pub(crate) rm_rustfmt_flags: Vec, 9 | pub(crate) toolchain: String, 10 | } 11 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | edition="2021" 2 | imports_granularity = "Crate" 3 | newline_style = "Unix" 4 | reorder_imports = true 5 | tab_spaces=2 6 | use_field_init_shorthand=true 7 | use_small_heuristics="Max" 8 | --------------------------------------------------------------------------------