rust_i18n_support/
atomic_str.rs1use std::fmt;
2use std::ops::Deref;
3
4use arc_swap::{ArcSwapAny, Guard};
5use triomphe::Arc;
6
7pub struct AtomicStr(ArcSwapAny<Arc<String>>);
9
10struct GuardedStr(Guard<Arc<String>>);
12
13impl Deref for GuardedStr {
14 type Target = str;
15
16 #[inline]
17 fn deref(&self) -> &Self::Target {
18 self.0.as_str()
19 }
20}
21
22impl AtomicStr {
23 pub fn new(value: &str) -> Self {
25 let arced = Arc::new(value.into());
26 Self(ArcSwapAny::new(arced))
27 }
28
29 #[inline]
31 pub fn as_str(&self) -> impl Deref<Target = str> {
32 GuardedStr(self.0.load())
33 }
34
35 pub fn replace(&self, src: impl Into<String>) {
37 let arced = Arc::new(src.into());
38 self.0.store(arced);
39 }
40}
41
42impl From<&str> for AtomicStr {
43 fn from(value: &str) -> Self {
44 Self::new(value)
45 }
46}
47
48impl fmt::Display for AtomicStr {
49 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50 f.write_str(&self.as_str())
51 }
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57
58 fn test_str(s: &str) {
59 assert_eq!(s, "hello");
60 }
61
62 #[test]
63 fn test_atomic_str() {
64 let s = AtomicStr::from("hello");
65 test_str(&s.as_str());
66 }
67}