Repository: nushell/nushell
File: crates/nu-protocol/src/value/record.rs (Rust)

Code before:
    fn keys_eq(lhs: &str, rhs: &str) -> bool {
        match SENSITIVE {
            true => lhs == rhs,
            false => lhs.eq_ignore_case(rhs),
        }
    }

    pub fn index_of(&self, col: impl AsRef<str>) -> Option<usize> {
        let col = col.as_ref();
        self.0.columns().rposition(|k| Self::keys_eq(k, col))
    }

    pub fn contains(&self, col: impl AsRef<str>) -> bool {
        self.index_of(col.as_ref()).is_some()
    }

    pub fn get(&self, col: impl AsRef<str>) -> Option<&Value> {
        let index = self.index_of(col.as_ref())?;
        Some(self.0.get_index(index)?.1)
    }

    pub fn get_mut(&mut self, col: impl AsRef<str>) -> Option<&mut Value> {
        let index = self.index_of(col.as_ref())?;
        Some(self.0.get_index_mut(index)?.1)
    }

    /// Remove single value by key and return it
    pub fn remove(&mut self, col: impl AsRef<str>) -> Option<Value> {
        let index = self.index_of(col.as_ref())?;
        Some(self.0.remove_index(index))
    }

    /// Insert into the record, replacing preexisting value if found.
    ///
    /// Returns `Some(previous_value)` if found. Else `None`
    pub fn insert<K>(&mut self, col: K, val: Value) -> Option<Value>
    where
        K: AsRef<str> + Into<String>,
    {
        if let Some(curr_val) = self.get_mut(col.as_ref()) {
            Some(std::mem::replace(curr_val, val))
        } else {
            self.0.push(col, val);
            None
        }
    }
}

/// Extension trait for [`Record`]. Enables separate implementations for `&Record` and `&mut Record`
pub trait RecordExt {
    type Ref<const S: bool>;

Review comment (suggestion):
This functionality is really an upsert vs insert. I'm not sure it matters for the api but I was confused when I read it. I see below that this terminology was already used before and you're just tweaking things.

Code after:
    pub fn index_of(&self, col: impl AsRef<str>) -> Option<usize> {
        let col = col.as_ref();
        self.0.columns().rposition(|k| Sensitivity::eq(k, col))
    }

    pub fn contains(&self, col: impl AsRef<str>) -> bool {
        self.index_of(col.as_ref()).is_some()
    }

    pub fn get(&self, col: impl AsRef<str>) -> Option<&Value> {
        let index = self.index_of(col.as_ref())?;
        Some(self.0.get_index(index)?.1)
    }

    pub fn get_mut(&mut self, col: impl AsRef<str>) -> Option<&mut Value> {
        let index = self.index_of(col.as_ref())?;
        Some(self.0.get_index_mut(index)?.1)
    }

    /// Remove single value by key and return it
    pub fn remove(&mut self, col: impl AsRef<str>) -> Option<Value> {
        let index = self.index_of(col.as_ref())?;
        Some(self.0.remove_index(index))
    }

    /// Insert into the record, replacing preexisting value if found.
    ///
    /// Returns `Some(previous_value)` if found. Else `None`
    pub fn insert<K>(&mut self, col: K, val: Value) -> Option<Value>
    where
        K: AsRef<str> + Into<String>,
    {
        if let Some(curr_val) = self.get_mut(col.as_ref()) {
            Some(std::mem::replace(curr_val, val))
        } else {
            self.0.push(col, val);
            None
        }
    }
}

impl<'a> WrapCased for &'a Record {
    type Wrapper<S: CaseSensitivity> = &'a CasedRecord<S>;

    #[inline]
    fn case_sensitive(self) -> Self::Wrapper<CaseSensitive> {
        CasedRecord::<CaseSensitive>::from_record(self)
    }

    #[inline]
    fn case_insensitive(self) -> Self::Wrapper<CaseInsensitive> {