├── .github ├── action │ └── publish_dart_package │ │ └── action.yml └── workflows │ ├── dart.yml │ └── publish.yml ├── .gitignore ├── .idea ├── kart.iml ├── libraries │ ├── Dart_Packages.xml │ └── Dart_SDK.xml ├── misc.xml ├── modules.xml └── vcs.xml ├── .pubignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── analysis_options.yaml ├── example └── kart_example.dart ├── kart.iml ├── lib ├── kart.dart └── src │ └── foundation │ ├── cast.dart │ ├── kt │ ├── collections │ │ ├── iterables.dart │ │ ├── lists.dart │ │ └── maps.dart │ └── standard │ │ └── standard.dart │ ├── pair │ └── pair.dart │ └── string │ └── strings.dart ├── pubspec.yaml └── test ├── foundation ├── cast_test.dart └── kt │ ├── collections │ ├── iterable_join_to_string_test.dart │ ├── iterable_map_test.dart │ ├── iterables_foreach_test.dart │ ├── iterables_get_elements_test.dart │ ├── iterables_test.dart │ ├── list_test.dart │ └── map │ │ ├── maps_get_test.dart │ │ └── nullable_map_test.dart │ └── standard │ └── standart_test.dart ├── kart_test.dart ├── pair └── pair_test.dart └── test_helper.dart /.github/action/publish_dart_package/action.yml: -------------------------------------------------------------------------------- 1 | name: Publish Flutter package to pub.dev 2 | description: Publish your Flutter package to pub.dev 3 | 4 | inputs: 5 | working-directory: 6 | description: directory with-in the repository where the package is located (if not in the repository root) 7 | required: false 8 | 9 | runs: 10 | using: "composite" 11 | steps: 12 | - name: 📚 Git Checkout 13 | uses: actions/checkout@v4 14 | - name: 🐦 Setup Dart 15 | uses: dart-lang/setup-dart@v1 16 | 17 | - name: 🪪 Get Id Token 18 | uses: actions/github-script@v6 19 | with: 20 | script: | 21 | let pub_token = await core.getIDToken('https://pub.dev') 22 | core.exportVariable('PUB_TOKEN', pub_token) 23 | 24 | - name: 📢 Authenticate 25 | shell: ${{ inputs.shell }} 26 | run: dart pub token add https://pub.dev --env-var PUB_TOKEN 27 | 28 | - name: 📦 Install dependencies 29 | shell: ${{ inputs.shell }} 30 | run: dart pub get 31 | working-directory: ${{ inputs.working-directory }} 32 | 33 | # - name: 🌵 Dry Run 34 | # shell: ${{ inputs.shell }} 35 | # run: dart pub publish --dry-run 36 | # working-directory: ${{ inputs.working-directory }} 37 | 38 | - name: 📢 Publish 39 | shell: ${{ inputs.shell }} 40 | run: dart pub publish -f 41 | working-directory: ${{ inputs.working-directory }} 42 | -------------------------------------------------------------------------------- /.github/workflows/dart.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. 2 | # They are provided by a third-party and are governed by 3 | # separate terms of service, privacy policy, and support 4 | # documentation. 5 | 6 | name: Dart 7 | 8 | on: 9 | push: 10 | branches: [ "main" ] 11 | pull_request: 12 | branches: [ "main" ] 13 | 14 | jobs: 15 | build: 16 | runs-on: ubuntu-latest 17 | 18 | steps: 19 | - uses: actions/checkout@v3 20 | 21 | # Note: This workflow uses the latest stable version of the Dart SDK. 22 | # You can specify other versions if desired, see documentation here: 23 | # https://github.com/dart-lang/setup-dart/blob/main/README.md 24 | # - uses: dart-lang/setup-dart@v1 25 | - uses: dart-lang/setup-dart@9a04e6d73cca37bd455e0608d7e5092f881fd603 26 | 27 | - name: Install dependencies 28 | run: dart pub get 29 | 30 | # Uncomment this step to verify the use of 'dart format' on each commit. 31 | # - name: Verify formatting 32 | # run: dart format --output=none --set-exit-if-changed . 33 | 34 | # Consider passing '--fatal-infos' for slightly stricter analysis. 35 | - name: Analyze project source 36 | run: dart analyze 37 | 38 | # Your project will need to have tests in test/ and a dependency on 39 | # package:test for this step to succeed. Note that Flutter projects will 40 | # want to change this to 'flutter test'. 41 | - name: Run tests 42 | run: dart test 43 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish to pub.dev 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v[0-9]+.[0-9]+.[0-9]+*' 7 | 8 | jobs: 9 | publish: 10 | environment: 'pub.dev' 11 | permissions: 12 | id-token: write # Required for authentication using OIDC 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: 📚 Git Checkout 16 | uses: actions/checkout@v4 17 | with: 18 | submodules: recursive 19 | - uses: ./.github/action/publish_dart_package 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Files and directories created by pub. 2 | .dart_tool/ 3 | .packages 4 | 5 | # Conventional directory for build outputs. 6 | build/ 7 | 8 | # Omit committing pubspec.lock for library packages; see 9 | # https://dart.dev/guides/libraries/private-files#pubspeclock. 10 | pubspec.lock 11 | .idea/workspace.xml -------------------------------------------------------------------------------- /.idea/kart.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/libraries/Dart_Packages.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | -------------------------------------------------------------------------------- /.idea/libraries/Dart_SDK.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.pubignore: -------------------------------------------------------------------------------- 1 | # Files and directories created by pub. 2 | .dart_tool/ 3 | .packages 4 | 5 | # Conventional directory for build outputs. 6 | build/ 7 | 8 | # Omit committing pubspec.lock for library packages; see 9 | # https://dart.dev/guides/libraries/private-files#pubspeclock. 10 | pubspec.lock 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 1.0.9 2 | * Override toString and `==` for Pair. 3 | 4 | # 1.0.8 5 | * orEmpty for List and Map. 6 | 7 | # 1.0.7 8 | * firstNotNullOfOrNull for iterable. 9 | 10 | ## 1.0.6 11 | * joinToString for iterable. 12 | 13 | ## 1.0.5 14 | * fistOrNullIf, lastOrNullIf for List and Iterable. 15 | 16 | ## 1.0.4+1 17 | * Fix mapNotNull issue. 18 | 19 | ## 1.0.4 20 | * Fix let issue. 21 | * Add takeUnless. 22 | 23 | ## 1.0.3 24 | * Add getOrElse for map. 25 | 26 | ## 1.0.2+1 27 | * Fix mapIndex return -1 issue. 28 | 29 | ## 1.0.2 30 | * support mapIndexed and mapNotNull. 31 | 32 | ## 1.0.1 33 | * support lastIndex, getOrElse and getOrNull for iterables. 34 | 35 | ## 1.0.0 36 | 37 | - Initial version. 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [2022] [OpenFlutter] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Collection of extensions 2 | 3 | Dart is good but can be better. 4 | 5 | ## Kotlin Style 6 | 7 | > Join QQ Group now: 1003811176 8 | 9 | For objects: 10 | 11 | - `let` 12 | - `run` 13 | - `also` 14 | - `takeIf` 15 | - `takeUnless` 16 | 17 | For strings: 18 | 19 | - `isBlank()` 20 | - `isNotBlank()` 21 | - `isNullOrBlank()` 22 | - `orEmpty()` 23 | 24 | For iterable 25 | 26 | - `firstOrNull()` 27 | - `lastOrNull()` 28 | - `lastIndex` 29 | - `getOrElse(int,defaultValue)` 30 | - `getOrNull(int)` 31 | - `mapIndexed(int,element)` 32 | - `mapNotNull(element)` 33 | - `firstOrNullIf(predicate)` 34 | - `lastOrNullIf(predicate)` 35 | - `forEachIndexed(index,element)` 36 | - `joinToString` 37 | 38 | For List 39 | 40 | - `firstOrNullIf(predicate)` 41 | - `lastOrNullIf(predicate)` 42 | 43 | For map 44 | - `getOrElse(key,defaultValue)` 45 | - 46 | ## Other 47 | 48 | 49 | `Pair` 50 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the static analysis results for your project (errors, 2 | # warnings, and lints). 3 | # 4 | # This enables the 'recommended' set of lints from `package:lints`. 5 | # This set helps identify many issues that may lead to problems when running 6 | # or consuming Dart code, and enforces writing Dart using a single, idiomatic 7 | # style and format. 8 | # 9 | # If you want a smaller set of lints you can change this to specify 10 | # 'package:lints/core.yaml'. These are just the most critical lints 11 | # (the recommended set includes the core lints). 12 | # The core lints are also what is used by pub.dev for scoring packages. 13 | 14 | include: package:lints/recommended.yaml 15 | 16 | # Uncomment the following section to specify additional rules. 17 | 18 | # linter: 19 | # rules: 20 | # - camel_case_types 21 | 22 | # analyzer: 23 | # exclude: 24 | # - path/to/excluded/files/** 25 | 26 | # For more information about the core and recommended set of lints, see 27 | # https://dart.dev/go/core-lints 28 | 29 | # For additional information about configuring this file, see 30 | # https://dart.dev/guides/language/analysis-options 31 | -------------------------------------------------------------------------------- /example/kart_example.dart: -------------------------------------------------------------------------------- 1 | void main() { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /kart.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /lib/kart.dart: -------------------------------------------------------------------------------- 1 | /// Support for doing something awesome. 2 | /// 3 | /// More dartdocs go here. 4 | library kart; 5 | 6 | export 'src/foundation/kt/standard/standard.dart'; 7 | export 'src/foundation/kt/collections/iterables.dart'; 8 | export 'src/foundation/kt/collections/maps.dart'; 9 | export 'src/foundation/kt/collections/lists.dart'; 10 | export 'src/foundation/cast.dart'; 11 | export 'src/foundation/pair/pair.dart'; 12 | export 'src/foundation/string/strings.dart'; 13 | -------------------------------------------------------------------------------- /lib/src/foundation/cast.dart: -------------------------------------------------------------------------------- 1 | extension CastExtension on T { 2 | R castTo() { 3 | return this as R; 4 | } 5 | 6 | ///cast object to R. 7 | ///returns R if it is R, otherwise null. 8 | R? safeCastTo() { 9 | if (this is R) { 10 | return this as R; 11 | } else { 12 | return null; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lib/src/foundation/kt/collections/iterables.dart: -------------------------------------------------------------------------------- 1 | class IndexedValue { 2 | int index; 3 | T value; 4 | 5 | IndexedValue(this.index, this.value); 6 | 7 | @override 8 | String toString() { 9 | return "[$index]{$value}"; 10 | } 11 | } 12 | 13 | extension KtIterableExtension on Iterable { 14 | Iterable whereNot(bool Function(E it) test) => where((it) => !test(it)); 15 | 16 | /// returns first element or [null] 17 | /// 18 | /// if `this` is is [null] or empty returns [null]. 19 | /// 20 | /// Example: 21 | /// ```dart 22 | /// var result = [].firstOrNull() // null 23 | /// var result = [1,2,3].firstOrNull() // 1 24 | E? firstOrNull() => isEmpty ? null : first; 25 | 26 | /// 27 | /// Returns the first element matching the given [predicate], or null if element was not found. 28 | /// 29 | /// Example: 30 | /// ```dart 31 | /// {"Ada", "James", "Harden", "Bob", "Jane"}.firstOrNullIf((it) => it.length == 9); // null 32 | /// {"Ada", "James", "Harden", "Bob", "Jane"}.firstOrNullIf((it) => it.length == 4); // Jane 33 | /// ``` 34 | /// 35 | E? firstOrNullIf(bool Function(E it) predicate) { 36 | for (var item in this) { 37 | if (predicate(item)) { 38 | return item; 39 | } 40 | } 41 | 42 | return null; 43 | } 44 | 45 | /// returns last element or [null] 46 | /// 47 | /// if `this` is is [null] or empty returns [null]. 48 | /// 49 | /// Example: 50 | /// ```dart 51 | /// var result = [].lastOrNull() // null 52 | /// var result = [1,2,3].lastOrNull() // 3 53 | /// ``` 54 | E? lastOrNull() => isEmpty ? null : last; 55 | 56 | /// 57 | /// Returns the last element matching the given [predicate], or null if element was not found. 58 | /// 59 | /// Example: 60 | /// ```dart 61 | /// {"Ada", "James", "Harden", "Bob", "Jane"}.lastOrNullIf((it) => it.length == 9); // null 62 | /// {"Ada", "James", "Harden", "Bob", "Jane"}.lastOrNullIf((it) => it.length == 3); // Bob 63 | /// ``` 64 | /// 65 | E? lastOrNullIf(bool Function(E it) predicate) { 66 | Iterator it = iterator; 67 | if (!it.moveNext()) { 68 | return null; 69 | } 70 | E? result; 71 | do { 72 | if (predicate(it.current)) { 73 | result = it.current; 74 | } 75 | } while (it.moveNext()); 76 | return result; 77 | } 78 | 79 | /// Returns the index of the last item in the list or -1 if the list is empty. 80 | /// 81 | /// Example: 82 | /// 83 | /// ```dart 84 | /// var result = [1,2,3].lastIndex // 2 85 | /// var result = [].lastIndex // -1 86 | /// 87 | int get lastIndex => length - 1; 88 | } 89 | 90 | extension KtNullabeIterableExtension on Iterable? { 91 | Iterable orEmpty() => this ?? Iterable.empty(); 92 | } 93 | 94 | typedef IterableFallbackElement = T Function(int); 95 | 96 | extension GetElementsForIterable on Iterable { 97 | /// Returns an element at the given index or the result of calling the [defaultValue] function if the index is out of bounds of this list. 98 | /// 99 | /// Example: 100 | /// ```dart 101 | /// Iterable iterables = [1, 2, 3, 4]; 102 | /// var result = iterables.getOrElse(6, (index) => 66); // 66 103 | /// 104 | /// Iterable iterables = [1, 2, 3, 4]; 105 | /// var result = iterables.getOrElse(1, (index) => 66); // 2 106 | /// ``` 107 | E getOrElse(int index, E Function(int) defaultValue) { 108 | if (index >= 0 && index <= lastIndex) { 109 | return elementAt(index); 110 | } else { 111 | return defaultValue(index); 112 | } 113 | } 114 | 115 | /// Returns an element at the given index or null if the index is out of bounds of this list. 116 | /// 117 | /// Example: 118 | /// ```dart 119 | /// Iterable iterables = [1, 2, 3, 4]; 120 | /// var result = iterables.getOrNull(6); // null 121 | /// 122 | /// Iterable iterables = [1, 2, 3, 4]; 123 | /// var result = iterables.getOrNull(1); // 2 124 | /// ``` 125 | /// 126 | E? getOrNull(int index) { 127 | if (index >= 0 && index <= lastIndex) { 128 | return elementAt(index); 129 | } else { 130 | return null; 131 | } 132 | } 133 | 134 | /// Returns the first non-null value produced by [transform] function being applied to elements of this 135 | /// collection in iteration order, or null if no non-null value was produced. 136 | /// Example: 137 | /// ```dart 138 | /// Iterable iterables = ["Ada", "John", "James", "Linda"]; 139 | /// var result = iterables.firstNotNullOfOrNull(transform: (e) { 140 | /// if (e == "James") { 141 | /// return 1; 142 | /// } else { 143 | /// return null; 144 | /// } 145 | /// }); // result is 1 146 | /// 147 | /// int? result = iterables.firstNotNullOfOrNull(transform: (e) { 148 | /// if (e == "Arthur") { 149 | /// return 2; 150 | /// } else { 151 | /// return null; 152 | /// } 153 | /// }); //result is null 154 | /// 155 | R? firstNotNullOfOrNull( 156 | {required R? Function(E e) transform}) { 157 | for (var element in this) { 158 | var result = transform(element); 159 | if (result != null) { 160 | return result; 161 | } 162 | } 163 | 164 | return null; 165 | } 166 | } 167 | 168 | extension MapForIterable on Iterable { 169 | ///Returns a list containing the results of applying the given transform function to each element and its index in the original collection. 170 | /// Params: 171 | /// [transform] - function that takes the index of an element and the element itself and returns the result of the transform applied to the element. 172 | /// 173 | /// Example: 174 | ///```dart 175 | /// Iterable iterables = [1, 2, 3, 4]; 176 | /// var result = iterables.mapIndexed((index, element) => "$index$element"); // ["01", "12", "23", "34"] 177 | /// 178 | /// Set iterables = {1, 2, 3, 4}; 179 | /// var result = iterables.mapIndexed((index, element) => "$index$element"); // ["01", "12", "23", "34"] 180 | /// ``` 181 | Iterable mapIndexed(R Function(int index, E e) transform) { 182 | if (this is List) { 183 | List list = this as List; 184 | return map((e) => transform(list.indexOf(e), e)); 185 | } 186 | var tempList = toList(); 187 | return tempList.map((e) => transform(tempList.indexOf(e), e)); 188 | } 189 | 190 | ///Returns a list containing only the non-null results of applying the given transform function to each element in the original collection. 191 | /// 192 | /// Example: 193 | /// 194 | /// ```dart 195 | /// [1, 2, null, 3, 4, null].mapNotNull((e) => e?.toString()) // ["1", "2", "3", "4"] 196 | /// 197 | /// [1, 5, 3, 4].mapNotNull((e) => "$e") // ["1", "5", "3", "4"] 198 | ///``` 199 | /// 200 | Iterable mapNotNull(R? Function(E? e) transform) { 201 | var resultList = []; 202 | forEach((element) { 203 | final item = transform(element); 204 | if (item != null) { 205 | resultList.add(item); 206 | } 207 | }); 208 | 209 | return resultList; 210 | } 211 | } 212 | 213 | extension ForEachOnIterable on Iterable { 214 | /// 215 | /// Performs the given [action] on each element, providing sequential index with the element. 216 | /// Params: 217 | /// [action] - function that takes the index of an element and the element itself and performs the action on the element. 218 | /// 219 | /// Example: 220 | /// 221 | /// ```dart 222 | /// Iterable list = ["James", "Morgan", "Bon"]; 223 | /// List result = []; 224 | /// list.forEachIndexed((index, element) => result.add("$index$element")); // ["James", "Morgan", "Bon"] 225 | /// ``` 226 | forEachIndexed(Function(int index, E element) action) { 227 | var i = 0; 228 | for (final e in this) { 229 | action(i++, e); 230 | } 231 | } 232 | } 233 | 234 | extension IterableJoinToString on Iterable { 235 | /// Appends the string from all the elements separated using separator and using the given [prefix] and [postfix] if supplied. 236 | /// If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first limit elements will be appended, 237 | /// followed by the [truncated] string (which defaults to "..."). 238 | /// 239 | /// Example: 240 | /// 241 | /// ```dart 242 | /// final result = [1, 2, 3, 4, 5].joinToString(); // 1, 2, 3, 4, 5 243 | /// 244 | /// final result = [1, 2, 3, 4, 5].joinToString( 245 | /// separator: ".", 246 | /// prefix: "prefix", 247 | /// postfix: "postfix", 248 | /// transform: (e) => "${e + 1}"); // prefix2.3.4.5.6postfix 249 | /// 250 | /// final result = [1, 2, 3, 4, 5].joinToString( 251 | /// limit: 4, 252 | /// truncated: "^^^"); // 1, 2, 3, 4, ^^^ 253 | /// ``` 254 | 255 | String joinToString({ 256 | String separator = ', ', 257 | String Function(E element)? transform, 258 | String prefix = '', 259 | String postfix = '', 260 | int limit = -1, 261 | String truncated = '...', 262 | }) { 263 | final buffer = StringBuffer(); 264 | var count = 0; 265 | 266 | buffer.write(prefix); 267 | for (final element in this) { 268 | if (++count > 1) buffer.write(separator); 269 | if (limit < 0 || count <= limit) { 270 | if (transform != null) { 271 | buffer.write(transform(element)); 272 | } else { 273 | buffer.write(element.toString()); 274 | } 275 | } else { 276 | break; 277 | } 278 | } 279 | 280 | if (limit >= 0 && count > limit) { 281 | buffer.write(truncated); 282 | } 283 | 284 | buffer.write(postfix); 285 | return buffer.toString(); 286 | } 287 | } 288 | -------------------------------------------------------------------------------- /lib/src/foundation/kt/collections/lists.dart: -------------------------------------------------------------------------------- 1 | extension ElementsOnList on List { 2 | /// 3 | /// Returns the first element matching the given [predicate], or null if element was not found. 4 | /// 5 | /// Example: 6 | /// ```dart 7 | /// {"Ada", "James", "Harden", "Bob", "Jane"}.firstOrNullIf((it) => it.length == 9); // null 8 | /// {"Ada", "James", "Harden", "Bob", "Jane"}.firstOrNullIf((it) => it.length == 4); // Jane 9 | /// ``` 10 | /// 11 | E? firstOrNullIf(bool Function(E it) predicate) { 12 | int length = this.length; 13 | for (int i = 0; i < length; i++) { 14 | E element = this[i]; 15 | if (predicate(element)) return element; 16 | if (length != this.length) { 17 | throw ConcurrentModificationError(this); 18 | } 19 | } 20 | return null; 21 | } 22 | 23 | /// 24 | /// Returns the last element matching the given [predicate], or null if element was not found. 25 | /// 26 | /// Example: 27 | /// ```dart 28 | /// ["Ada", "James", "Harden", "Bob", "Jane"].lastOrNullIf((it) => it.length == 9); // null 29 | /// ["Ada", "James", "Harden", "Bob", "Jane"].lastOrNullIf((it) => it.length == 3); // Bob 30 | /// ``` 31 | /// 32 | E? lastOrNullIf(bool Function(E it) predicate) { 33 | int length = this.length; 34 | for (int i = length - 1; i >= 0; i--) { 35 | E element = this[i]; 36 | if (predicate(element)) return element; 37 | if (length != this.length) { 38 | throw ConcurrentModificationError(this); 39 | } 40 | } 41 | return null; 42 | } 43 | } 44 | 45 | extension KtNullableListExtension on List? { 46 | /// Returns this List if it's not null and the empty list otherwise. 47 | /// 48 | /// Example: 49 | /// ```dart 50 | /// List? list; 51 | /// var result = list.orEmpty(); // [] 52 | /// List? list = ["Ada"]; 53 | /// var result = list.orEmpty(); // ["Ada"] 54 | /// ``` 55 | List orEmpty() => this ?? []; 56 | } 57 | -------------------------------------------------------------------------------- /lib/src/foundation/kt/collections/maps.dart: -------------------------------------------------------------------------------- 1 | extension KtMapGetExtension on Map { 2 | ///Returns the value for the given key, or the result of the [defaultValue] function if there was no entry for the given key. 3 | /// 4 | /// Example: 5 | /// 6 | /// ```dart 7 | /// var map = { 8 | /// "test1": 1, 9 | /// "test2": 2, 10 | /// }; 11 | /// var result = map.getOrElse("test3", () => 3); // 3 12 | /// 13 | /// var map = { 14 | /// "test1": 1, 15 | /// "test2": 2, 16 | /// }; 17 | /// var result = map.getOrElse("test1", () => 3); // 1 18 | /// 19 | /// ``` 20 | V getOrElse(K key, V Function() defaultValue) { 21 | return this[key] ?? defaultValue(); 22 | } 23 | } 24 | 25 | extension KtNullableMapExtension on Map? { 26 | /// Returns the Map if its not null, or the empty Map otherwise. 27 | /// 28 | /// Example: 29 | /// ```dart 30 | /// Map? map ; 31 | /// var result = map.orEmpty(); // {} 32 | /// Map? map = { 33 | /// "lan":"dart" 34 | /// }; 35 | /// var result = map.orEmpty(); // {"lan":"dart"} 36 | /// ``` 37 | Map orEmpty() => this ?? {}; 38 | } 39 | -------------------------------------------------------------------------------- /lib/src/foundation/kt/standard/standard.dart: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022. OpenFlutter Project 3 | * 4 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor 5 | * license agreements. See the NOTICE file distributed with this work for 6 | * additional information regarding copyright ownership. The ASF licenses this 7 | * file to you under the Apache License, Version 2.0 (the "License"); you may not 8 | * use this file except in compliance with the License. You may obtain a copy of 9 | * the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | * License for the specific language governing permissions and limitations under 17 | * the License. 18 | */ 19 | 20 | extension KtStandardExtension on T { 21 | /// Calls the specified function [block] with this value as its argument and returns its result. 22 | /// Example: 23 | /// 24 | /// ```dart 25 | /// String? str; 26 | /// var result = str?.let((self) { 27 | /// return self.isNotEmpty; 28 | /// }); // null 29 | /// ``` 30 | /// 31 | R let(R Function(T self) block) { 32 | return block(this); 33 | } 34 | 35 | T apply(void Function() block) { 36 | block(); 37 | return this; 38 | } 39 | 40 | R also(R Function(T self) func) { 41 | return func(this); 42 | } 43 | 44 | R run(R Function() func) { 45 | return func(); 46 | } 47 | 48 | T? takeIf(bool Function(T self) predicate) { 49 | if (predicate(this)) { 50 | return this; 51 | } else { 52 | return null; 53 | } 54 | } 55 | 56 | /// Returns this value if it does not satisfy the given predicate or null, if it does. 57 | /// 58 | /// Example: 59 | /// 60 | /// ```dart 61 | /// "James".takeUnless((self) => self == "Tom"); // James 62 | /// "James".takeUnless((self) => self == "James"); // null 63 | /// 64 | /// ``` 65 | T? takeUnless(bool Function(T self) predicate) { 66 | if (!predicate(this)) { 67 | return this; 68 | } else { 69 | return null; 70 | } 71 | } 72 | } 73 | 74 | extension KtStandardExtension2 on T {} 75 | 76 | ///Executes the given function action specified number of times. 77 | /// A zero-based index of current iteration is passed as a parameter to action. 78 | repeat(int times, Function(int index) action) { 79 | for (int index = 0; index < times; index++) { 80 | action(index); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /lib/src/foundation/pair/pair.dart: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022. OpenFlutter Project 3 | * 4 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor 5 | * license agreements. See the NOTICE file distributed with this work for 6 | * additional information regarding copyright ownership. The ASF licenses this 7 | * file to you under the Apache License, Version 2.0 (the "License"); you may not 8 | * use this file except in compliance with the License. You may obtain a copy of 9 | * the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | * License for the specific language governing permissions and limitations under 17 | * the License. 18 | */ 19 | class Pair { 20 | final F first; 21 | final S second; 22 | 23 | const Pair(this.first, this.second); 24 | @override 25 | bool operator ==(Object other) => 26 | identical(this, other) || 27 | other is Pair && 28 | runtimeType == other.runtimeType && 29 | first == other.first && 30 | second == other.second; 31 | 32 | @override 33 | int get hashCode => first.hashCode ^ second.hashCode; 34 | 35 | @override 36 | String toString() => 'Pair($first, $second)'; 37 | } 38 | 39 | /// create pair for given elements first and second. 40 | /// 41 | Pair pairOf(F first, S second) { 42 | return Pair(first, second); 43 | } 44 | -------------------------------------------------------------------------------- /lib/src/foundation/string/strings.dart: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022. OpenFlutter Project 3 | * 4 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor 5 | * license agreements. See the NOTICE file distributed with this work for 6 | * additional information regarding copyright ownership. The ASF licenses this 7 | * file to you under the Apache License, Version 2.0 (the "License"); you may not 8 | * use this file except in compliance with the License. You may obtain a copy of 9 | * the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 16 | * License for the specific language governing permissions and limitations under 17 | * the License. 18 | */ 19 | 20 | extension NullableStringExtension on String? { 21 | /// returns true when given string is null or empty. 22 | bool isNullOrBlank() { 23 | return this?.trim().isEmpty ?? true; 24 | } 25 | 26 | /// returns "" if null. 27 | String orEmpty() { 28 | return this ?? ""; 29 | } 30 | } 31 | 32 | extension StringExtension on String { 33 | bool isBlank() { 34 | return trim().isEmpty; 35 | } 36 | 37 | bool isNotBlank() => !isBlank(); 38 | } 39 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: kart 2 | description: Taste and smell dart a little like Kotlin. We can feel magic of Kotin even in dart. 3 | version: 1.0.9 4 | homepage: https://github.com/OpenFlutter/kart 5 | 6 | environment: 7 | sdk: '>=2.16.2 <4.0.0' 8 | 9 | 10 | # dependencies: 11 | # path: ^1.8.0 12 | 13 | dev_dependencies: 14 | lints: ^1.0.0 15 | test: ^1.16.0 16 | -------------------------------------------------------------------------------- /test/foundation/cast_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:kart/kart.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | group('cast test', () { 6 | test("cast", () { 7 | Iterable hi = [""]; 8 | List map = hi.castTo(); 9 | expect(map.runtimeType, List); 10 | }); 11 | 12 | test("safe cast", () { 13 | int a = 1; 14 | expect(a.safeCastTo(), null); 15 | }); 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /test/foundation/kt/collections/iterable_join_to_string_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:kart/kart.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | group('iterable joinToString test', () { 6 | test("joinToString Default", () { 7 | final result = [1, 2, 3, 4, 5].joinToString(); 8 | expect(result, "1, 2, 3, 4, 5"); 9 | }); 10 | 11 | test("joinToString withNullable", () { 12 | final result = [1, 2, 3, 4, 5, null].joinToString(); 13 | expect(result, "1, 2, 3, 4, 5, null"); 14 | }); 15 | 16 | test("joinToString ", () { 17 | final result = [1, 2, 3, 4, 5].joinToString( 18 | separator: ".", 19 | prefix: "prefix", 20 | postfix: "postfix", 21 | transform: (e) => "${e + 1}", 22 | ); 23 | expect(result, "prefix2.3.4.5.6postfix"); 24 | }); 25 | 26 | test("joinToString truncated", () { 27 | final result = [1, 2, 3, 4, 5].joinToString(limit: 4, truncated: "^^^"); 28 | expect(result, "1, 2, 3, 4, ^^^"); 29 | }); 30 | }); 31 | } 32 | -------------------------------------------------------------------------------- /test/foundation/kt/collections/iterable_map_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:kart/kart.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | group('iterable mapIndex test', () { 6 | test("mapIndex List Expected Correct", () { 7 | Iterable<_MapTestObject> iterables = [ 8 | _MapTestObject("1"), 9 | _MapTestObject("2"), 10 | _MapTestObject("3"), 11 | _MapTestObject("4"), 12 | ]; 13 | var result = iterables 14 | .mapIndexed((index, element) => "$index${element.identifier}"); 15 | 16 | expect(result, ["01", "12", "23", "34"]); 17 | }); 18 | 19 | test("mapIndex NotList Expected Correct", () { 20 | Set<_MapTestObject> iterables = { 21 | _MapTestObject("1"), 22 | _MapTestObject("2"), 23 | _MapTestObject("3"), 24 | _MapTestObject("4"), 25 | }; 26 | var result = iterables 27 | .mapIndexed((index, element) => "$index${element.identifier}"); 28 | 29 | expect(result, ["01", "12", "23", "34"]); 30 | }); 31 | }); 32 | 33 | group('iterable mapNotNull test', () { 34 | test("mapNotNull containsNull Expected Correct", () { 35 | Iterable iterables = [1, 2, null, 3, 4, null]; 36 | var result = iterables.mapNotNull((e) => e?.toString()); 37 | 38 | expect(result, ["1", "2", "3", "4"]); 39 | }); 40 | 41 | test("mapNotNull NotContainsNull Expected Correct", () { 42 | Iterable iterables = [1, 5, 3, 4]; 43 | var result = iterables.mapNotNull((e) => "$e"); 44 | 45 | expect(result, ["1", "5", "3", "4"]); 46 | }); 47 | }); 48 | } 49 | 50 | class _MapTestObject { 51 | final String identifier; 52 | 53 | _MapTestObject(this.identifier); 54 | } 55 | -------------------------------------------------------------------------------- /test/foundation/kt/collections/iterables_foreach_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:kart/kart.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | group('iterable forEach test', () { 6 | test("forEachIndexed SourceEmpty ResultEmpty", () { 7 | Iterable list = []; 8 | List result = []; 9 | list.forEachIndexed((index, element) => result.add("$index$element")); 10 | expect(result, containsAll([])); 11 | }); 12 | 13 | test("forEachIndexed HasSource CombinedResult", () { 14 | Iterable list = ["James", "Morgan", "Bon"]; 15 | List result = []; 16 | list.forEachIndexed((index, element) => result.add("$index$element")); 17 | expect(result, containsAll(["0James", "1Morgan", "2Bon"])); 18 | }); 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /test/foundation/kt/collections/iterables_get_elements_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:kart/kart.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | group('iterable get elements test', () { 6 | test("getOrElse Expected DefaultValue", () { 7 | Iterable iterables = [1, 2, 3, 4]; 8 | var result = iterables.getOrElse(6, (index) => 66); 9 | expect(result, 66); 10 | }); 11 | 12 | test("getOrElse Expected CorrectValue", () { 13 | Iterable iterables = [1, 2, 3, 4]; 14 | var result = iterables.getOrElse(1, (index) => 66); 15 | expect(result, 2); 16 | }); 17 | 18 | test("getOrNull Expected null", () { 19 | Iterable iterables = [1, 2, 3, 4]; 20 | var result = iterables.getOrNull(6); 21 | expect(result, null); 22 | }); 23 | 24 | test("getOrNull Expected CorrectValue", () { 25 | Iterable iterables = [1, 2, 3, 4]; 26 | var result = iterables.getOrNull(1); 27 | expect(result, 2); 28 | }); 29 | }); 30 | 31 | group("firstNotNullOfOrNull", () { 32 | test("non-null value was produced | return 1", () { 33 | Iterable iterables = ["Ada", "John", "James", "Linda"]; 34 | 35 | var result = iterables.firstNotNullOfOrNull(transform: (e) { 36 | if (e == "James") { 37 | return 1; 38 | } else { 39 | return null; 40 | } 41 | }); 42 | 43 | expect(result, 1); 44 | }); 45 | 46 | test("no non-null value was produced | return null", () { 47 | Iterable iterables = ["Ada", "John", "James", "Linda"]; 48 | 49 | int? result = iterables.firstNotNullOfOrNull(transform: (e) { 50 | if (e == "Arthur") { 51 | return null; 52 | } else { 53 | return null; 54 | } 55 | }); 56 | 57 | expect(result, null); 58 | }); 59 | }); 60 | } 61 | -------------------------------------------------------------------------------- /test/foundation/kt/collections/iterables_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:kart/kart.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | group('iterables test', () { 6 | test("iterables orEmpty not empty", () { 7 | List list = ["test"]; 8 | expect(list.orEmpty().isEmpty, false); 9 | }); 10 | 11 | test("iterables orEmpty empty", () { 12 | List? list; 13 | expect(list.orEmpty().isEmpty, true); 14 | }); 15 | }); 16 | 17 | group('no-nullable test firstOrNull', () { 18 | test("first not null", () { 19 | Iterable list = ["test", "test1"]; 20 | expect(list.firstOrNull(), "test"); 21 | }); 22 | 23 | test("first null", () { 24 | Iterable list = []; 25 | expect(list.firstOrNull(), null); 26 | }); 27 | }); 28 | 29 | group('no-nullable iterables test lastOrNull', () { 30 | test("last not null", () { 31 | Iterable list = ["test", "test1"]; 32 | expect(list.lastOrNull(), "test1"); 33 | }); 34 | 35 | test("last null", () { 36 | Iterable list = []; 37 | expect(list.lastOrNull(), null); 38 | }); 39 | }); 40 | 41 | group('nullable test firstOrNull', () { 42 | test("not empty nullable-iterable expect first element not null", () { 43 | Iterable? list = ["test", "test1"]; 44 | expect(list.firstOrNull(), "test"); 45 | }); 46 | 47 | test("empty nullable-iterable expect first element null", () { 48 | Iterable? list = []; 49 | expect(list.firstOrNull(), null); 50 | }); 51 | }); 52 | 53 | group('nullable test lastOrNull', () { 54 | test("not empty null-iterable expect last element not null", () { 55 | Iterable? list = ["test", "test1"]; 56 | expect(list.lastOrNull(), "test1"); 57 | }); 58 | 59 | test("empty nullable-iterable expect last element null", () { 60 | Iterable? list = []; 61 | expect(list.lastOrNull(), null); 62 | }); 63 | }); 64 | 65 | group('test firstOrNullIf', () { 66 | test("firstOrNullIf nameLengthIs3 ExpectJane", () { 67 | Iterable? names = {"Ada", "James", "Harden", "Bob", "Jane"}; 68 | var result = names.firstOrNullIf((it) => it.length == 4); 69 | expect(result, "Jane"); 70 | }); 71 | 72 | test("firstOrNullIf nameLengthIs8 ExpectNull", () { 73 | Iterable? names = {"Ada", "James", "Harden", "Bob", "Jane"}; 74 | var result = names.firstOrNullIf((it) => it.length == 9); 75 | expect(result, null); 76 | }); 77 | }); 78 | 79 | group('test lastOrNullIf', () { 80 | test("lastOrNullIf nameLengthIs3 ExpectBob", () { 81 | Iterable? names = {"Ada", "Jame", "Harden", "Bob", "Jane"}; 82 | var result = names.lastOrNullIf((it) => it.length == 3); 83 | expect(result, "Bob"); 84 | }); 85 | 86 | test("lastOrNullIf nameLengthIs9 ExpectNull", () { 87 | Iterable? names = {"Ada", "Jame", "Harden", "Bob", "Jane"}; 88 | var result = names.lastOrNullIf((it) => it.length == 9); 89 | expect(result, null); 90 | }); 91 | }); 92 | 93 | group('iterable lastIndex test', () { 94 | test("lastIndex is Correct", () { 95 | Iterable list = ["test", "abc", "dart"]; 96 | var result = list.lastIndex; 97 | expect(result, 2); 98 | }); 99 | 100 | test("lastIndex is -1", () { 101 | Iterable list = []; 102 | var result = list.lastIndex; 103 | expect(result, -1); 104 | }); 105 | }); 106 | } 107 | -------------------------------------------------------------------------------- /test/foundation/kt/collections/list_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:kart/kart.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | group('test firstOrNullIf', () { 6 | test("firstOrNullIf nameLengthIs3 ExpectJane", () { 7 | List? names = ["Ada", "James", "Harden", "Bob", "Jane"]; 8 | var result = names.firstOrNullIf((it) => it.length == 4); 9 | expect(result, "Jane"); 10 | }); 11 | 12 | test("firstOrNullIf nameLengthIs8 ExpectNull", () { 13 | List? names = ["Ada", "James", "Harden", "Bob", "Jane"]; 14 | var result = names.firstOrNullIf((it) => it.length == 9); 15 | expect(result, null); 16 | }); 17 | }); 18 | 19 | group('test lastOrNullIf', () { 20 | test("lastOrNullIf nameLengthIs3 ExpectBob", () { 21 | List? names = ["Ada", "James", "Harden", "Bob", "Jane"]; 22 | var result = names.lastOrNullIf((it) => it.length == 3); 23 | expect(result, "Bob"); 24 | }); 25 | 26 | test("lastOrNullIf nameLengthIs9 ExpectNull", () { 27 | List? names = ["Ada", "James", "Harden", "Bob", "Jane"]; 28 | var result = names.lastOrNullIf((it) => it.length == 9); 29 | expect(result, null); 30 | }); 31 | }); 32 | 33 | group("nullable list", () { 34 | test("orEmpty | given list is null | returns empty", () { 35 | List? list; 36 | var result = list.orEmpty(); 37 | expect(result, []); 38 | }); 39 | 40 | test("orEmpty | given list is not null | returns self", () { 41 | List? list = ["Ada"]; 42 | var result = list.orEmpty(); 43 | expect(result, ["Ada"]); 44 | }); 45 | }); 46 | } 47 | -------------------------------------------------------------------------------- /test/foundation/kt/collections/map/maps_get_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:kart/kart.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | group('map getOrElse test', () { 6 | test("map getOrElse Expected NotDefaultValue", () { 7 | var map = { 8 | "test1": 1, 9 | "test2": 2, 10 | }; 11 | var result = map.getOrElse("test1", () => 3); 12 | 13 | expect(result, 1); 14 | }); 15 | 16 | test("map getOrElse Expected defaultValue", () { 17 | var map = { 18 | "test1": 1, 19 | "test2": 2, 20 | }; 21 | var result = map.getOrElse("test3", () => 3); 22 | 23 | expect(result, 3); 24 | }); 25 | }); 26 | } 27 | -------------------------------------------------------------------------------- /test/foundation/kt/collections/map/nullable_map_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:kart/kart.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | group('orEmpty', () { 6 | test(" given map is null || return empty map", () { 7 | Map? map; 8 | var result = map.orEmpty(); 9 | 10 | expect(result, {}); 11 | }); 12 | 13 | test(" given map is null || return empty map", () { 14 | Map? map = {"lan": "dart"}; 15 | var result = map.orEmpty(); 16 | 17 | expect(result, {"lan": "dart"}); 18 | }); 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /test/foundation/kt/standard/standart_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:kart/kart.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | group('Standard test', () { 6 | test("takeIf", () { 7 | String test = "takIf"; 8 | 9 | var result = test.takeIf((self) => self == "takIf"); 10 | expect(result, "takIf"); 11 | 12 | var result2 = test.takeIf((p0) => p0 == "takeIf2"); 13 | expect(result2, null); 14 | }); 15 | 16 | test("takeUnless PredicateTrue ExpectString", () { 17 | String test = "James"; 18 | 19 | var result = test.takeUnless((self) => self == "Tom"); 20 | expect(result, "James"); 21 | }); 22 | 23 | test("takeUnless PredicateFalse ExpectNull", () { 24 | String test = "James"; 25 | var result = test.takeUnless((self) => self == "James"); 26 | expect(result, null); 27 | }); 28 | 29 | test("repeat", () { 30 | var finalIndex = -1; 31 | repeat(10, (index) => finalIndex = index); 32 | expect(finalIndex, 9); 33 | }); 34 | 35 | test("let without?Operator Expect 1", () { 36 | String? str; 37 | var result = str.let((self) { 38 | return 111; 39 | }); 40 | expect(result, 111); 41 | }); 42 | 43 | test("let notNull", () { 44 | String? str = "mapped"; 45 | var result = str.let((self) { 46 | return self.isNotEmpty; 47 | }); 48 | expect(result, true); 49 | }); 50 | }); 51 | } 52 | -------------------------------------------------------------------------------- /test/kart_test.dart: -------------------------------------------------------------------------------- 1 | void main() {} 2 | -------------------------------------------------------------------------------- /test/pair/pair_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:kart/kart.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | group('pair test', () { 6 | test("pair element check", () { 7 | var first = "first"; 8 | var second = 1; 9 | var result = pairOf(first, second); 10 | expect("first", result.first); 11 | expect(1, result.second); 12 | }); 13 | 14 | test("pair equal", () { 15 | var pair1 = pairOf("first", 2); 16 | var pair2 = pairOf("first", 2); 17 | 18 | assert(pair1 == pair2); 19 | }); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/test_helper.dart: -------------------------------------------------------------------------------- 1 | class ClassForTest { 2 | final String name; 3 | 4 | ClassForTest(this.name); 5 | } 6 | --------------------------------------------------------------------------------