From fe39c9fd5cc635abb5579055abf20d3763716908 Mon Sep 17 00:00:00 2001 From: Eduardo Trujillo <ed@chromabits.com> Date: Sat, 22 Mar 2025 20:34:54 +0000 Subject: [PATCH] feat(rangemap): Add Index and IndexMut implementations --- Cargo.lock | 7 +++++ Cargo.toml | 5 +++- rustfmt.toml | 2 +- src/rangemap.rs | 76 ++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 87 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c29c7bc..b7e6f58 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "anyhow" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" + [[package]] name = "atty" version = "0.2.14" @@ -62,6 +68,7 @@ dependencies = [ name = "collective" version = "0.1.2" dependencies = [ + "anyhow", "clap", "figment", "lazy_static", diff --git a/Cargo.toml b/Cargo.toml index 5fcbcac..2096c29 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,4 +20,7 @@ default = ["config-yaml", "config-json", "thread", "xdg"] config-yaml = ["figment/yaml"] config-json = ["figment/json"] thread = ["lazy_static"] -xdg = ["dep:xdg"] \ No newline at end of file +xdg = ["dep:xdg"] + +[dev-dependencies] +anyhow = "1.0.97" diff --git a/rustfmt.toml b/rustfmt.toml index 08e342c..458b56f 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1 +1 @@ -format_code_in_doc_comments = true \ No newline at end of file +#format_code_in_doc_comments = true diff --git a/src/rangemap.rs b/src/rangemap.rs index 8c58716..2d54668 100644 --- a/src/rangemap.rs +++ b/src/rangemap.rs @@ -1,4 +1,7 @@ -use std::collections::BTreeMap; +use std::{ + collections::BTreeMap, + ops::{Index, IndexMut}, +}; use thiserror::Error; @@ -57,6 +60,32 @@ impl<RK: Ord + Copy, V> RangeMap<RK, V> { Ok(()) } + /// Looks up a value at the specified range + /// + /// If the range does not match, `None` is returned. + pub fn get(&self, key: (RK, RK)) -> Option<&V> { + if let Some(entry) = self.ranges.get(&key.0) { + if entry.0 == key.1 { + return Some(&entry.1); + } + } + + None + } + + /// Looks up a mutable value at the specified range + /// + /// If the range does not match, `None` is returned. + pub fn get_mut(&mut self, key: (RK, RK)) -> Option<&mut V> { + if let Some(entry) = self.ranges.get_mut(&key.0) { + if entry.0 == key.1 { + return Some(&mut entry.1); + } + } + + None + } + /// Looks up a value at the specified key /// /// If the key is within an existing range, the matching value is @@ -109,6 +138,36 @@ impl<RK: Ord + Copy, V> Default for RangeMap<RK, V> { } } +impl<RK: Ord + Copy, V> Index<(RK, RK)> for RangeMap<RK, V> { + type Output = V; + + fn index(&self, index: (RK, RK)) -> &Self::Output { + let entry = self.ranges.index(&index.0); + + if entry.0 != index.1 { + panic!("no entry found for key"); + } + + &entry.1 + } +} + +impl<RK: Ord + Copy, V> IndexMut<(RK, RK)> for RangeMap<RK, V> { + fn index_mut(&mut self, index: (RK, RK)) -> &mut Self::Output { + let entry = self.ranges.get_mut(&index.0); + + if let Some(entry) = entry { + if entry.0 != index.1 { + panic!("no entry found for key"); + } + + &mut entry.1 + } else { + panic!("no entry found for key") + } + } +} + #[cfg(test)] mod tests { use crate::rangemap::RangeMapError; @@ -187,4 +246,19 @@ mod tests { assert_eq!(rm.insert(41, 20, "A"), Err(RangeMapError::InvalidRange)); } + + #[test] + pub fn test_index_mut() -> anyhow::Result<()> { + let mut rm: RangeMap<i64, &str> = RangeMap::new(); + + rm.insert(1, 200, "hello")?; + + assert_eq!(rm[(1, 200)], "hello"); + + rm[(1, 200)] = "world"; + + assert_eq!(rm[(1, 200)], "world"); + + Ok(()) + } } -- GitLab