Simple string validation

Without using regexp, I want to do simple string validation. Specifically I want to validate that a string begins with one class of "character" (yes, I know) and is followed by zero or more "characters" (yes, I know) of a different class.

I've primarily been working in C for the past decades, so I'm trying to learn to use some of the more functional-like constructs:

fn validate_heading(heading: &str) -> Result<(), Error> {
  let ch = heading.chars().next();
  if let Some(ch) = ch {
    if !is_heading_leading_char(ch) {
      return Err(Error::BadFormat("Invalid leading character".to_string()));
    }
  } else {
    return Err(Error::BadFormat("Empty or broken string".to_string()));
  }
  if let Some(_idx) = heading.chars().nth(1).position(|c| !is_heading_char(c)) {
    return Err(Error::BadFormat("Invalid heading".to_string()));
  }

  Ok(())
}

nth() returns an Optional, so position() fails.

What's an idiomatic way to do this?

Instead of nth, you want skip. Or you could create a single .chars() iterator, check its first item, and then use the same iterator to check the remaining items. Here's how I might write this function:

fn validate_heading(heading: &str) -> Result<(), Error> {
    let mut chars = heading.chars();
    match chars.next() {
        Some(c) => if !is_heading_leading_char(c) {
            return Err(Error::BadFormat("Invalid leading character".to_string()));
        }
        None => {
            return Err(Error::BadFormat("Empty or broken string".to_string()))
        }
    }
    if chars.any(|c| !is_heading_char(c)) {
        return Err(Error::BadFormat("Invalid heading".to_string()));
    }
    Ok(())
}
3 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.