immigrant_schema/
uid.rs

1use std::{cell::Cell, collections::HashMap};
2
3use crate::{ids::DbIdent, HasDefaultDbName};
4
5#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)]
6pub struct Uid(usize);
7
8/// OwnUid - Uid attached to annotation/something else
9/// It doesn't make sense to clone Annotation Uid, because if we do so, then
10/// changing name of annotation on table column also changes annotation name in scalar/other copies of this annotation
11/// Because of that, cloning of OwnUid should also clone entry of RenameMap.
12#[derive(PartialEq, Eq, Hash, Debug)]
13#[repr(transparent)]
14pub struct OwnUid(Uid);
15impl HasUid for OwnUid {
16	fn uid(&self) -> Uid {
17		self.0
18	}
19}
20
21thread_local! {
22	static LAST_UID: Cell<usize> = Default::default();
23}
24
25pub(crate) fn next_uid() -> OwnUid {
26	OwnUid(LAST_UID.with(|u| {
27		let v = u.get();
28		u.set(v.checked_add(1).expect("overflow"));
29		Uid(v)
30	}))
31}
32
33#[derive(Default, Clone)]
34pub struct RenameMap(HashMap<Uid, String>);
35impl RenameMap {
36	pub fn new() -> Self {
37		Self::default()
38	}
39	pub fn merge(&mut self, other: RenameMap) {
40		for (k, v) in other.0 {
41			assert!(
42				self.0.insert(k, v).is_none(),
43				"cannot merge RenameMap with conflicting entries"
44			)
45		}
46	}
47}
48
49pub trait HasUid {
50	fn uid(&self) -> Uid;
51}
52impl<T> HasUid for &T
53where
54	T: HasUid,
55{
56	fn uid(&self) -> Uid {
57		(*self).uid()
58	}
59}
60
61pub trait RenameExt {
62	type Kind;
63	fn db(&self, rn: &RenameMap) -> DbIdent<Self::Kind> {
64		self.try_db(rn).expect("name was not assigned")
65	}
66	fn try_db(&self, rn: &RenameMap) -> Option<DbIdent<Self::Kind>>;
67	fn set_db(&self, rn: &mut RenameMap, name: DbIdent<Self::Kind>);
68	fn db_assigned(&self, rn: &RenameMap) -> bool;
69}
70impl<T: HasDefaultDbName + HasUid> RenameExt for T {
71	type Kind = T::Kind;
72	fn try_db(&self, rn: &RenameMap) -> Option<DbIdent<Self::Kind>> {
73		if let Some(v) = rn.0.get(&self.uid()) {
74			Some(DbIdent::new(v.as_str()))
75		} else {
76			self.default_db()
77		}
78	}
79	fn set_db(&self, rn: &mut RenameMap, name: DbIdent<Self::Kind>) {
80		rn.0.insert(self.uid(), name.raw().to_string());
81	}
82	fn db_assigned(&self, rn: &RenameMap) -> bool {
83		rn.0.contains_key(&self.uid()) || self.default_db().is_some()
84	}
85}