Skip to content

Instantly share code, notes, and snippets.

@blueforesticarus
Last active November 18, 2022 19:10
Show Gist options
  • Save blueforesticarus/789a60c8fa1e7d5db298b1976aa7cad5 to your computer and use it in GitHub Desktop.
Save blueforesticarus/789a60c8fa1e7d5db298b1976aa7cad5 to your computer and use it in GitHub Desktop.
segfault's monster
/*
Sick of the type system catching your mistakes?
Wish you could just yeet anything into a hashmap with arbitrary key and value types like in python?
Wish that unlike python, you could have the same key map to differnt entries for each type of data?
Well, this is for you.
motivation: I need runtime configured models (blackbox computation) which can depend on each other.
idea: Create a cache of all the state the program knows about. Models access state by key and type.
*/
use dashmap::DashMap;
use strum::EnumDiscriminants;
// Example data and id types
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
struct ThingA(u32, u32);
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
struct ThingB(u32);
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
struct ThingC(String);
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
struct IdA(String);
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
struct IdB(u64, bool);
// enums for stuff
#[derive(
Debug, Clone, PartialEq, Eq, Hash, derive_more::From, derive_more::TryInto, EnumDiscriminants,
)]
#[strum_discriminants(derive(Hash))]
enum ValueEnum {
ThingA(ThingA),
ThingB(ThingB),
ThingC(ThingC),
}
#[derive(
Debug, Clone, PartialEq, Eq, Hash, derive_more::From, derive_more::TryInto, EnumDiscriminants,
)]
enum IdEnum {
IdA(IdA),
IdB(IdB),
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct ThingId {
id: IdEnum,
typ: ValueEnumDiscriminants,
}
type BigMap = DashMap<ThingId, ValueEnum>;
fn get<T, I>(map: &BigMap, id: &I) -> Option<T>
where
T: Into<ValueEnum> + Default,
T: TryFrom<ValueEnum>,
I: Clone + Into<IdEnum>,
{
//XXX Unfortionatly this is the only easy way to get the discriminant
let d = ValueEnumDiscriminants::from(T::default().into());
let key = ThingId {
id: id.clone().into(),
typ: d,
};
let v = map.get(&key)?.value().clone();
Some(v.try_into().unwrap_or_else(|_| unreachable!()))
}
fn insert(map: &BigMap, id: impl Into<IdEnum>, value: impl Into<ValueEnum>) {
let value = value.into();
let key = ThingId {
id: id.into(),
typ: ValueEnumDiscriminants::from(&value),
};
map.insert(key, value);
}
fn main() {
let map = BigMap::new();
let keya = IdA("test".to_string());
let value = ThingA::default();
insert(&map, keya.clone(), value);
let keyb = IdB(100, false);
let value = ThingB::default();
insert(&map, keyb.clone(), value);
let value = ThingC::default();
insert(&map, keyb.clone(), value);
let thinga: ThingA = get(&map, &keya).unwrap();
let thingb: ThingB = get(&map, &keyb).unwrap();
let thingc: ThingC = get(&map, &keyb).unwrap();
dbg!(thinga, thingb, thingc);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment