Emille C.
Emille C.

Reputation: 375

Javascript Regex into Rust regex

I have a Javascript regex for password validation:

// Validates password with
// — No white spaces
// — At least one upper case English letter, (?=.*?[A-Z])
// — At least one lower case English letter, (?=.*?[a-z])
// — At least one digit, (?=.*?[0-9])
// — Minimum eight in length .{8,} (with the anchors)

const passwordRegex = /^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9]).{6,10}$/;

I am trying to translate it into Rust regex using regex library; but it seems that it doesn't support lookahead: https://docs.rs/regex/latest/regex/

use regex::Regex;

pub fn validate_password(string: &str) -> bool {
  let regex_no_whitespaces = Regex::new(r"^\s*\S+\s*$").unwrap();
  let regex_password = Regex::new(r"^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9]).{6,10}$").unwrap();
  let password_valid = regex_password.is_match(&string);
  let password_has_no_whitespaces = regex_no_whitespaces.is_match(&string);
  let is_valid = password_valid && password_has_no_whitespaces;

  return is_valid;
}

What is the common way to validate a string with multiple conditions without a lookahead?

EDIT: it is possible to do it using Regex, here a version in the playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=c6f69f5018e38677af1624a7bfcd186c.

pub fn validate_password(string: &str) -> bool {
  let regex_no_whitespaces = Regex::new(r"^\s*\S+\s*$").unwrap();
  let no_whitespaces = regex_no_whitespaces.is_match(&string);
  let regex_one_uppercase = Regex::new(r"[a-z]{1,}").unwrap();
  let one_uppercase = regex_one_uppercase.is_match(&string);
  let regex_one_lowercase = Regex::new(r"[A-Z]{1,}").unwrap();
  let one_lowercase = regex_one_lowercase.is_match(&string);
  let regex_one_digit = Regex::new(r"[0-9]{1,}").unwrap();
  let one_digit = regex_one_digit.is_match(&string);
  let regex_length = Regex::new(r".{8,}").unwrap();
  let length = regex_length.is_match(&string);

  let is_valid = no_whitespaces && one_uppercase && one_lowercase && one_digit && length;

  return is_valid;
}

But the version provided by @sirdarius is way cleaner.

Upvotes: 1

Views: 1038

Answers (3)

Ashim Saha
Ashim Saha

Reputation: 493

Here I tried to create a performing alternative to the other solutions.

pub fn is_password_valid(password: &str) -> bool {
    const MIN_LENGTH: usize = 8; // Minimum password length
    const MAX_LENGTH: usize = 64; // Maximum password length
    
    let len = password.len();
    if len < MIN_LENGTH || len > MAX_LENGTH {
        return false;
    }

    let mut criteria = 0b0000;

    for &byte in password.as_bytes() {
        match byte {
            b'A'..=b'Z' => criteria |= 0b0001,
            b'a'..=b'z' => criteria |= 0b0010,
            b'0'..=b'9' => criteria |= 0b0100,
            b'!' | b'@' | b'#' | b'^' | b'&' | b'*' | b'_' | b'-' => {
                criteria |= 0b1000
            }
            _ => return false, // Invalid character
        }
    }
    criteria == 0b1111
}

Upvotes: 0

Varun V
Varun V

Reputation: 11

fn is_password_valid(password: &str) -> bool {
    let mut has_uppercase = false;
    let mut has_lowercase = false;
    let mut has_digit = false;
    let mut has_whitespace = false;
    for c in password.chars() {
        if c.is_uppercase() {
            has_uppercase = true;
        } else if c.is_lowercase() {
            has_lowercase = true;
        } else if c.is_digit(10) {
            has_digit = true;
        } else if c.is_whitespace() {
            has_whitespace = true;
        }
    }
    has_uppercase && has_lowercase && has_digit && !has_whitespace
}

Upvotes: 0

SirDarius
SirDarius

Reputation: 42959

Here is a solution that does not use regular expressions.

fn is_password_valid(s: &str) -> bool {
    let mut has_whitespace = false;
    let mut has_upper = false;
    let mut has_lower = false;
    let mut has_digit = false;

    for c in s.chars() {
        has_whitespace |= c.is_whitespace();
        has_lower |= c.is_lowercase();
        has_upper |= c.is_uppercase();
        has_digit |= c.is_digit(10);
    }

    !has_whitespace && has_upper && has_lower && has_digit && s.len() >= 8
}

Playground link

Upvotes: 3

Related Questions