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

Code before:
use serde_json::Value as JsonValue;
use yaml_rust2::{Yaml, YamlLoader};

use std::borrow::Cow;
use std::env;

use super::{Context, Module, ModuleConfig};

use crate::configs::kubernetes::KubernetesConfig;
use crate::formatter::StringFormatter;
use crate::utils;

#[derive(Default)]
struct KubeCtxComponents {
    user: Option<String>,
    namespace: Option<String>,
    cluster: Option<String>,
}

fn get_current_kube_context_name(document: &JsonOrYaml) -> Option<String> {
    match document {
        JsonOrYaml::Json(json) => json
            .get("current-context")
            .and_then(JsonValue::as_str)
            .filter(|s| !s.is_empty())
            .map(String::from),
        JsonOrYaml::Yaml(yaml) => yaml["current-context"]
            .as_str()
            .filter(|s| !s.is_empty())
            .map(String::from),
    }
}

fn get_kube_ctx_components(
    document: &JsonOrYaml,
    current_ctx_name: &str,
) -> Option<KubeCtxComponents> {
    match document {
        JsonOrYaml::Json(json) => json["contexts"]
            .as_array()?
            .iter()
            .find(|ctx| ctx["name"].as_str() == Some(current_ctx_name))
            .map(|ctx| KubeCtxComponents {
                user: ctx["context"]["user"]
                    .as_str()

Review comment (performance):
```suggestion
fn get_current_kube_context_name(document: &JsonOrYaml) -> Option<&str> {
```

This avoids cloning, and thanks to lifetime elision, there's no need to specify lifetime annotations (Rust infers that the return value borrows from `document`, as there's no other option). The function return value seems to be used in places where read-only access/`&str` suffices (except for one place, where you then need to clone).

So this change doesn't improve performance in the sense of avoiding clones (before: 1, after: 1), but it's neat to lean on the side of 'least capability necessary'. The effect would start kicking in if this function were called more than once.

Code after:
use serde_json::Value as JsonValue;
use yaml_rust2::{Yaml, YamlLoader};

use std::borrow::Cow;
use std::env;

use super::{Context, Module, ModuleConfig};

use crate::configs::kubernetes::KubernetesConfig;
use crate::formatter::StringFormatter;
use crate::utils;

#[derive(Default)]
struct KubeCtxComponents {
    user: Option<String>,
    namespace: Option<String>,
    cluster: Option<String>,
}

fn get_current_kube_context_name<T: DataValue>(document: &T) -> Option<&str> {
    document
        .get("current-context")
        .and_then(DataValue::as_str)
        .filter(|s| !s.is_empty())
}

fn get_kube_ctx_components<T: DataValue>(
    document: &T,
    current_ctx_name: &str,
) -> Option<KubeCtxComponents> {
    document
        .get("contexts")?
        .as_array()?
        .iter()
        .find(|ctx| ctx.get("name").and_then(DataValue::as_str) == Some(current_ctx_name))
        .map(|ctx| KubeCtxComponents {
            user: ctx
                .get("context")
                .and_then(|v| v.get("user"))
                .and_then(DataValue::as_str)
                .map(String::from),
            namespace: ctx
                .get("context")
                .and_then(|v| v.get("namespace"))
                .and_then(DataValue::as_str)