flams_utils/
id_counters.rs

1use std::{borrow::Cow, collections::hash_map::Entry, fmt::Display};
2
3use crate::prelude::HMap;
4
5#[derive(Clone, Debug, PartialEq, Eq, Hash)]
6pub enum CowStr {
7    Borrowed(&'static str),
8    Owned(Box<str>),
9}
10impl std::ops::Deref for CowStr {
11    type Target = str;
12    #[inline]
13    fn deref(&self) -> &str {
14        match self {
15            Self::Borrowed(s) => s,
16            Self::Owned(s) => s,
17        }
18    }
19}
20impl AsRef<str> for CowStr {
21    #[inline]
22    fn as_ref(&self) -> &str {
23        &**self
24    }
25}
26
27impl From<&'static str> for CowStr {
28    #[inline]
29    fn from(s: &'static str) -> Self {
30        Self::Borrowed(s)
31    }
32}
33impl From<String> for CowStr {
34    #[inline]
35    fn from(s: String) -> Self {
36        Self::Owned(s.into_boxed_str())
37    }
38}
39impl From<Box<str>> for CowStr {
40    #[inline]
41    fn from(s: Box<str>) -> Self {
42        Self::Owned(s)
43    }
44}
45impl From<Cow<'static, str>> for CowStr {
46    #[inline]
47    fn from(s: Cow<'static, str>) -> Self {
48        match s {
49            Cow::Borrowed(s) => Self::Borrowed(s),
50            Cow::Owned(s) => Self::Owned(s.into_boxed_str()),
51        }
52    }
53}
54
55impl Display for CowStr {
56    #[inline]
57    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
58        self.as_ref().fmt(f)
59    }
60}
61
62#[derive(Clone, Debug)]
63pub struct IdCounter {
64    inner: HMap<CowStr, u32>,
65}
66impl Default for IdCounter {
67    fn default() -> Self {
68        let mut inner = HMap::default();
69        inner.insert("EXTSTRUCT".into(), 0);
70        Self { inner }
71    }
72}
73impl IdCounter {
74    pub fn new_id(&mut self, prefix: impl Into<CowStr>) -> Box<str> {
75        let prefix = prefix.into();
76        let r = match self.inner.entry(prefix) {
77            Entry::Occupied(mut e) => {
78                *e.get_mut() += 1;
79                format!("{}_{}", e.key(), e.get())
80            }
81            Entry::Vacant(e) => {
82                let r = e.key().to_string();
83                e.insert(0);
84                r
85            }
86        };
87        r.into_boxed_str()
88    }
89}