Skip to main content

valheim_mod_manager/
intern.rs

1use lasso::{Rodeo, Spur};
2
3/// Type alias for the string interner (lasso::Rodeo).
4///
5/// The interner stores unique strings and returns small integer keys that can be
6/// used to retrieve them later, reducing memory usage for repeated strings.
7pub type StringInterner = Rodeo;
8
9/// Type alias for interned string keys (lasso::Spur).
10///
11/// These keys are compact integer identifiers that reference strings stored in
12/// a StringInterner.
13pub type InternKey = Spur;
14
15/// Interns an optional string value.
16///
17/// # Parameters
18///
19/// * `interner` - The string interner to use
20/// * `s` - Optional string slice to intern
21///
22/// # Returns
23///
24/// An optional intern key, or None if the input was None.
25pub fn intern_option(interner: &mut StringInterner, s: Option<&str>) -> Option<InternKey> {
26  s.map(|val| interner.get_or_intern(val))
27}
28
29/// Resolves an optional interned key back to a String.
30///
31/// # Parameters
32///
33/// * `interner` - The string interner containing the interned strings
34/// * `key` - Optional intern key to resolve
35///
36/// # Returns
37///
38/// The resolved string, or None if the key was None.
39pub fn resolve_option(interner: &StringInterner, key: Option<InternKey>) -> Option<String> {
40  key.map(|k| interner.resolve(&k).to_string())
41}
42
43/// Interns a slice of strings into a vector of intern keys.
44///
45/// # Parameters
46///
47/// * `interner` - The string interner to use
48/// * `strings` - Slice of strings to intern
49///
50/// # Returns
51///
52/// A vector of intern keys corresponding to the input strings.
53pub fn intern_vec(interner: &mut StringInterner, strings: &[String]) -> Vec<InternKey> {
54  strings
55    .iter()
56    .map(|s| interner.get_or_intern(s.as_str()))
57    .collect()
58}
59
60/// Resolves a slice of intern keys back to a vector of Strings.
61///
62/// # Parameters
63///
64/// * `interner` - The string interner containing the interned strings
65/// * `keys` - Slice of intern keys to resolve
66///
67/// # Returns
68///
69/// A vector of resolved strings.
70pub fn resolve_vec(interner: &StringInterner, keys: &[InternKey]) -> Vec<String> {
71  keys
72    .iter()
73    .map(|k| interner.resolve(k).to_string())
74    .collect()
75}
76
77#[cfg(test)]
78mod tests {
79  use super::*;
80
81  #[test]
82  fn test_intern_option_some() {
83    let mut interner = StringInterner::default();
84    let key = intern_option(&mut interner, Some("test"));
85    assert!(key.is_some());
86    assert_eq!(resolve_option(&interner, key), Some("test".to_string()));
87  }
88
89  #[test]
90  fn test_intern_option_none() {
91    let mut interner = StringInterner::default();
92    let key = intern_option(&mut interner, None);
93    assert!(key.is_none());
94    assert_eq!(resolve_option(&interner, key), None);
95  }
96
97  #[test]
98  fn test_intern_vec() {
99    let mut interner = StringInterner::default();
100    let strings = vec!["a".to_string(), "b".to_string(), "c".to_string()];
101    let keys = intern_vec(&mut interner, &strings);
102    assert_eq!(keys.len(), 3);
103    assert_eq!(resolve_vec(&interner, &keys), strings);
104  }
105
106  #[test]
107  fn test_intern_vec_empty() {
108    let mut interner = StringInterner::default();
109    let strings: Vec<String> = vec![];
110    let keys = intern_vec(&mut interner, &strings);
111    assert!(keys.is_empty());
112    assert!(resolve_vec(&interner, &keys).is_empty());
113  }
114
115  #[test]
116  fn test_deduplication() {
117    let mut interner = StringInterner::default();
118    let key1 = interner.get_or_intern("duplicate");
119    let key2 = interner.get_or_intern("duplicate");
120    assert_eq!(key1, key2);
121    assert_eq!(interner.len(), 1);
122  }
123
124  #[test]
125  fn test_multiple_strings() {
126    let mut interner = StringInterner::default();
127    let key_a = interner.get_or_intern("a");
128    let key_b = interner.get_or_intern("b");
129    let key_a2 = interner.get_or_intern("a");
130
131    assert_eq!(key_a, key_a2);
132    assert_ne!(key_a, key_b);
133    assert_eq!(interner.len(), 2);
134  }
135}