diff --git a/Cargo.lock b/Cargo.lock index 11a0a879b4c5a..448b3401bb341 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -231,12 +231,6 @@ version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" -[[package]] -name = "anymap" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344" - [[package]] name = "anymap" version = "1.0.0-beta.2" @@ -9961,7 +9955,6 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" name = "vector" version = "0.35.0" dependencies = [ - "anymap 0.12.1", "apache-avro", "approx", "arc-swap", @@ -10497,7 +10490,7 @@ source = "git+https://github.com/vectordotdev/vrl?rev=37319dfca17dc5d7637b244551 dependencies = [ "aes", "ansi_term", - "anymap 1.0.0-beta.2", + "anymap", "arbitrary", "base16", "base64 0.21.5", diff --git a/Cargo.toml b/Cargo.toml index 34bdf236dca57..d0a9774ee9e5d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -233,7 +233,6 @@ sha2 = { version = "0.10.8", default-features = false, optional = true } greptimedb-client = { git = "https://github.com/GreptimeTeam/greptimedb-client-rust.git", rev = "bc32362adf0df17a41a95bae4221d6d8f1775656", optional = true } # External libs -anymap = { version = "0.12", default-features = false } arc-swap = { version = "1.6", default-features = false, optional = true } async-compression = { version = "0.4.5", default-features = false, features = ["tokio", "gzip", "zstd"], optional = true } apache-avro = { version = "0.16.0", default-features = false, optional = true } diff --git a/LICENSE-3rdparty.csv b/LICENSE-3rdparty.csv index a5a6ce58f89ba..9a26ccb5e1f9e 100644 --- a/LICENSE-3rdparty.csv +++ b/LICENSE-3rdparty.csv @@ -20,7 +20,6 @@ anstyle-query,https://github.com/rust-cli/anstyle,MIT OR Apache-2.0,The anstyle- anstyle-wincon,https://github.com/rust-cli/anstyle,MIT OR Apache-2.0,The anstyle-wincon Authors anyhow,https://github.com/dtolnay/anyhow,MIT OR Apache-2.0,David Tolnay anymap,https://github.com/chris-morgan/anymap,BlueOak-1.0.0 OR MIT OR Apache-2.0,Chris Morgan -anymap,https://github.com/chris-morgan/anymap,MIT OR Apache-2.0,Chris Morgan apache-avro,https://github.com/apache/avro,Apache-2.0,Apache Avro team arbitrary,https://github.com/rust-fuzz/arbitrary,MIT OR Apache-2.0,"The Rust-Fuzz Project Developers, Nick Fitzgerald , Manish Goregaokar , Simonas Kazlauskas , Brian L. Troutwine , Corey Farwell " arc-swap,https://github.com/vorner/arc-swap,MIT OR Apache-2.0,Michal 'vorner' Vaner diff --git a/src/extra_context.rs b/src/extra_context.rs index 69dd741dc63e8..23251c88ea510 100644 --- a/src/extra_context.rs +++ b/src/extra_context.rs @@ -1,51 +1,99 @@ //! ExtraContext is used for passing extra data to Vector's components when Vector is used as a library. use std::{ + any::{Any, TypeId}, + collections::HashMap, marker::{Send, Sync}, sync::Arc, }; -use anymap::{ - any::{Any, IntoBox}, - Map, -}; - /// Structure containing any extra data. /// The data is held in an [`Arc`] so is cheap to clone. -#[derive(Clone)] -pub struct ExtraContext(Arc>); - -impl Default for ExtraContext { - fn default() -> Self { - Self(Arc::new(Map::new())) - } -} +#[derive(Clone, Default)] +pub struct ExtraContext(Arc>>); impl ExtraContext { - /// Create a new `ExtraContext` with the provided [`anymap::Map`]. - pub fn new(context: Map) -> Self { + /// Create a new `ExtraContext` with the provided [`HashMap`]. + pub fn new(context: HashMap>) -> Self { Self(Arc::new(context)) } /// Create a new `ExtraContext` that contains the single passed in value. pub fn single_value(value: T) -> Self { - let mut map = Map::new(); - map.insert(value); + let mut map = HashMap::new(); + map.insert(value.type_id(), Box::new(value) as _); Self(Arc::new(map)) } + #[cfg(test)] + /// This is only available for tests due to panic implications of making an Arc + /// mutable when there may be multiple references to it. + fn insert(&mut self, value: T) { + Arc::get_mut(&mut self.0) + .expect("only insert into extra context when there is a single reference to it") + .insert(value.type_id(), Box::new(value)); + } + /// Get an object from the context. - pub fn get(&self) -> Option<&T> - where - T: IntoBox, - { - self.0.get() + pub fn get(&self) -> Option<&T> { + self.0 + .get(&TypeId::of::()) + .and_then(|t| t.downcast_ref()) } /// Get an object from the context, if it doesn't exist return the default. - pub fn get_or_default(&self) -> T + pub fn get_or_default(&self) -> T where - T: IntoBox + Clone + Default, + T: Clone + Default, { - self.0.get().cloned().unwrap_or_default() + self.get().cloned().unwrap_or_default() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[derive(Clone, Eq, PartialEq, Debug, Default)] + struct Peas { + beans: usize, + } + + #[derive(Clone, Eq, PartialEq, Debug, Default)] + struct Potatoes(usize); + + #[test] + fn get_fetches_item() { + let peas = Peas { beans: 42 }; + let potatoes = Potatoes(8); + + let mut context = ExtraContext::default(); + context.insert(peas); + context.insert(potatoes); + + assert_eq!(&Peas { beans: 42 }, context.get::().unwrap()); + assert_eq!(&Potatoes(8), context.get::().unwrap()); + } + + #[test] + fn get_or_default_fetches_item() { + let potatoes = Potatoes(8); + + let mut context = ExtraContext::default(); + context.insert(potatoes); + + assert_eq!(Potatoes(8), context.get_or_default::()); + assert_eq!(Peas::default(), context.get_or_default::()); + } + + #[test] + fn duplicate_types() { + let potatoes = Potatoes(8); + let potatoes99 = Potatoes(99); + + let mut context = ExtraContext::default(); + context.insert(potatoes); + context.insert(potatoes99); + + assert_eq!(&Potatoes(99), context.get::().unwrap()); } }