stringid/
static_str_store.rs

1use crate::static_str_buffer::StaticStrBuffer;
2use std::sync::{LazyLock, Mutex};
3
4/// A trait for store [`str`] until the end of program.
5///
6/// This allow to get `'static` lifetime on ref : `&'static str`
7pub trait StaticStrStore {
8	fn add(str: &str) -> &'static str;
9}
10
11/// A [`StaticStrStore`] where implementation leak allocated buffer of the [`String`].
12///
13/// This is a very simple implementation, but do one allocation by value.
14pub struct StringStrStore;
15
16impl StaticStrStore for StringStrStore {
17	fn add(value: &str) -> &'static str {
18		String::from(value).leak()
19	}
20}
21
22/// The size of buffer for [`BufferStrStore`]
23const START_BUFFER_SIZE: usize = 128 * 1024; // use block of 128ko
24
25/// A type than carry a [`StaticStrBuffer`] instance.
26pub struct BufferStrStore;
27
28impl StaticStrStore for BufferStrStore {
29	fn add(str: &str) -> &'static str {
30		Self::buffer().lock().unwrap().insert(str)
31	}
32}
33
34impl BufferStrStore {
35	fn buffer() -> &'static LazyLock<Mutex<StaticStrBuffer>> {
36		static STR_BUFFER: LazyLock<Mutex<StaticStrBuffer>> = LazyLock::new(|| {
37			log::trace!("Initialisation of StaticStrBuffer");
38			Mutex::new(StaticStrBuffer::with_capacity(START_BUFFER_SIZE))
39		});
40		&STR_BUFFER
41	}
42}
43
44#[cfg(test)]
45mod tests {
46	use super::*;
47
48	#[test]
49	fn test_string_str_store_1() {
50		const DATA_1: &str = "data_1";
51		let data_str = StringStrStore::add(DATA_1);
52		// test than str content is equal to origin
53		assert_eq!(data_str, DATA_1);
54		// test than str content is copied (ptr are different)
55		assert_ne!(data_str.as_ptr(), DATA_1.as_ptr());
56	}
57
58	#[test]
59	fn test_string_str_store_2() {
60		// test than str can be used out of the context creation
61		const DATA_1: &str = "data_1";
62		let static_str;
63		{
64			let data_str = StringStrStore::add(DATA_1);
65			static_str = data_str;
66		}
67		assert_eq!(static_str, DATA_1);
68		assert_ne!(static_str.as_ptr(), DATA_1.as_ptr());
69	}
70
71	#[test]
72	fn test_buffer_str_store_1() {
73		const DATA_1: &str = "data_1";
74		let data_str = BufferStrStore::add(DATA_1);
75		// test than str content is equal to origin
76		assert_eq!(data_str, DATA_1);
77		// test than str content is copied (ptr are different)
78		assert_ne!(data_str.as_ptr(), DATA_1.as_ptr());
79	}
80
81	#[test]
82	fn test_buffer_str_store_2() {
83		// test than str can be used out of the context creation
84		const DATA_1: &str = "data_1";
85		let static_str;
86		{
87			let data_str = BufferStrStore::add(DATA_1);
88			static_str = data_str;
89		}
90		assert_eq!(static_str, DATA_1);
91		assert_ne!(static_str.as_ptr(), DATA_1.as_ptr());
92	}
93}