Repository: starship/starship
File: src/modules/kubernetes.rs (Rust)

Code before:
                    .as_str()
                    .filter(|s| !s.is_empty())
                    .map(String::from),
                cluster: ctx_yaml["context"]["cluster"]
                    .as_str()
                    .filter(|s| !s.is_empty())
                    .map(String::from),
            });
        }
    }
}

fn get_aliased_name<'a>(
    pattern: Option<&'a str>,
    current_value: Option<&str>,
    alias: Option<&'a str>,
) -> Option<String> {
    let replacement = alias.or(current_value)?.to_string();
    let Some(pattern) = pattern else {
        // If user pattern not set, treat it as a match-all pattern
        return Some(replacement);
    };
    // If a pattern is set, but we have no value, there is no match
    let value = current_value?;
    if value == pattern {
        return Some(replacement);
    }
    let re = match regex::Regex::new(&format!("^{pattern}$")) {
        Ok(re) => re,
        Err(error) => {
            log::warn!(
                "Could not compile regular expression `{}`:\n{}",
                &format!("^{pattern}$"),
                error
            );
            return None;
        }
    };
    let replaced = re.replace(value, replacement.as_str());
    match replaced {
        Cow::Owned(replaced) => Some(replaced),
        // It didn't match...
        _ => None,
    }
}

#[derive(Debug)]
enum Document {
    Json(JsonValue),
    Yaml(Yaml),
}

Review comment (bug):
I'm not really happy that this ends up in two different codepath everywhere, just to get a bit more speed in an edge case (That's at least how I perceive this: how often do you have such big kube configs?) :-(

Personally, I would also have expected to get a common data structure from both parser.

If this is acceptable, then I would expect an explanation in the code why this solution was chosen, so one does not have to look up the original commits to understand why two different parsers are used, either here where the data structure is defined or in the parser function.

Code after:
    // If a pattern is set, but we have no value, there is no match
    let value = current_value?;
    if value == pattern {
        return Some(replacement);
    }
    let re = match regex::Regex::new(&format!("^{pattern}$")) {
        Ok(re) => re,
        Err(error) => {
            log::warn!(
                "Could not compile regular expression `{}`:\n{}",
                &format!("^{pattern}$"),
                error
            );
            return None;
        }
    };
    let replaced = re.replace(value, replacement.as_str());
    match replaced {
        Cow::Owned(replaced) => Some(replaced),
        // It didn't match...
        _ => None,
    }
}

#[derive(Debug)]
enum Document {
    Json(JsonValue),
    Yaml(Yaml),
}

trait DataValue {
    fn get(&self, key: &str) -> Option<&Self>;
    fn as_str(&self) -> Option<&str>;
    fn as_array(&self) -> Option<Vec<&Self>>;
}

impl DataValue for JsonValue {
    fn get(&self, key: &str) -> Option<&Self> {
        self.get(key)
    }

    fn as_str(&self) -> Option<&str> {
        self.as_str()
    }

    fn as_array(&self) -> Option<Vec<&Self>> {
        self.as_array().map(|arr| arr.iter().collect())
    }
}

impl DataValue for Yaml {