├── .github └── workflows │ └── rust.yml ├── .gitignore ├── CHANGELOG.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md └── src ├── boolean_toggler.rs └── lib.rs /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - main 10 | 11 | env: 12 | RUST_BACKTRACE: 1 13 | 14 | jobs: 15 | test: 16 | name: Test Rust - ${{ matrix.build }} 17 | runs-on: ${{ matrix.os }} 18 | env: 19 | CARGO: cargo 20 | TARGET: "" 21 | strategy: 22 | fail-fast: false 23 | matrix: 24 | build: 25 | - macos 26 | - linux 27 | - linux32 28 | - win64-msvc 29 | - win64-gnu 30 | - win32-msvc 31 | - win32-gnu 32 | - beta 33 | - nightly 34 | - arm32 35 | - arm64 36 | - ppc32 37 | - ppc64 38 | include: 39 | - build: linux 40 | os: ubuntu-latest 41 | rust: stable 42 | - build: macos 43 | os: macos-latest 44 | rust: stable 45 | - build: win64-msvc 46 | os: windows-2019 47 | rust: stable 48 | - build: win64-gnu 49 | os: windows-2019 50 | rust: stable-x86_64-gnu 51 | - build: win32-msvc 52 | os: windows-2019 53 | rust: stable-i686-msvc 54 | - build: win32-gnu 55 | os: windows-2019 56 | rust: stable-i686-gnu 57 | - build: beta 58 | os: ubuntu-latest 59 | rust: beta 60 | - build: nightly 61 | os: ubuntu-latest 62 | rust: nightly 63 | - build: linux32 64 | os: ubuntu-latest 65 | rust: stable 66 | target: i686-unknown-linux-gnu 67 | # should probably not be android 68 | - build: arm32 69 | os: ubuntu-latest 70 | rust: stable 71 | target: armv7-linux-androideabi 72 | - build: arm64 73 | os: ubuntu-latest 74 | rust: stable 75 | target: aarch64-unknown-linux-gnu 76 | # ppc is big endian. 77 | - build: ppc32 78 | os: ubuntu-latest 79 | rust: stable 80 | target: powerpc-unknown-linux-gnu 81 | - build: ppc64 82 | os: ubuntu-latest 83 | rust: stable 84 | target: powerpc64-unknown-linux-gnu 85 | - build: riscv 86 | os: ubuntu-latest 87 | rust: stable 88 | target: riscv64gc-unknown-linux-gnu 89 | 90 | steps: 91 | - uses: actions/checkout@v4 92 | - name: Install Rust 93 | uses: actions-rust-lang/setup-rust-toolchain@v1 94 | with: 95 | toolchain: ${{ matrix.rust }} 96 | 97 | - name: Setup cross if needed 98 | if: matrix.target != '' 99 | run: | 100 | cargo install cross 101 | echo "CARGO=cross" >> $GITHUB_ENV 102 | echo "TARGET=--target ${{ matrix.target }}" >> $GITHUB_ENV 103 | 104 | - name: Show command used for Cargo 105 | run: | 106 | echo "cargo command is: ${{ env.CARGO }}" 107 | echo "target flag is: ${{ env.TARGET }}" 108 | 109 | - name: Test 110 | run: ${{ env.CARGO }} test --verbose ${{ env.TARGET }} 111 | 112 | miri: 113 | name: Miri 114 | runs-on: ubuntu-latest 115 | env: 116 | RUSTFLAGS: "-Zrandomize-layout" 117 | steps: 118 | - uses: actions/checkout@v2 119 | with: 120 | fetch-depth: 1 121 | - uses: actions-rust-lang/setup-rust-toolchain@v1 122 | with: 123 | toolchain: nightly 124 | components: miri 125 | - name: Run tests 126 | run: cargo miri test 127 | 128 | cargo-clippy: 129 | name: Lint 130 | runs-on: ubuntu-latest 131 | env: 132 | RUSTFLAGS: -Dwarnings 133 | steps: 134 | - uses: actions/checkout@v2 135 | with: 136 | fetch-depth: 1 137 | - uses: actions-rust-lang/setup-rust-toolchain@v1 138 | with: 139 | toolchain: stable 140 | - name: Run cargo clippy (default features) 141 | run: cargo clippy --all-targets --verbose -- -D clippy::all 142 | 143 | # Ensure patch is formatted. 144 | fmt: 145 | name: Format 146 | runs-on: ubuntu-latest 147 | steps: 148 | - uses: actions/checkout@v2 149 | with: 150 | fetch-depth: 1 151 | - uses: actions-rust-lang/setup-rust-toolchain@v1 152 | with: 153 | toolchain: stable 154 | components: rustfmt 155 | - name: Check formatting 156 | run: cargo fmt --all -- --check 157 | 158 | # Check doc reference links are all valid. 159 | doc: 160 | name: Doc check 161 | runs-on: ubuntu-latest 162 | steps: 163 | - uses: actions/checkout@v2 164 | with: 165 | fetch-depth: 1 166 | - uses: actions-rust-lang/setup-rust-toolchain@v1 167 | with: 168 | toolchain: nightly 169 | - name: Check docs 170 | # Note: needs cargo rustdoc, not cargo doc. 171 | run: cargo rustdoc --all-features -- -D warnings 172 | 173 | vibe_check: 174 | name: Vibe check 175 | runs-on: ubuntu-latest 176 | steps: 177 | - name: Vibe check 178 | run: | 179 | if [ $((RANDOM % 3)) -eq 0 ]; then 180 | echo "Failed the vibe check!" 181 | exit 1 182 | fi 183 | 184 | sanitizers: 185 | name: Test sanitizer ${{ matrix.sanitizer }} 186 | runs-on: ubuntu-latest 187 | env: 188 | RUST_BACKTRACE: 0 189 | # only used by asan, but we set it for all of them cuz its easy 190 | ASAN_OPTIONS: detect_stack_use_after_return=1 191 | 192 | strategy: 193 | fail-fast: false 194 | matrix: 195 | sanitizer: [address, memory] 196 | include: 197 | - sanitizer: memory 198 | extra_rustflags: "-Zsanitizer-memory-track-origins" 199 | steps: 200 | - uses: actions/checkout@v4 201 | with: 202 | fetch-depth: 1 203 | - uses: actions-rust-lang/setup-rust-toolchain@v1 204 | with: 205 | toolchain: nightly 206 | components: rust-src 207 | 208 | - name: Test with sanitizer 209 | env: 210 | RUSTFLAGS: -Zsanitizer=${{ matrix.sanitizer }} ${{ matrix.extra_rustflags }} 211 | RUSTDOCFLAGS: -Zsanitizer=${{ matrix.sanitizer }} ${{ matrix.extra_rustflags }} 212 | run: | 213 | echo "note: RUSTFLAGS='$RUSTFLAGS'" 214 | cargo -Zbuild-std test --target=x86_64-unknown-linux-gnu 215 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.1.1 2 | 3 | Improved internal architecture. 4 | 5 | ## 1.1.0 6 | 7 | Added SIMD-optimized impl `impl TogglingIsALifestyle for [bool; N]` (available only for enterprise users). 8 | 9 | ## 1.0.0 10 | 11 | Initial release. 12 | -------------------------------------------------------------------------------- /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 = "bool-toggle" 7 | version = "1.1.0" 8 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bool-toggle" 3 | description = "bool toggling for the bool toggle enjoyers" 4 | version = "1.1.1" 5 | edition = "2021" 6 | license = "MIT" 7 | repository = "https://github.com/Nilstrieb/bool-toggle" 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Nilstrieb 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **i love toggling bools it's one of my favourite things to do** 2 | 3 | Provides `fn toggle(&mut self)` on `bool` for toggling bools. 4 | 5 | ```rust 6 | use bool_toggle::TogglingIsALifestyle; 7 | let mut omg_i_want_to_be_toggled_soooo_badly = false; 8 | assert_eq!(omg_i_want_to_be_toggled_soooo_badly, false); 9 | omg_i_want_to_be_toggled_soooo_badly.toggle(); 10 | assert_eq!(omg_i_want_to_be_toggled_soooo_badly, true); 11 | omg_i_want_to_be_toggled_soooo_badly.toggle(); 12 | assert_eq!(omg_i_want_to_be_toggled_soooo_badly, false); 13 | ``` 14 | 15 | ```rust 16 | let i_dont_want_to_be_toggled = false; 17 | // That's okay. 18 | ``` 19 | 20 | ## Enterprise license 21 | 22 | This crate supports a professional re-export of the trait, `BoolToggleExt`. 23 | It is only available when compiling with `--cfg enterprise_license` and obtaining an enterprise license. 24 | For license inquiries, send mail to `/dev/null`. 25 | 26 | ## MSRV 27 | 28 | The minimum supported Rust version of this crate is 1.1000.0. 29 | Lower versions might compile but are not supported. 30 | 31 | ## Architecture 32 | 33 | This Crate features the world's most resilient bit flipping algorithm. Its code adheres to the highest clean code standards 34 | and aims to provide a maintainable and future proof solution to all the boolean toggling needs there are. 35 | -------------------------------------------------------------------------------- /src/boolean_toggler.rs: -------------------------------------------------------------------------------- 1 | use super::TogglingIsALifestyle; 2 | 3 | pub struct BooleanToggler<'a> { 4 | bool_to_toggle: &'a mut bool, 5 | } 6 | 7 | impl TogglingIsALifestyle for BooleanToggler<'_> { 8 | #[inline] 9 | fn toggle(&mut self) { 10 | // i'm enterprise fast 11 | *self.bool_to_toggle ^= true; 12 | } 13 | } 14 | 15 | pub struct BooleanTogglerFactory; 16 | 17 | impl BooleanTogglerFactory { 18 | #[inline] 19 | pub fn create_boolean_toggler(bool_to_toggle: &mut bool) -> BooleanToggler { 20 | BooleanToggler { bool_to_toggle } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![doc = include_str!("../README.md")] 2 | #![cfg_attr(docsrs, feature(doc_cfg))] 3 | 4 | mod boolean_toggler; 5 | 6 | use boolean_toggler::BooleanTogglerFactory; 7 | 8 | // Extension trait for toggling a bool. 9 | pub trait TogglingIsALifestyle { 10 | /// Toggle the bool. 11 | fn toggle(&mut self); 12 | } 13 | 14 | #[cfg_attr(not(docsrs), cfg(enterprise_license))] 15 | #[cfg_attr(docsrs, doc(cfg(enterprise_license)))] 16 | pub use TogglingIsALifestyle as BoolToggleExt; 17 | pub use TogglingIsALifestyle as Toggler; 18 | pub use TogglingIsALifestyle as Toggling; 19 | pub use TogglingIsALifestyle as IAmTheToggler; 20 | 21 | impl TogglingIsALifestyle for bool { 22 | fn toggle(&mut self) { 23 | // i am so smart 24 | BooleanTogglerFactory::create_boolean_toggler(self).toggle(); 25 | } 26 | } 27 | 28 | #[cfg(enterprise_license)] 29 | impl TogglingIsALifestyle for [bool; N] { 30 | fn toggle(&mut self) { 31 | // i am so fast 32 | for b in self { 33 | let mut bool_toggler = BooleanTogglerFactory::create_boolean_toggler(b); 34 | bool_toggler.toggle(); 35 | } 36 | } 37 | } 38 | 39 | #[cfg(test)] 40 | #[allow(clippy::bool_assert_comparison)] 41 | mod tests { 42 | // cheap tests 43 | 44 | use super::TogglingIsALifestyle; 45 | #[test] 46 | fn toggle() { 47 | let mut b = false; 48 | b.toggle(); 49 | assert_eq!(b, true); 50 | b.toggle(); 51 | assert_eq!(b, false); 52 | } 53 | } 54 | 55 | #[cfg(all(test, enterprise_license))] 56 | #[allow(clippy::bool_assert_comparison)] 57 | mod enteprise_tests { 58 | // enterprise-grade tests 59 | // only ran when using an enterprise license for the bool-toggle crate 60 | 61 | use super::BoolToggleExt; 62 | 63 | #[test] 64 | fn enterprise_toggle() { 65 | let mut b = false; 66 | b.toggle(); 67 | assert_eq!(b, true); 68 | } 69 | #[test] 70 | fn enterprise_simd_toggle() { 71 | let mut b = [false, true, false]; 72 | b.toggle(); 73 | assert_eq!(b, [true, false, true]); 74 | } 75 | } 76 | --------------------------------------------------------------------------------