├── .gitignore ├── .gitmodules ├── .travis.yml ├── Cargo.toml ├── LICENSE ├── README.md ├── appveyor.yml └── src └── lib.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /local 2 | target 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "scripts"] 2 | path = scripts 3 | url = https://github.com/DanielKeep/rust-script-toolbox.git 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | rust: 3 | - 1.0.0 4 | - 1.1.0 5 | - 1.2.0 6 | - 1.3.0 7 | - 1.4.0 8 | - 1.5.0 9 | - 1.6.0 10 | - 1.7.0 11 | - 1.8.0 12 | - 1.9.0 13 | - 1.10.0 14 | - stable 15 | - beta 16 | - nightly 17 | matrix: 18 | allow_failures: 19 | - rust: nightly 20 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "boolinator" 3 | version = "2.4.1" 4 | authors = ["Daniel Keep "] 5 | 6 | description = "Provides the Boolinator trait, which lets you use Option and Result-style combinators with bools." 7 | repository = "https://github.com/DanielKeep/rust-boolinator" 8 | documentation = "https://danielkeep.github.io/rust-boolinator/doc/boolinator/index.html" 9 | readme = "README.md" 10 | keywords = ["bool", "combinator", "monad", "serious"] 11 | license = "MIT/Apache-2.0" 12 | 13 | exclude = [ 14 | ".gitignore", 15 | ".gitmodules", 16 | ".travis.yml", 17 | "appveyor.yml", 18 | "scripts/*", 19 | ] 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright ⓒ 2016 Daniel Keep. 2 | 3 | Licensed under either of: 4 | 5 | * MIT license, or 6 | * Apache License, Version 2.0 7 | 8 | at your option. 9 | 10 | Unless you explicitly state otherwise, any contribution intentionally 11 | submitted for inclusion in the work by you shall be dual licensed as 12 | above, without any additional terms or conditions. 13 | 14 | # MIT License 15 | 16 | Permission is hereby granted, free of charge, to any person obtaining 17 | a copy of this software and associated documentation files (the 18 | "Software"), to deal in the Software without restriction, including 19 | without limitation the rights to use, copy, modify, merge, publish, 20 | distribute, sublicense, and/or sell copies of the Software, and to 21 | permit persons to whom the Software is furnished to do so, subject 22 | to the following conditions: 23 | 24 | The above copyright notice and this permission notice shall be included 25 | in all copies or substantial portions of the Software. 26 | 27 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 28 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 30 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 31 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 32 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 33 | OTHER DEALINGS IN THE SOFTWARE. 34 | 35 | # Apache License, Version 2.0 36 | 37 | Apache License 38 | Version 2.0, January 2004 39 | http://www.apache.org/licenses/ 40 | 41 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 42 | 43 | 1. Definitions. 44 | 45 | "License" shall mean the terms and conditions for use, reproduction, 46 | and distribution as defined by Sections 1 through 9 of this document. 47 | 48 | "Licensor" shall mean the copyright owner or entity authorized by 49 | the copyright owner that is granting the License. 50 | 51 | "Legal Entity" shall mean the union of the acting entity and all 52 | other entities that control, are controlled by, or are under common 53 | control with that entity. For the purposes of this definition, 54 | "control" means (i) the power, direct or indirect, to cause the 55 | direction or management of such entity, whether by contract or 56 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 57 | outstanding shares, or (iii) beneficial ownership of such entity. 58 | 59 | "You" (or "Your") shall mean an individual or Legal Entity 60 | exercising permissions granted by this License. 61 | 62 | "Source" form shall mean the preferred form for making modifications, 63 | including but not limited to software source code, documentation 64 | source, and configuration files. 65 | 66 | "Object" form shall mean any form resulting from mechanical 67 | transformation or translation of a Source form, including but 68 | not limited to compiled object code, generated documentation, 69 | and conversions to other media types. 70 | 71 | "Work" shall mean the work of authorship, whether in Source or 72 | Object form, made available under the License, as indicated by a 73 | copyright notice that is included in or attached to the work 74 | (an example is provided in the Appendix below). 75 | 76 | "Derivative Works" shall mean any work, whether in Source or Object 77 | form, that is based on (or derived from) the Work and for which the 78 | editorial revisions, annotations, elaborations, or other modifications 79 | represent, as a whole, an original work of authorship. For the purposes 80 | of this License, Derivative Works shall not include works that remain 81 | separable from, or merely link (or bind by name) to the interfaces of, 82 | the Work and Derivative Works thereof. 83 | 84 | "Contribution" shall mean any work of authorship, including 85 | the original version of the Work and any modifications or additions 86 | to that Work or Derivative Works thereof, that is intentionally 87 | submitted to Licensor for inclusion in the Work by the copyright owner 88 | or by an individual or Legal Entity authorized to submit on behalf of 89 | the copyright owner. For the purposes of this definition, "submitted" 90 | means any form of electronic, verbal, or written communication sent 91 | to the Licensor or its representatives, including but not limited to 92 | communication on electronic mailing lists, source code control systems, 93 | and issue tracking systems that are managed by, or on behalf of, the 94 | Licensor for the purpose of discussing and improving the Work, but 95 | excluding communication that is conspicuously marked or otherwise 96 | designated in writing by the copyright owner as "Not a Contribution." 97 | 98 | "Contributor" shall mean Licensor and any individual or Legal Entity 99 | on behalf of whom a Contribution has been received by Licensor and 100 | subsequently incorporated within the Work. 101 | 102 | 2. Grant of Copyright License. Subject to the terms and conditions of 103 | this License, each Contributor hereby grants to You a perpetual, 104 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 105 | copyright license to reproduce, prepare Derivative Works of, 106 | publicly display, publicly perform, sublicense, and distribute the 107 | Work and such Derivative Works in Source or Object form. 108 | 109 | 3. Grant of Patent License. Subject to the terms and conditions of 110 | this License, each Contributor hereby grants to You a perpetual, 111 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 112 | (except as stated in this section) patent license to make, have made, 113 | use, offer to sell, sell, import, and otherwise transfer the Work, 114 | where such license applies only to those patent claims licensable 115 | by such Contributor that are necessarily infringed by their 116 | Contribution(s) alone or by combination of their Contribution(s) 117 | with the Work to which such Contribution(s) was submitted. If You 118 | institute patent litigation against any entity (including a 119 | cross-claim or counterclaim in a lawsuit) alleging that the Work 120 | or a Contribution incorporated within the Work constitutes direct 121 | or contributory patent infringement, then any patent licenses 122 | granted to You under this License for that Work shall terminate 123 | as of the date such litigation is filed. 124 | 125 | 4. Redistribution. You may reproduce and distribute copies of the 126 | Work or Derivative Works thereof in any medium, with or without 127 | modifications, and in Source or Object form, provided that You 128 | meet the following conditions: 129 | 130 | (a) You must give any other recipients of the Work or 131 | Derivative Works a copy of this License; and 132 | 133 | (b) You must cause any modified files to carry prominent notices 134 | stating that You changed the files; and 135 | 136 | (c) You must retain, in the Source form of any Derivative Works 137 | that You distribute, all copyright, patent, trademark, and 138 | attribution notices from the Source form of the Work, 139 | excluding those notices that do not pertain to any part of 140 | the Derivative Works; and 141 | 142 | (d) If the Work includes a "NOTICE" text file as part of its 143 | distribution, then any Derivative Works that You distribute must 144 | include a readable copy of the attribution notices contained 145 | within such NOTICE file, excluding those notices that do not 146 | pertain to any part of the Derivative Works, in at least one 147 | of the following places: within a NOTICE text file distributed 148 | as part of the Derivative Works; within the Source form or 149 | documentation, if provided along with the Derivative Works; or, 150 | within a display generated by the Derivative Works, if and 151 | wherever such third-party notices normally appear. The contents 152 | of the NOTICE file are for informational purposes only and 153 | do not modify the License. You may add Your own attribution 154 | notices within Derivative Works that You distribute, alongside 155 | or as an addendum to the NOTICE text from the Work, provided 156 | that such additional attribution notices cannot be construed 157 | as modifying the License. 158 | 159 | You may add Your own copyright statement to Your modifications and 160 | may provide additional or different license terms and conditions 161 | for use, reproduction, or distribution of Your modifications, or 162 | for any such Derivative Works as a whole, provided Your use, 163 | reproduction, and distribution of the Work otherwise complies with 164 | the conditions stated in this License. 165 | 166 | 5. Submission of Contributions. Unless You explicitly state otherwise, 167 | any Contribution intentionally submitted for inclusion in the Work 168 | by You to the Licensor shall be under the terms and conditions of 169 | this License, without any additional terms or conditions. 170 | Notwithstanding the above, nothing herein shall supersede or modify 171 | the terms of any separate license agreement you may have executed 172 | with Licensor regarding such Contributions. 173 | 174 | 6. Trademarks. This License does not grant permission to use the trade 175 | names, trademarks, service marks, or product names of the Licensor, 176 | except as required for reasonable and customary use in describing the 177 | origin of the Work and reproducing the content of the NOTICE file. 178 | 179 | 7. Disclaimer of Warranty. Unless required by applicable law or 180 | agreed to in writing, Licensor provides the Work (and each 181 | Contributor provides its Contributions) on an "AS IS" BASIS, 182 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 183 | implied, including, without limitation, any warranties or conditions 184 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 185 | PARTICULAR PURPOSE. You are solely responsible for determining the 186 | appropriateness of using or redistributing the Work and assume any 187 | risks associated with Your exercise of permissions under this License. 188 | 189 | 8. Limitation of Liability. In no event and under no legal theory, 190 | whether in tort (including negligence), contract, or otherwise, 191 | unless required by applicable law (such as deliberate and grossly 192 | negligent acts) or agreed to in writing, shall any Contributor be 193 | liable to You for damages, including any direct, indirect, special, 194 | incidental, or consequential damages of any character arising as a 195 | result of this License or out of the use or inability to use the 196 | Work (including but not limited to damages for loss of goodwill, 197 | work stoppage, computer failure or malfunction, or any and all 198 | other commercial damages or losses), even if such Contributor 199 | has been advised of the possibility of such damages. 200 | 201 | 9. Accepting Warranty or Additional Liability. While redistributing 202 | the Work or Derivative Works thereof, You may choose to offer, 203 | and charge a fee for, acceptance of support, warranty, indemnity, 204 | or other liability obligations and/or rights consistent with this 205 | License. However, in accepting such obligations, You may act only 206 | on Your own behalf and on Your sole responsibility, not on behalf 207 | of any other Contributor, and only if You agree to indemnify, 208 | defend, and hold each Contributor harmless for any liability 209 | incurred by, or claims asserted against, such Contributor by reason 210 | of your accepting any such warranty or additional liability. 211 | 212 | END OF TERMS AND CONDITIONS 213 | 214 | APPENDIX: How to apply the Apache License to your work. 215 | 216 | To apply the Apache License to your work, attach the following 217 | boilerplate notice, with the fields enclosed by brackets "[]" 218 | replaced with your own identifying information. (Don't include 219 | the brackets!) The text should be enclosed in the appropriate 220 | comment syntax for the file format. We also recommend that a 221 | file or class name and description of purpose be included on the 222 | same "printed page" as the copyright notice for easier 223 | identification within third-party archives. 224 | 225 | Copyright [yyyy] [name of copyright owner] 226 | 227 | Licensed under the Apache License, Version 2.0 (the "License"); 228 | you may not use this file except in compliance with the License. 229 | You may obtain a copy of the License at 230 | 231 | http://www.apache.org/licenses/LICENSE-2.0 232 | 233 | Unless required by applicable law or agreed to in writing, software 234 | distributed under the License is distributed on an "AS IS" BASIS, 235 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 236 | See the License for the specific language governing permissions and 237 | limitations under the License. 238 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `boolinator` 2 | 3 | Provides the `Boolinator` trait, which lets you use `Option` and `Result`-style combinators with `bool`s. 4 | 5 | **Links** 6 | 7 | * [Latest Release](https://crates.io/crates/boolinator/) 8 | * [Latest Docs](https://danielkeep.github.io/rust-boolinator/doc/boolinator/index.html) 9 | * [Repository](https://github.com/DanielKeep/rust-boolinator) 10 | 11 | ## Compatibility 12 | 13 | `boolinator` is tested against Rust 1.0+. *Exhaustively* so. 14 | 15 | ## License 16 | 17 | Licensed under either of 18 | 19 | * MIT license (see [LICENSE](LICENSE) or ) 20 | * Apache License, Version 2.0 (see [LICENSE](LICENSE) or ) 21 | 22 | at your option. 23 | 24 | ### Contribution 25 | 26 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you shall be dual licensed as above, without any additional terms or conditions. 27 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | matrix: 3 | - TARGET: 1.11.0-x86_64-pc-windows-msvc 4 | - TARGET: 1.11.0-i686-pc-windows-msvc 5 | - TARGET: 1.11.0-x86_64-pc-windows-gnu 6 | - TARGET: 1.11.0-i686-pc-windows-gnu 7 | install: 8 | - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-${env:TARGET}.exe" -FileName "rust-install.exe" 9 | - ps: .\rust-install.exe /VERYSILENT /NORESTART /DIR="C:\rust" | Out-Null 10 | - ps: $env:PATH="$env:PATH;C:\rust\bin" 11 | - rustc -vV 12 | - cargo -vV 13 | build_script: 14 | - cargo build --verbose 15 | - cargo package --allow-dirty 16 | test_script: 17 | - cargo test --verbose 18 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright ⓒ 2016 Daniel Keep. 3 | 4 | Licensed under the MIT license (see LICENSE or ) or the Apache License, Version 2.0 (see LICENSE of 6 | ), at your option. All 7 | files in the project carrying such notice may not be copied, modified, 8 | or distributed except according to those terms. 9 | */ 10 | /*! 11 | 12 | Provides the [`Boolinator`](trait.Boolinator.html) trait, which lets you use `Option` and `Result`-style combinators with `bool`s. 13 | 14 | 27 | 36 | 37 | ## Compatibility 38 | 39 | `boolinator` is tested against Rust 1.0+. *Exhaustively* so. 40 | 41 | */ 42 | // Can't have undocumented APIs! Nosiree! 43 | #![deny(missing_docs)] 44 | 45 | /** 46 | This trait defines a number of combinator-style methods for use with `bool` values. 47 | 48 | In general, `true`/`false` map to `Some(_)`/`None` and `Ok(_)`/`Err(_)` respectively. 49 | */ 50 | pub trait Boolinator: Sized { 51 | /** 52 | If this value is `true`, returns `Some(())`; `None` otherwise. 53 | */ 54 | fn as_option(self) -> Option<()>; 55 | 56 | /** 57 | If this value is `true`, returns `Some(some)`; `None` otherwise. 58 | */ 59 | fn as_some(self, some: T) -> Option; 60 | 61 | /** 62 | If this value is `true`, returns `Some(some())`; `None` otherwise. 63 | */ 64 | fn as_some_from(self, some: F) -> Option 65 | where F: FnOnce() -> T; 66 | 67 | /** 68 | If this value is `true`, returns `opt`; `None` otherwise. 69 | */ 70 | fn and_option(self, opt: Option) -> Option; 71 | 72 | /** 73 | If this value is `true`, returns `opt()`; `None` otherwise. 74 | */ 75 | fn and_option_from(self, opt: F) -> Option 76 | where F: FnOnce() -> Option; 77 | 78 | /** 79 | If this value is `true`, returns `Ok(ok)`; `Err(err)` otherwise. 80 | */ 81 | fn as_result(self, ok: T, err: E) -> Result; 82 | 83 | /** 84 | If this value is `true`, returns `Ok(ok())`; `Err(err())` otherwise. 85 | */ 86 | fn as_result_from(self, ok: F, err: G) -> Result 87 | where F: FnOnce() -> T, G: FnOnce() -> E; 88 | 89 | /** 90 | If this value is `true`, returns `Ok(())`; `Err(err)` otherwise. 91 | */ 92 | fn ok_or(self, err: E) -> Result<(), E>; 93 | 94 | /** 95 | If this value is `true`, returns `Ok(())`; `Err(err())` otherwise. 96 | */ 97 | fn ok_or_else(self, err: G) -> Result<(), E> 98 | where G: FnOnce() -> E; 99 | 100 | /** 101 | If this value is `true`, does nothing; panics with `msg` otherwise. 102 | */ 103 | fn expect(self, msg: &str); 104 | } 105 | 106 | impl Boolinator for bool { 107 | #[inline] 108 | fn as_option(self) -> Option<()> { 109 | if self { Some(()) } else { None } 110 | } 111 | 112 | #[inline] 113 | fn as_some(self, some: T) -> Option { 114 | if self { Some(some) } else { None } 115 | } 116 | 117 | #[inline] 118 | fn as_some_from(self, some: F) -> Option 119 | where F: FnOnce() -> T { 120 | if self { Some(some()) } else { None } 121 | } 122 | 123 | #[inline] 124 | fn and_option(self, opt: Option) -> Option { 125 | if self { opt } else { None } 126 | } 127 | 128 | #[inline] 129 | fn and_option_from(self, opt: F) -> Option 130 | where F: FnOnce() -> Option { 131 | if self { opt() } else { None } 132 | } 133 | 134 | #[inline] 135 | fn as_result(self, ok: T, err: E) -> Result { 136 | if self { Ok(ok) } else { Err(err) } 137 | } 138 | 139 | #[inline] 140 | fn as_result_from(self, ok: F, err: G) -> Result 141 | where F: FnOnce() -> T, G: FnOnce() -> E { 142 | if self { Ok(ok()) } else { Err(err()) } 143 | } 144 | 145 | #[inline] 146 | fn ok_or(self, err: E) -> Result<(), E> { 147 | if self { Ok(()) } else { Err(err) } 148 | } 149 | 150 | #[inline] 151 | fn ok_or_else(self, err: G) -> Result<(), E> 152 | where G: FnOnce() -> E { 153 | if self { Ok(()) } else { Err(err()) } 154 | } 155 | 156 | #[inline] 157 | fn expect(self, msg: &str) { 158 | if self { () } else { panic!("{}", msg) } 159 | } 160 | } 161 | 162 | /* 163 | Serious code must have serious tests, and Boolinator is serious business! 164 | */ 165 | #[cfg(test)] 166 | mod tests { 167 | use super::Boolinator; // as opposed to the original NES version. 168 | 169 | #[test] 170 | fn test_as_option() { 171 | // Very test. 172 | assert_eq!(true.as_option(), Some(())); 173 | assert_eq!(false.as_option(), None); 174 | } 175 | 176 | #[test] 177 | fn test_as_some() { 178 | // Much serious. 179 | let love = true; 180 | let everybody = love.as_some("body").expect("needs"); 181 | assert_eq!(everybody, "body"); 182 | 183 | assert_eq!((!love).as_some("money can buy"), None); 184 | } 185 | 186 | #[test] 187 | fn test_as_some_from() { 188 | // Wow. 189 | let mothers = vec![true, false, false, true, false, true]; 190 | assert!(mothers.into_iter() 191 | .map(|e| e.as_some_from(|| Some("em"))) 192 | .filter(Option::is_some) 193 | .count() > 0); 194 | } 195 | 196 | #[test] 197 | fn test_and_option() { 198 | // Such original. 199 | assert_eq!(true.and_option(Some("fries with that")), Some("fries with that")); 200 | assert_eq!(false.and_option(Some("fries with that")), None); 201 | assert_eq!(true.and_option(None), None::<()>); 202 | assert_eq!(false.and_option(None), None::<()>); 203 | } 204 | 205 | #[test] 206 | fn test_and_option_from() { 207 | // Such original. 208 | assert_eq!(true.and_option_from(|| Some("chips too, guv'")), Some("chips too, guv'")); 209 | assert_eq!(false.and_option_from(|| Some("chips too, guv'")), None); 210 | assert_eq!(true.and_option_from(|| None), None::<()>); 211 | assert_eq!(false.and_option_from(|| None), None::<()>); 212 | } 213 | 214 | #[test] 215 | fn test_as_result() { 216 | // Very result. 217 | assert_eq!(true.as_result("now; ", ", what?"), Ok("now; ")); 218 | assert_eq!(false.as_result("now; ", ", what?"), Err(", what?")); 219 | } 220 | 221 | #[test] 222 | fn test_as_result_from() { 223 | // Code good. 224 | assert_eq!(true.as_result_from(|| "four space indent", || "anything else"), Ok("four space indent")); 225 | assert_eq!(false.as_result_from(|| "four space indent", || "anything else"), Err("anything else")); 226 | } 227 | 228 | #[test] 229 | fn test_ok_or() { 230 | // Ok. 231 | let mut annie = true; 232 | assert_eq!(annie.ok_or("hit back"), Ok(())); 233 | annie = false; 234 | assert_eq!(annie.ok_or("hit back"), Err("hit back")); 235 | } 236 | 237 | #[test] 238 | fn test_ok_or_else() { 239 | // Ok. 240 | let mut annie = true; 241 | assert_eq!(annie.ok_or_else(|| "hit back"), Ok(())); 242 | annie = false; 243 | assert_eq!(annie.ok_or_else(|| "hit back"), Err("hit back")); 244 | } 245 | 246 | const DREAMS: &'static str = "love and financial security"; 247 | 248 | #[test] 249 | fn test_expect() { 250 | // Movies lie. 251 | true.expect(DREAMS); 252 | } 253 | 254 | #[test] 255 | #[should_panic] 256 | fn test_expect_reality() { 257 | // Send hugs. 258 | false.expect(DREAMS); 259 | } 260 | } 261 | --------------------------------------------------------------------------------