fn try_from()

in components/support/firefox-versioning/src/version.rs [235:301]


    fn try_from(value: &'_ str) -> Result<Self, Self::Error> {
        if !value.is_ascii() {
            return Err(VersionParsingError::ParseError(format!(
                "version string {} contains non-ascii characters",
                value
            )));
        }
        if value.is_empty() {
            return Ok(Default::default());
        }

        let mut res: VersionPart = Default::default();
        // if the string value is the special "*",
        // then we set the num_a to be the highest possible value
        // handle that case before we start
        if value == "*" {
            res.num_a = i32::MAX;
            return Ok(res);
        }
        // Step 1: Parse the num_a, it's guaranteed to be
        // a base-10 number, if it exists
        let mut curr_idx = 0;
        while curr_idx < value.len() && char_at(value, curr_idx)?.is_numeric() {
            parse_version_num(
                char_at(value, curr_idx)?.to_digit(10).unwrap() as i32,
                &mut res.num_a,
            )?;
            curr_idx += 1;
        }
        if curr_idx >= value.len() {
            return Ok(res);
        }
        // Step 2: Parse the str_b. If str_b starts with a "+"
        // then we increment num_a, and set str_b to be "pre"
        let first_char = char_at(value, curr_idx)?;
        if first_char == '+' {
            res.num_a += 1;
            res.str_b = "pre".into();
            return Ok(res);
        }
        // otherwise, we parse until we either finish the string
        // or we find a numeric number, indicating the start of num_c
        while curr_idx < value.len() && !is_num_c(char_at(value, curr_idx)?) {
            res.str_b.push(char_at(value, curr_idx)?);
            curr_idx += 1;
        }

        if curr_idx >= value.len() {
            return Ok(res);
        }

        // Step 3: Parse the num_c, similar to how we parsed num_a
        while curr_idx < value.len() && char_at(value, curr_idx)?.is_numeric() {
            parse_version_num(
                char_at(value, curr_idx)?.to_digit(10).unwrap() as i32,
                &mut res.num_c,
            )?;
            curr_idx += 1;
        }
        if curr_idx >= value.len() {
            return Ok(res);
        }

        // Step 4: Assign all the remaining to extra_d
        res.extra_d = value[curr_idx..].into();
        Ok(res)
    }