Skip to content

Commit

Permalink
tech-debt: Context lib (prisma#4060)
Browse files Browse the repository at this point in the history
  • Loading branch information
Miguel Fernández authored Jul 3, 2023
1 parent 4913410 commit 27eb244
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions libs/context/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "context"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
87 changes: 87 additions & 0 deletions libs/context/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
use std::{
any::{Any, TypeId},
collections::HashMap,
sync::{Arc, Mutex},
};

#[derive(Debug, Default)]
pub struct Context {
store: HashMap<(String, TypeId), Box<dyn Any>>,
}

impl Context {
pub fn concurrent(self) -> Arc<Mutex<Context>> {
Arc::new(Mutex::new(self))
}

pub fn insert<T: Any>(&mut self, key: &str, value: T) {
self.store.insert((key.to_owned(), TypeId::of::<T>()), Box::new(value));
}

pub fn get<T: Any>(&self, key: &str) -> Option<&T> {
self.store
.get(&(key.to_owned(), TypeId::of::<T>()))
.map(|v| v.downcast_ref::<T>().unwrap())
}

pub fn get_mut<T: Any>(&mut self, key: &str) -> Option<&mut T> {
self.store
.get_mut(&(key.to_owned(), TypeId::of::<T>()))
.map(|v| v.downcast_mut::<T>().unwrap())
}

pub fn remove<T: Any>(&mut self, key: &str) -> Option<T> {
self.store
.remove(&(key.to_owned(), TypeId::of::<T>()))
.map(|v| *v.downcast::<T>().unwrap())
}
}

#[cfg(test)]
mod tests {
use super::Context;

#[test]
fn set_and_retrieve() {
let mut ctx: Context = Context::default();
ctx.insert("foo", 42 as u32);

let val: u32 = *ctx.get("foo").unwrap();
assert_eq!(val, 42 as u32)
}

#[test]
fn concurrent() {
let mut ctx: Context = Context::default();
ctx.insert("foo", 42 as u32);

assert_eq!(42 as u32, *ctx.get::<u32>("foo").unwrap());
assert_eq!(None, ctx.get::<u32>("bar"));

let safe_context = ctx.concurrent();
let mut ctx = safe_context.lock().unwrap();
ctx.insert("bar", 32 as u32);
assert_eq!(32 as u32, *ctx.get::<u32>("bar").unwrap());
assert_eq!(42 as u32, *ctx.get::<u32>("foo").unwrap());
}

#[test]
fn get_mut() {
let mut ctx: Context = Context::default();
ctx.insert("foo", 42 as u32);

let val: &mut u32 = ctx.get_mut("foo").unwrap();
*val = 32 as u32;
assert_eq!(32 as u32, *ctx.get::<u32>("foo").unwrap());
}

#[test]
fn remove() {
let mut ctx: Context = Context::default();
ctx.insert("foo", 42 as u32);

let val: u32 = ctx.remove("foo").unwrap();
assert_eq!(42 as u32, val);
assert_eq!(None, ctx.get::<u32>("foo"));
}
}

0 comments on commit 27eb244

Please sign in to comment.