├── analysis_options.yaml ├── lib ├── enum_flag.dart └── src │ └── enum_flag.dart ├── .gitignore ├── CHANGELOG.md ├── pubspec.yaml ├── .github ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md └── workflows │ └── tests.yml ├── example └── example.dart ├── test └── src │ └── enum_flag_test.dart ├── LICENSE ├── README.md └── CODE_OF_CONDUCT.md /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:very_good_analysis/analysis_options.yaml 2 | -------------------------------------------------------------------------------- /lib/enum_flag.dart: -------------------------------------------------------------------------------- 1 | /// Package to create enums for flags using bitmask in Dart using a mixin and 2 | /// extensions. 3 | library enum_flag; 4 | 5 | export 'src/enum_flag.dart'; 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://www.dartlang.org/guides/libraries/private-files 2 | 3 | # Files and directories created by pub 4 | .dart_tool/ 5 | .packages 6 | build/ 7 | coverage/ 8 | pubspec.lock -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 1.0.2 4 | 5 | - Make `EnumFlag` a `mixin` over `Enum` instead of `abstract class` over `Object` 6 | - Upgrade dependencies 7 | 8 | ## 1.0.1 9 | 10 | - Add example 11 | - Improve description of `pubspec.yaml` 12 | - Improve description of `README.md` 13 | 14 | ## 1.0.0 15 | 16 | - Initial release 17 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: enum_flag 2 | description: Package to create enums for flags using bitmask in Dart using a mixin and extensions. 3 | repository: https://github.com/leynier/dart-enum-flag 4 | version: 1.0.2 5 | 6 | environment: 7 | sdk: ">=2.17.0 <3.0.0" 8 | 9 | dev_dependencies: 10 | test: ^1.23.1 11 | very_good_analysis: ^4.0.0+1 12 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: tests 2 | on: push 3 | 4 | jobs: 5 | tests: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - name: 📚 Git Checkout 9 | uses: actions/checkout@v3 10 | - name: 🎯 Setup Dart 11 | uses: dart-lang/setup-dart@v1 12 | - name: 📦 Install Dependencies 13 | run: dart pub get 14 | - name: ✨ Check Formatting 15 | run: dart format --set-exit-if-changed . 16 | - name: 🕵️ Analyze 17 | run: dart analyze --fatal-infos --fatal-warnings lib test 18 | - name: 🧪 Run Tests 19 | run: | 20 | dart pub global activate coverage 1.2.0 21 | dart test -j 4 --coverage=coverage 22 | dart pub global run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.packages --report-on=lib 23 | - name: 📊 Upload Code Coverage 24 | uses: codecov/codecov-action@v2 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /example/example.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: avoid_print 2 | 3 | import 'package:enum_flag/enum_flag.dart'; 4 | 5 | enum EnumX with EnumFlag { 6 | one, 7 | two, 8 | three, 9 | four, 10 | } 11 | 12 | void main() { 13 | print(EnumX.one.value); // 1 14 | print(EnumX.two.value); // 2 15 | print(EnumX.three.value); // 4 16 | print(EnumX.four.value); // 8 17 | print(EnumX.one.value | EnumX.two.value); // 3 18 | print(EnumX.one.value | EnumX.three.value); // 5 19 | print(1.hasFlag(EnumX.one)); // true 20 | print(1.hasFlag(EnumX.two)); // false 21 | print(2.hasFlag(EnumX.one)); // false 22 | print(2.hasFlag(EnumX.two)); // true 23 | print(3.hasFlag(EnumX.one)); // true 24 | print(3.hasFlag(EnumX.two)); // true 25 | print(1.getFlags(EnumX.values)); // [EnumX.one] 26 | print(2.getFlags(EnumX.values)); // [EnumX.two] 27 | print((1 | 2).getFlags(EnumX.values)); // [EnumX.one, EnumX.two] 28 | print(3.getFlags(EnumX.values)); // [EnumX.one, EnumX.two] 29 | print([EnumX.one, EnumX.two].flag); // 3 30 | } 31 | -------------------------------------------------------------------------------- /test/src/enum_flag_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:enum_flag/enum_flag.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | enum EnumX with EnumFlag { 5 | one, 6 | two, 7 | } 8 | 9 | void main() { 10 | test('Test', () { 11 | expect(EnumX.one.value, equals(1)); 12 | expect(EnumX.two.value, equals(2)); 13 | expect(EnumX.one.value | EnumX.two.value, equals(1 | 2)); 14 | expect(1.hasFlag(EnumX.one), isTrue); 15 | expect(1.hasFlag(EnumX.two), isFalse); 16 | expect(2.hasFlag(EnumX.one), isFalse); 17 | expect(2.hasFlag(EnumX.two), isTrue); 18 | expect((1 | 2).hasFlag(EnumX.one), isTrue); 19 | expect(3.hasFlag(EnumX.two), isTrue); 20 | expect(1.getFlags(EnumX.values), equals([EnumX.one])); 21 | expect(2.getFlags(EnumX.values), equals([EnumX.two])); 22 | expect((1 | 2).getFlags(EnumX.values), equals([EnumX.one, EnumX.two])); 23 | expect([EnumX.one].flag, equals(1)); 24 | expect([EnumX.two].flag, equals(2)); 25 | expect([EnumX.one, EnumX.two].flag, equals(1 | 2)); 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Leynier Gutiérrez González 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 | # enum_flag 2 | 3 | [![style: very good analysis][very_good_analysis_badge]][very_good_analysis_link] 4 | [![License: MIT][license_badge]][license_link] 5 | [![Tests](https://github.com/leynier/dart-enum-flag/actions/workflows/tests.yml/badge.svg)](https://github.com/leynier/dart-enum-flag/actions/workflows/tests.yml) 6 | [![Codecov](https://codecov.io/gh/leynier/dart-enum-flag/branch/main/graph/badge.svg?token=Llxe6rjE9g)](https://codecov.io/gh/leynier/dart-enum-flag) 7 | 8 | Package to create enums for flags using bitmask in Dart using a mixin and extensions. 9 | 10 | ## Usage 11 | 12 | ```dart 13 | import 'package:enum_flag/enum_flag.dart'; 14 | 15 | enum EnumX with EnumFlag { 16 | one, 17 | two, 18 | three, 19 | four, 20 | } 21 | 22 | void main() { 23 | print(EnumX.one.value); // 1 24 | print(EnumX.two.value); // 2 25 | print(EnumX.three.value); // 4 26 | print(EnumX.four.value); // 8 27 | print(EnumX.one.value | EnumX.two.value); // 3 28 | print(EnumX.one.value | EnumX.three.value); // 5 29 | print(1.hasFlag(EnumX.one)); // true 30 | print(1.hasFlag(EnumX.two)); // false 31 | print(2.hasFlag(EnumX.one)); // false 32 | print(2.hasFlag(EnumX.two)); // true 33 | print(3.hasFlag(EnumX.one)); // true 34 | print(3.hasFlag(EnumX.two)); // true 35 | print(1.getFlags(EnumX.values)); // [EnumX.one] 36 | print(2.getFlags(EnumX.values)); // [EnumX.two] 37 | print((1 | 2).getFlags(EnumX.values)); // [EnumX.one, EnumX.two] 38 | print(3.getFlags(EnumX.values)); // [EnumX.one, EnumX.two] 39 | print([EnumX.one, EnumX.two].flag); // 3 40 | } 41 | ``` 42 | 43 | [license_badge]: https://img.shields.io/badge/license-MIT-blue.svg 44 | [license_link]: https://opensource.org/licenses/MIT 45 | [very_good_analysis_badge]: https://img.shields.io/badge/style-very_good_analysis-B22C89.svg 46 | [very_good_analysis_link]: https://pub.dev/packages/very_good_analysis 47 | -------------------------------------------------------------------------------- /lib/src/enum_flag.dart: -------------------------------------------------------------------------------- 1 | /// Mixin for [Enum] flags 2 | /// 3 | /// Example: 4 | /// 5 | /// ```dart 6 | /// enum EnumX with EnumFlag { 7 | /// one, 8 | /// two, 9 | /// three, 10 | /// four, 11 | /// } 12 | /// 13 | /// print(EnumX.one.value); // 1 14 | /// print(EnumX.two.value); // 2 15 | /// print(EnumX.three.value); // 4 16 | /// print(EnumX.four.value); // 8 17 | /// print(EnumX.one.value | EnumX.two.value); // 3 18 | /// print(EnumX.one.value | EnumX.three.value); // 5 19 | /// ``` 20 | mixin EnumFlag on Enum { 21 | /// Return the value of the [EnumFlag] 22 | int get value => 1 << index; 23 | } 24 | 25 | /// Extensions over [int] to support [EnumFlag] 26 | extension EnumFlagExtensor on int { 27 | /// Returns true if the [int] value has active the bit of [flag] 28 | /// 29 | /// Example: 30 | /// 31 | /// ```dart 32 | /// enum EnumX with EnumFlag { 33 | /// one, 34 | /// two, 35 | /// } 36 | /// 37 | /// ... 38 | /// 39 | /// print(1.hasFlag(EnumX.one)); // true 40 | /// print(1.hasFlag(EnumX.two)); // false 41 | /// print(2.hasFlag(EnumX.one)); // false 42 | /// print(2.hasFlag(EnumX.two)); // true 43 | /// print(3.hasFlag(EnumX.one)); // true 44 | /// print(3.hasFlag(EnumX.two)); // true 45 | /// ``` 46 | bool hasFlag(EnumFlag flag) => this & flag.value != 0; 47 | 48 | /// Returns a [Iterable] of [EnumFlag] that are active in the [int] value 49 | /// 50 | /// Example: 51 | /// 52 | /// ```dart 53 | /// enum EnumX with EnumFlag { 54 | /// one, 55 | /// two, 56 | /// } 57 | /// 58 | /// ... 59 | /// 60 | /// print(1.getFlags(EnumX.values)); // [EnumX.one] 61 | /// print(2.getFlags(EnumX.values)); // [EnumX.two] 62 | /// print((1 | 2).getFlags(EnumX.values)); // [EnumX.one, EnumX.two] 63 | /// print(3.getFlags(EnumX.values)); // [EnumX.one, EnumX.two] 64 | /// ``` 65 | Iterable getFlags(Iterable flags) => flags.where(hasFlag); 66 | } 67 | 68 | /// Extensions over [Iterable] of [EnumFlag] to support [EnumFlag] 69 | extension EnumFlagsExtensor on Iterable { 70 | /// Returns the [int] with the active bits of the [Iterable] of [EnumFlag] 71 | /// 72 | /// Example: 73 | /// 74 | /// ```dart 75 | /// enum EnumX with EnumFlag { 76 | /// one, 77 | /// two, 78 | /// } 79 | /// 80 | /// ... 81 | /// 82 | /// print([EnumX.one, EnumX.two].flag); // 3 83 | /// ``` 84 | int get flag => fold(0, (int value, EnumFlag flag) => value | flag.value); 85 | } 86 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | leynier41@gmail.com. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | --------------------------------------------------------------------------------