rhai/src/types/interner.rs

96 lines
3.2 KiB
Rust
Raw Normal View History

2021-12-27 14:56:50 +01:00
use crate::{Identifier, ImmutableString};
#[cfg(feature = "no_std")]
use std::prelude::v1::*;
2022-01-05 05:52:56 +01:00
use std::{collections::BTreeMap, ops::AddAssign};
2021-12-27 14:56:50 +01:00
/// _(internals)_ A factory of identifiers from text strings.
/// Exported under the `internals` feature only.
///
2022-01-04 08:22:48 +01:00
/// Normal identifiers, property getters and setters are interned separately.
2021-12-27 14:56:50 +01:00
#[derive(Debug, Clone, Default, Hash)]
pub struct StringsInterner {
2022-01-04 08:22:48 +01:00
/// Normal strings.
2022-01-05 05:52:56 +01:00
strings: BTreeMap<Identifier, ImmutableString>,
2021-12-27 14:56:50 +01:00
/// Property getters.
2021-12-27 15:28:11 +01:00
#[cfg(not(feature = "no_object"))]
2022-01-05 05:52:56 +01:00
getters: BTreeMap<Identifier, ImmutableString>,
2021-12-27 14:56:50 +01:00
/// Property setters.
2021-12-27 15:28:11 +01:00
#[cfg(not(feature = "no_object"))]
2022-01-05 05:52:56 +01:00
setters: BTreeMap<Identifier, ImmutableString>,
2021-12-27 14:56:50 +01:00
}
impl StringsInterner {
2021-12-31 16:01:34 +01:00
/// Create a new [`StringsInterner`].
2021-12-27 14:56:50 +01:00
#[inline]
#[must_use]
pub fn new() -> Self {
Self {
2022-01-05 05:52:56 +01:00
strings: BTreeMap::new(),
2021-12-27 15:28:11 +01:00
#[cfg(not(feature = "no_object"))]
2022-01-05 05:52:56 +01:00
getters: BTreeMap::new(),
2021-12-27 15:28:11 +01:00
#[cfg(not(feature = "no_object"))]
2022-01-05 05:52:56 +01:00
setters: BTreeMap::new(),
2021-12-27 14:56:50 +01:00
}
}
/// Get an identifier from a text string and prefix, adding it to the interner if necessary.
///
2022-01-04 08:22:48 +01:00
/// # Prefix
///
/// Currently recognized prefixes are:
///
/// * `""` - None (normal string)
/// * `"get$"` - Property getter, not available under `no_object`
/// * `"set$"` - Property setter, not available under `no_object`
///
2021-12-27 14:56:50 +01:00
/// # Panics
///
/// Panics if the prefix is not recognized.
#[inline]
#[must_use]
2022-01-04 08:22:48 +01:00
pub fn get(&mut self, prefix: impl AsRef<str>, text: impl AsRef<str>) -> ImmutableString {
let (dict, mapper): (_, fn(&str) -> Identifier) = match prefix.as_ref() {
"" => (&mut self.strings, |s| s.into()),
2021-12-27 15:28:11 +01:00
2022-01-04 08:22:48 +01:00
#[cfg(not(feature = "no_object"))]
2022-01-05 05:52:56 +01:00
crate::engine::FN_GET => (&mut self.getters, crate::engine::make_getter),
2022-01-04 08:22:48 +01:00
#[cfg(not(feature = "no_object"))]
2022-01-05 05:52:56 +01:00
crate::engine::FN_SET => (&mut self.setters, crate::engine::make_setter),
2021-12-27 15:28:11 +01:00
2022-01-04 08:22:48 +01:00
_ => unreachable!("unsupported prefix {}", prefix.as_ref()),
};
if dict.contains_key(text.as_ref()) {
2022-01-06 04:07:52 +01:00
dict.get(text.as_ref()).unwrap().clone()
2022-01-04 08:22:48 +01:00
} else {
let value: ImmutableString = mapper(text.as_ref()).into();
dict.insert(text.as_ref().into(), value.clone());
value
2021-12-27 14:56:50 +01:00
}
}
}
2021-12-29 07:26:54 +01:00
impl AddAssign<Self> for StringsInterner {
2021-12-27 14:56:50 +01:00
#[inline(always)]
fn add_assign(&mut self, rhs: Self) {
2022-01-04 08:22:48 +01:00
self.strings.extend(rhs.strings.into_iter());
2021-12-27 15:28:11 +01:00
#[cfg(not(feature = "no_object"))]
2022-01-04 08:22:48 +01:00
self.getters.extend(rhs.getters.into_iter());
#[cfg(not(feature = "no_object"))]
self.setters.extend(rhs.setters.into_iter());
2021-12-27 14:56:50 +01:00
}
}
2021-12-29 07:26:54 +01:00
impl AddAssign<&Self> for StringsInterner {
#[inline(always)]
fn add_assign(&mut self, rhs: &Self) {
2022-01-04 08:22:48 +01:00
self.strings
.extend(rhs.strings.iter().map(|(k, v)| (k.clone(), v.clone())));
2021-12-29 07:26:54 +01:00
#[cfg(not(feature = "no_object"))]
2022-01-04 08:22:48 +01:00
self.getters
.extend(rhs.getters.iter().map(|(k, v)| (k.clone(), v.clone())));
#[cfg(not(feature = "no_object"))]
self.setters
.extend(rhs.setters.iter().map(|(k, v)| (k.clone(), v.clone())));
2021-12-29 07:26:54 +01:00
}
}