use std::borrow::Cow;
use std::rc::Rc;
use std::sync::Arc;
pub type CowStr<'a> = Cow<'a, str>;
pub type SharedString = Arc<str>;
pub trait StringOptimizations {
fn as_cow(&self) -> CowStr;
fn to_shared(&self) -> SharedString;
}
impl StringOptimizations for String {
fn as_cow(&self) -> CowStr {
Cow::Borrowed(self.as_str())
}
fn to_shared(&self) -> SharedString {
Arc::from(self.as_str())
}
}
impl StringOptimizations for &str {
fn as_cow(&self) -> CowStr {
Cow::Borrowed(self)
}
fn to_shared(&self) -> SharedString {
Arc::from(*self)
}
}
pub struct StringCache {
cache: std::collections::HashMap<String, Rc<str>>,
}
impl StringCache {
pub fn new() -> Self {
Self {
cache: std::collections::HashMap::new(),
}
}
pub fn get_or_insert(&mut self, s: &str) -> Rc<str> {
if let Some(cached) = self.cache.get(s) {
Rc::clone(cached)
} else {
let rc = Rc::from(s);
self.cache.insert(s.to_string(), Rc::clone(&rc));
rc
}
}
pub fn get(&self, s: &str) -> Option<Rc<str>> {
self.cache.get(s).map(Rc::clone)
}
}
impl Default for StringCache {
fn default() -> Self {
Self::new()
}
}
pub struct OptimizedParamMap<'a> {
data: std::collections::HashMap<&'a str, &'a str>,
owned: std::collections::HashMap<String, String>,
}
impl<'a> OptimizedParamMap<'a> {
pub fn new() -> Self {
Self {
data: std::collections::HashMap::new(),
owned: std::collections::HashMap::new(),
}
}
pub fn insert_borrowed(&mut self, key: &'a str, value: &'a str) {
self.data.insert(key, value);
}
pub fn insert_owned(&mut self, key: String, value: String) {
self.owned.insert(key, value);
}
pub fn get(&self, key: &str) -> Option<&str> {
self.data
.get(key)
.map(|&s| s)
.or_else(|| self.owned.get(key).map(String::as_str))
}
pub fn contains_key(&self, key: &str) -> bool {
self.data.contains_key(key) || self.owned.contains_key(key)
}
pub fn iter(&self) -> impl Iterator<Item = (&str, &str)> + '_ {
self.data
.iter()
.map(|(&k, &v)| (k, v))
.chain(self.owned.iter().map(|(k, v)| (k.as_str(), v.as_str())))
}
}
impl<'a> Default for OptimizedParamMap<'a> {
fn default() -> Self {
Self::new()
}
}
pub mod clone_reduction {
use super::*;
pub fn process_string<'a>(s: &'a str, needs_modification: bool) -> Cow<'a, str> {
if needs_modification {
let owned = s.to_string();
Cow::Owned(owned)
} else {
Cow::Borrowed(s)
}
}
pub fn share_element<T: Clone>(collection: &[T], index: usize) -> Option<Rc<T>> {
collection.get(index).map(|elem| Rc::new(elem.clone()))
}
pub fn intern_string(s: &str, cache: &mut StringCache) -> Rc<str> {
cache.get_or_insert(s)
}
}
pub struct OptimizedStringMap {
data: std::collections::HashMap<Arc<str>, Arc<str>>,
}
impl OptimizedStringMap {
pub fn new() -> Self {
Self {
data: std::collections::HashMap::new(),
}
}
pub fn insert(&mut self, key: impl Into<Arc<str>>, value: impl Into<Arc<str>>) {
self.data.insert(key.into(), value.into());
}
pub fn get(&self, key: &str) -> Option<&str> {
self.data.get(key).map(|arc| arc.as_ref())
}
pub fn contains_key(&self, key: &str) -> bool {
self.data.contains_key(key)
}
pub fn iter(&self) -> impl Iterator<Item = (&str, &str)> + '_ {
self.data.iter().map(|(k, v)| (k.as_ref(), v.as_ref()))
}
pub fn cheap_clone(&self) -> Self {
Self {
data: self.data.clone(),
}
}
}
impl Default for OptimizedStringMap {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_string_cache() {
let mut cache = StringCache::new();
let s1 = cache.get_or_insert("hello");
let s2 = cache.get_or_insert("hello");
assert!(Rc::ptr_eq(&s1, &s2));
}
#[test]
fn test_optimized_param_map() {
let mut map = OptimizedParamMap::new();
map.insert_borrowed("key1", "value1");
map.insert_owned("key2".to_string(), "value2".to_string());
assert_eq!(map.get("key1"), Some("value1"));
assert_eq!(map.get("key2"), Some("value2"));
assert!(map.contains_key("key1"));
assert!(map.contains_key("key2"));
}
#[test]
fn test_cow_usage() {
let original = "hello";
let borrowed = clone_reduction::process_string(original, false);
assert!(matches!(borrowed, Cow::Borrowed(_)));
let owned = clone_reduction::process_string(original, true);
assert!(matches!(owned, Cow::Owned(_)));
}
#[test]
fn test_optimized_string_map() {
let mut map = OptimizedStringMap::new();
map.insert("key1", "value1");
map.insert("key2", "value2");
assert_eq!(map.get("key1"), Some("value1"));
assert_eq!(map.get("key2"), Some("value2"));
let cloned = map.cheap_clone();
assert_eq!(cloned.get("key1"), Some("value1"));
}
}