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#[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}