cobia/
cape_string_map.rs

1use crate::{CapeStringHashKey,C,CapeStringImpl,CapeStringConstProvider};
2
3/// Class to store a platform dependent string encoding for use in case
4/// insensitive hash maps or for use of case insensitive comparisons.
5///
6/// For COBIA, strings go over the pipeline
7///  as null terminated. For Windows, COBIA requires UTF-16 encoding.
8///
9/// The [`CapeStringHashKey`] implementation uses a `Vec<u16>` to store,
10/// owned string data, or allows reference to data provided by any 
11/// class that implements CapeStringConstProvider, so that a copy of 
12/// the data is not needed for hash lookups.
13///
14/// This construct however requires that the hash keys are given a
15/// lifetime; the hash keys that are stored in the map are owned by the map
16/// and are given a dummy life time of 'static. Hash keys that are borrowed
17/// from a CapeStringConstProvider are given the lifetime of the provider.
18/// This implies that the life time checker for any mutable references
19/// to the hash map assumes that keys past to such references are of 
20/// life time 'static. Hence, mutable members of the hash map cannot
21/// take a borrowed key, but must use an owned key; in particular we cannot
22/// remove a key from the map using a borrowed key, nor can we return
23/// mutable references to the values in the map based on borrowed keys.
24/// Some traits, like Index, do not allow for such life time constraints
25/// and are not implemented. Use fn get() instead. Other than that, 
26/// the CapeOpenMap generally provides the same interface as the
27/// standard HashMap, on which it is based.
28///
29/// A common use case in CAPE-OPEN is to make hash maps of
30/// strings for case-insentive lookups: CapeOpenMap` uses the 
31/// more performant hasher in the FxHasmap class.
32///
33/// As the constructors are not const, a construct like for example
34/// LazyLock can be used to make static instances of this class, 
35/// or any class that contains this class.
36/// 
37/// # Examples
38///
39/// ```
40/// use cobia::*;
41/// use cobia::prelude::*;
42/// let mut map=cobia::CapeOpenMap::new();
43/// map.insert(cobia::CapeStringHashKey::from_string("idealGasEnthalpy"),1);
44/// map.insert("idealGasEntropy".into(),2);
45///
46/// assert_eq!(map.get(&cobia::CapeStringConstNoCase::from_string("IDEALGASENTHALPY")),Some(&1));
47///
48/// assert_eq!(map.get(&cobia::CapeStringImpl::from_string("IDEALGASENTROPY")),Some(&2));
49///
50/// let s2=cobia::CapeStringImpl::from_string("IDEALGASENTHALPY");
51/// fn test_string_in(map:&cobia::CapeOpenMap<i32>,s: &cobia::CapeStringIn) {
52///     assert_eq!(map.get(s),Some(&1));
53/// }
54/// test_string_in(&map,&CapeStringInFromProvider::from(&s2).as_cape_string_in());
55///
56/// assert_eq!(map.get(&cobia::CapeStringImpl::from_string("CriticalTemperature")),None);
57/// ```
58
59pub struct CapeOpenMap<V> (std::collections::HashMap<CapeStringHashKey<'static>,V,fxhash::FxBuildHasher>);
60
61impl<V> CapeOpenMap<V> {
62
63	pub fn new() -> Self {
64		Self(std::collections::HashMap::with_hasher(fxhash::FxBuildHasher::default()))
65	}
66
67	pub fn with_capacity(capacity: usize) -> Self {
68		Self(std::collections::HashMap::with_capacity_and_hasher(capacity,fxhash::FxBuildHasher::default()))
69	}
70
71	pub fn capacity(&self) -> usize {
72		self.0.capacity()
73	}
74
75	pub fn keys(&self) -> std::collections::hash_map::Keys<'_, CapeStringHashKey<'static>, V> {
76		self.0.keys()
77	}
78
79	pub fn into_keys(self) -> std::collections::hash_map::IntoKeys<CapeStringHashKey<'static>, V> {
80		self.0.into_keys()
81	}
82
83	pub fn values(&self) -> std::collections::hash_map::Values<'_, CapeStringHashKey<'static>, V> {
84		self.0.values()
85	}
86
87	pub fn values_mut(&mut self) -> std::collections::hash_map::ValuesMut<'_, CapeStringHashKey<'static>, V> {
88		self.0.values_mut()
89	}
90
91	pub fn into_values(self) -> std::collections::hash_map::IntoValues<CapeStringHashKey<'static>, V> {
92		self.0.into_values()
93	}
94
95	pub fn iter(&self) -> std::collections::hash_map::Iter<'_, CapeStringHashKey<'static>, V> {
96		self.0.iter()
97	}
98
99	pub fn iter_mut(&mut self) -> std::collections::hash_map::IterMut<'_, CapeStringHashKey<'static>, V> {
100		self.0.iter_mut()
101	}
102
103	pub fn len(&self) -> usize {
104		self.0.len()
105	}
106
107	pub fn is_empty(&self) -> bool {
108		self.0.is_empty()
109	}
110
111	pub fn drain(&mut self) -> std::collections::hash_map::Drain<'_, CapeStringHashKey<'static>, V> {
112		self.0.drain()
113	}
114
115	pub fn retain<F>(&mut self, f: F) 
116		where F: FnMut(&CapeStringHashKey<'static>, &mut V) -> bool {
117		self.0.retain(f)
118	}
119
120	pub fn clear(&mut self) {
121		self.0.clear()
122	}
123
124	pub fn reserve(&mut self, additional: usize) {
125		self.0.reserve(additional)
126	}
127
128	pub fn try_reserve(&mut self, additional: usize) -> Result<(), std::collections::TryReserveError> {
129		self.0.try_reserve(additional)
130	}
131
132	pub fn shrink_to_fit(&mut self) {
133		self.0.shrink_to_fit()
134	}
135
136	pub fn shrink_to(&mut self, min_capacity: usize) {
137		self.0.shrink_to(min_capacity)
138	}
139
140	pub fn entry(&mut self, key: CapeStringHashKey<'static>) -> std::collections::hash_map::Entry<'_, CapeStringHashKey<'static>, V> {
141		self.0.entry(key)
142	}
143
144	pub fn get<'a,'b,Q:CapeStringConstProvider>(&'a self, k: &'b Q) -> Option<&'a V> where 'b:'a {
145		let k = CapeStringHashKey::from_string_constant(k);
146		self.0.get(&k)
147	}
148
149	pub fn get_mut<'a>(&'a mut self, k: CapeStringHashKey<'static>) -> Option<&'a mut V> {
150		self.0.get_mut(&k)
151	}
152
153	pub fn contains_key<Q:CapeStringConstProvider>(&self, k: &Q) -> bool {
154		let k = CapeStringHashKey::from_string_constant(k);
155		self.0.contains_key(&k)
156	}
157
158	pub fn insert_from_cape_string_constant<T:CapeStringConstProvider>(&mut self, k: T, v: V) -> Option<V> {
159		let (ptr,size)=k.as_capechar_const_with_length();
160		self.0.insert(CapeStringHashKey::from_cape_char_const(ptr,size),v)
161	}
162
163	pub fn insert(&mut self, k: CapeStringHashKey<'static>, v: V) -> Option<V> {
164		self.0.insert(k,v)
165	}
166
167	pub fn remove<'a>(&'a mut self, k: CapeStringHashKey<'static>) -> Option<V> {
168		self.0.remove(&k)
169	}
170
171	pub fn remove_entry<'a>(&mut self, k: CapeStringHashKey<'static>) -> Option<(CapeStringHashKey<'static>, V)> {
172		self.0.remove_entry(&k)
173	}
174
175}
176
177impl<V:Clone> Clone for CapeOpenMap<V> {
178	fn clone(&self) -> Self {
179		Self(self.0.clone())
180	}
181}
182
183impl<V:std::fmt::Debug> std::fmt::Debug for CapeOpenMap<V> {
184	fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
185		self.0.fmt(f)
186	}
187}
188
189impl <V> std::default::Default for CapeOpenMap<V> {
190	fn default() -> Self {
191		Self::new()
192	}
193}
194
195impl <V:std::cmp::PartialEq> std::cmp::PartialEq for CapeOpenMap<V> {
196	fn eq(&self, other: &Self) -> bool {
197		self.0.eq(&other.0)
198	}
199}
200
201impl <V:std::cmp::Eq> std::cmp::Eq for CapeOpenMap<V> {}
202