broomdog ๐Ÿงน๐Ÿ•

broomdog is a Rust library providing a map of type-erased values with indefinite loanership semantics.

what is a type map?

broomdog's type map is a map of std::any::TypeId keys to type-erased values. There may be at most one value for each key, which means the map stores singleton values of different types.

why another type map library?

broomdog provides the usual map-like API, and then some. Notably broomdog provides "indefinite loanership".

wtf is indefinite loanership?

It's a wordsmush that roughly means you can get a loaned value from the map without a lifetime.

wtf is a loaned value?

A loaned value is a smart pointer to a value that you can deref or deref_mut.

You may only have one exclusive (write) loan of any one value at a time, but you may have as many non-exclusive (read) loans of the same value as you like. You may also have multiple exclusive loans of different types at the same time.

After an exclusive loan is dropped you may make another exclusive loan of the same type, or multiple non-exclusive loans of that type.

This allows you to make multiple loans of different types at the same time, without map borrow conflicts - so long as you don't try to share an exclusive loan of the same type at the same time.

Furthermore, broomdog has nice descriptive errors with the names of the types (more even, if compiled with debug_assertions).

uses

Type erased maps have many uses, but broomdog was to facilitate the following:

It works particularly well with dagga, which is a DAG scheduler. Together it's possible to define and run an extensible system of functions that share mutable resources, some of which may run in parallel.

why (the heck) did you name it broomdog

example

```rust use broomdog::{TypeMap, TypeKey};

let mut map = TypeMap::default(); assert!(map.insertvalue(0usize).unwrap().isnone()); assert!(map.insertvalue(0.0f32).unwrap().isnone()); assert!(map.insertvalue("hello").unwrap().isnone());

{ let numusize = map.getvaluemut::().unwrap().unwrap(); *numusize += 666; } asserteq!(666, *map.getvalue::().unwrap().unwrap()); asserteq!("hello", *map.getvalue::<&str>().unwrap().unwrap());

{ let loan = map.loan(TypeKey::new::()).unwrap().unwrap(); asserteq!(666, *loan.downcastref::().unwrap()); let loan2 = map.loan(TypeKey::new::()).unwrap().unwrap(); asserteq!(666, *loan2.downcastref::().unwrap());

let mut loan_mut = map.loan_mut(TypeKey::new::<&str>()).unwrap().unwrap();
let word = loan_mut.downcast_mut::<&str>().unwrap();
assert_eq!("hello", *word);
*word = "goodbye";

}

map.unify().unwrap(); ```