Use bitflags to hold error states

Joseph T. Lyons created

Change summary

Cargo.lock                             | 19 ++++++++-------
crates/feedback2/Cargo.toml            |  6 +++-
crates/feedback2/src/feedback_modal.rs | 33 +++++++++++++++------------
3 files changed, 32 insertions(+), 26 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -182,7 +182,7 @@ dependencies = [
  "alacritty_config",
  "alacritty_config_derive",
  "base64 0.13.1",
- "bitflags 2.4.0",
+ "bitflags 2.4.1",
  "home",
  "libc",
  "log",
@@ -1025,9 +1025,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
 [[package]]
 name = "bitflags"
-version = "2.4.0"
+version = "2.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
+checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
 dependencies = [
  "serde",
 ]
@@ -3280,6 +3280,7 @@ name = "feedback2"
 version = "0.1.0"
 dependencies = [
  "anyhow",
+ "bitflags 2.4.1",
  "client2",
  "db2",
  "editor2",
@@ -4026,7 +4027,7 @@ dependencies = [
  "async-task",
  "backtrace",
  "bindgen 0.65.1",
- "bitflags 2.4.0",
+ "bitflags 2.4.1",
  "block",
  "cbindgen",
  "cocoa",
@@ -6195,7 +6196,7 @@ version = "0.10.57"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c"
 dependencies = [
- "bitflags 2.4.0",
+ "bitflags 2.4.1",
  "cfg-if 1.0.0",
  "foreign-types",
  "libc",
@@ -7915,7 +7916,7 @@ version = "0.29.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "549b9d036d571d42e6e85d1c1425e2ac83491075078ca9a15be021c56b1641f2"
 dependencies = [
- "bitflags 2.4.0",
+ "bitflags 2.4.1",
  "fallible-iterator",
  "fallible-streaming-iterator",
  "hashlink",
@@ -8031,7 +8032,7 @@ version = "0.38.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "747c788e9ce8e92b12cd485c49ddf90723550b654b32508f979b71a7b1ecda4f"
 dependencies = [
- "bitflags 2.4.0",
+ "bitflags 2.4.1",
  "errno 0.3.3",
  "libc",
  "linux-raw-sys 0.4.7",
@@ -9134,7 +9135,7 @@ dependencies = [
  "atoi",
  "base64 0.21.4",
  "bigdecimal",
- "bitflags 2.4.0",
+ "bitflags 2.4.1",
  "byteorder",
  "bytes 1.5.0",
  "chrono",
@@ -9181,7 +9182,7 @@ dependencies = [
  "atoi",
  "base64 0.21.4",
  "bigdecimal",
- "bitflags 2.4.0",
+ "bitflags 2.4.1",
  "byteorder",
  "chrono",
  "crc",

crates/feedback2/Cargo.toml 🔗

@@ -18,7 +18,6 @@ gpui = { package = "gpui2", path = "../gpui2" }
 language = { package = "language2", path = "../language2" }
 menu = { package = "menu2", path = "../menu2" }
 project = { package = "project2", path = "../project2" }
-regex.workspace = true
 search = { package = "search2", path = "../search2" }
 settings = { package = "settings2", path = "../settings2" }
 theme = { package = "theme2", path = "../theme2" }
@@ -26,13 +25,16 @@ ui = { package = "ui2", path = "../ui2" }
 util = { path = "../util" }
 workspace = { package = "workspace2", path = "../workspace2"}
 
+bitflags = "2.4.1"
+human_bytes = "0.4.1"
+
 anyhow.workspace = true
 futures.workspace = true
-human_bytes = "0.4.1"
 isahc.workspace = true
 lazy_static.workspace = true
 log.workspace = true
 postage.workspace = true
+regex.workspace = true
 serde.workspace = true
 serde_derive.workspace = true
 smallvec.workspace = true

crates/feedback2/src/feedback_modal.rs 🔗

@@ -1,6 +1,7 @@
 use std::{ops::RangeInclusive, sync::Arc, time::Duration};
 
 use anyhow::{anyhow, bail};
+use bitflags::bitflags;
 use client::{Client, ZED_SECRET_CLIENT_TOKEN, ZED_SERVER_URL};
 use db::kvp::KEY_VALUE_STORE;
 use editor::{Editor, EditorEvent};
@@ -48,15 +49,17 @@ struct FeedbackRequestBody<'a> {
     token: &'a str,
 }
 
-#[derive(Debug, Clone, PartialEq)]
-enum InvalidStateIssue {
-    EmailAddress,
-    CharacterCount,
+bitflags! {
+    #[derive(Debug, Clone, PartialEq)]
+    struct InvalidStateFlags: u8 {
+        const EmailAddress = 0b00000001;
+        const CharacterCount = 0b00000010;
+    }
 }
 
 #[derive(Debug, Clone, PartialEq)]
 enum CannotSubmitReason {
-    InvalidState { issues: Vec<InvalidStateIssue> },
+    InvalidState { flags: InvalidStateFlags },
     AwaitingSubmission,
 }
 
@@ -322,7 +325,7 @@ impl FeedbackModal {
             return;
         }
 
-        let mut invalid_state_issues = Vec::new();
+        let mut invalid_state_flags = InvalidStateFlags::empty();
 
         let valid_email_address = match self.email_address_editor.read(cx).text_option(cx) {
             Some(email_address) => Regex::new(EMAIL_REGEX).unwrap().is_match(&email_address),
@@ -330,37 +333,37 @@ impl FeedbackModal {
         };
 
         if !valid_email_address {
-            invalid_state_issues.push(InvalidStateIssue::EmailAddress);
+            invalid_state_flags |= InvalidStateFlags::EmailAddress;
         }
 
         if !FEEDBACK_CHAR_LIMIT.contains(&self.character_count) {
-            invalid_state_issues.push(InvalidStateIssue::CharacterCount);
+            invalid_state_flags |= InvalidStateFlags::CharacterCount;
         }
 
-        if invalid_state_issues.is_empty() {
+        if invalid_state_flags.is_empty() {
             self.submission_state = Some(SubmissionState::CanSubmit);
         } else {
             self.submission_state = Some(SubmissionState::CannotSubmit {
                 reason: CannotSubmitReason::InvalidState {
-                    issues: invalid_state_issues,
+                    flags: invalid_state_flags,
                 },
             });
         }
     }
 
     fn valid_email_address(&self) -> bool {
-        !self.in_invalid_state(InvalidStateIssue::EmailAddress)
+        !self.in_invalid_state(InvalidStateFlags::EmailAddress)
     }
 
     fn valid_character_count(&self) -> bool {
-        !self.in_invalid_state(InvalidStateIssue::CharacterCount)
+        !self.in_invalid_state(InvalidStateFlags::CharacterCount)
     }
 
-    fn in_invalid_state(&self, a: InvalidStateIssue) -> bool {
+    fn in_invalid_state(&self, flag: InvalidStateFlags) -> bool {
         match self.submission_state {
             Some(SubmissionState::CannotSubmit {
-                reason: CannotSubmitReason::InvalidState { ref issues },
-            }) => issues.contains(&a),
+                reason: CannotSubmitReason::InvalidState { ref flags },
+            }) => flags.contains(flag),
             _ => false,
         }
     }