typetoken 0.0.1

type tokens for branding via unique singletons
Documentation
/// example: prevent "wrong interner" bugs at compile time

use typetoken::{token, Token};

use std::marker::PhantomData;

//#[derive(PartialEq)]
struct Interner<T: Token> {
	// actual interning implementation doesn't matter
	v: Vec<String>,
	_token: PhantomData<T>,
}

struct InternedString<T: Token> {
	index: usize,
	_token: PhantomData<T>,
}

impl<T: Token> Interner<T> {
	fn new(_token: T) -> Self {
		Self{ v: vec![], _token: PhantomData::default() }
	}

	fn intern(&mut self, s: &str) -> InternedString<T> {
		let index;
		if let Some(idx) = self.v.iter().position(|x| x == s) {
			index = idx;
		} else {
			index = self.v.len();
			self.v.push(s.to_string());
		}
		InternedString{
			index,
			_token: PhantomData::default(),
		}	
	}

	fn resolve(&self, s: InternedString<T>) -> &str {
		&self.v[s.index]
	}
}

fn main() {
	token!(token1);
	let mut pool1 = Interner::new(token1);
	token!(token2);
	let mut pool2 = Interner::new(token2);
	let str1 = pool1.intern("abcd");
	let str2 = pool2.intern("1234");
	println!("{}", pool1.resolve(str1));
	println!("{}", pool2.resolve(str2));
	// wrong interner, compile error
	//println!("{}", pool2.resolve(str1));
}

// TODO: test that a recursive function cant construct the same token twice (invariant lifetimes should make this impossible)
//fn recursive(args: Option<(