1use alloc::borrow::Cow;
2use alloc::sync::Arc;
3use core::fmt;
4
5#[cfg(feature = "shared_ns")]
6use std::sync::{Mutex, Weak};
7
8use crate::strings;
9
10#[cfg(feature = "shared_ns")]
11use weak_table;
12
13#[cfg(feature = "shared_ns")]
14use alloc::string::String;
15
16#[cfg(feature = "shared_ns")]
17type StringWeakSet = weak_table::WeakHashSet<Weak<String>>;
18
19#[derive(Default)]
33pub struct Context {
34 #[cfg(feature = "shared_ns")]
35 nss: Mutex<StringWeakSet>,
36 #[allow(dead_code)]
39 phantom: (),
40}
41
42impl Context {
43 pub fn new() -> Context {
45 Context::default()
46 }
47
48 pub fn intern_namespace<'a, T: Into<Cow<'a, str>>>(&self, ns: T) -> strings::Namespace {
60 let ns = ns.into();
61 if let Some(result) = strings::Namespace::try_share_static(&ns) {
62 return result;
63 }
64 #[cfg(feature = "shared_ns")]
65 {
66 let mut nss = self.nss.lock().unwrap();
67 let ptr = match nss.get(&*ns) {
68 Some(ptr) => ptr.clone(),
69 None => {
70 let ptr = Arc::new(ns.into_owned());
71 nss.insert(ptr.clone());
72 ptr
73 }
74 };
75 strings::Namespace::from(ptr)
76 }
77 #[cfg(not(feature = "shared_ns"))]
78 strings::Namespace::from(Arc::new(ns.into_owned()))
79 }
80
81 pub fn release_temporaries(&self) {
88 #[cfg(feature = "shared_ns")]
89 {
90 let mut nss = self.nss.lock().unwrap();
91 nss.remove_expired();
92 nss.shrink_to_fit();
93 }
94 }
95
96 pub fn namespaces(&self) -> usize {
102 #[cfg(feature = "shared_ns")]
103 {
104 let nss = self.nss.lock().unwrap();
105 nss.len()
106 }
107 #[cfg(not(feature = "shared_ns"))]
108 0
109 }
110
111 pub fn cdata_capacity(&self) -> usize {
115 #[cfg(feature = "shared_ns")]
116 {
117 let nss = self.nss.lock().unwrap();
118 nss.capacity()
119 }
120 #[cfg(not(feature = "shared_ns"))]
121 0
122 }
123}
124
125impl fmt::Debug for Context {
126 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
127 let mut f = f.debug_struct("Context");
128 f.field("instance", &(self as *const Context));
129 #[cfg(feature = "shared_ns")]
130 {
131 let nss = self.nss.lock().unwrap();
132 f.field("nss.capacity()", &nss.capacity())
133 .field("nss.length()", &nss.len());
134 }
135 f.finish()
136 }
137}
138
139impl fmt::UpperHex for Context {
140 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
141 let mut f = f.debug_set();
142 #[cfg(feature = "shared_ns")]
143 {
144 let nss = self.nss.lock().unwrap();
145 for item in nss.iter() {
146 f.entry(&(Arc::strong_count(&item) - 1, &*item));
147 }
148 }
149 f.finish()
150 }
151}