use alloc::borrow::Cow;
#[cfg(not(feature = "extra-platforms"))]
use alloc::sync::Arc;
use core::fmt;
#[cfg(feature = "extra-platforms")]
use portable_atomic_util::Arc;
#[cfg(all(feature = "shared_ns", not(feature = "extra-platforms")))]
use std::sync::{Mutex, Weak};
use crate::strings;
#[cfg(all(feature = "shared_ns", not(feature = "extra-platforms")))]
use weak_table;
#[cfg(all(feature = "shared_ns", not(feature = "extra-platforms")))]
use alloc::string::String;
#[cfg(all(feature = "shared_ns", not(feature = "extra-platforms")))]
type StringWeakSet = weak_table::WeakHashSet<Weak<String>>;
#[derive(Default)]
pub struct Context {
#[cfg(all(feature = "shared_ns", not(feature = "extra-platforms")))]
nss: Mutex<StringWeakSet>,
#[allow(dead_code)]
phantom: (),
}
impl Context {
pub fn new() -> Context {
Context::default()
}
pub fn intern_namespace<'a, T: Into<Cow<'a, str>>>(
&self,
ns: T,
) -> strings::Namespace<'static> {
let ns = ns.into();
if let Some(result) = strings::Namespace::try_share_static(&ns) {
return result;
}
#[cfg(all(feature = "shared_ns", not(feature = "extra-platforms")))]
{
let mut nss = self.nss.lock().unwrap();
let ptr = match nss.get(&*ns) {
Some(ptr) => ptr.clone(),
None => {
let ptr = Arc::new(ns.into_owned());
nss.insert(ptr.clone());
ptr
}
};
strings::Namespace::from(ptr)
}
#[cfg(not(all(feature = "shared_ns", not(feature = "extra-platforms"))))]
strings::Namespace::from(Arc::new(ns.into_owned()))
}
pub fn release_temporaries(&self) {
#[cfg(all(feature = "shared_ns", not(feature = "extra-platforms")))]
{
let mut nss = self.nss.lock().unwrap();
nss.remove_expired();
nss.shrink_to_fit();
}
}
pub fn namespaces(&self) -> usize {
#[cfg(all(feature = "shared_ns", not(feature = "extra-platforms")))]
{
let nss = self.nss.lock().unwrap();
nss.len()
}
#[cfg(not(all(feature = "shared_ns", not(feature = "extra-platforms"))))]
0
}
pub fn cdata_capacity(&self) -> usize {
#[cfg(all(feature = "shared_ns", not(feature = "extra-platforms")))]
{
let nss = self.nss.lock().unwrap();
nss.capacity()
}
#[cfg(not(all(feature = "shared_ns", not(feature = "extra-platforms"))))]
0
}
}
impl fmt::Debug for Context {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut f = f.debug_struct("Context");
f.field("instance", &(self as *const Context));
#[cfg(all(feature = "shared_ns", not(feature = "extra-platforms")))]
{
let nss = self.nss.lock().unwrap();
f.field("nss.capacity()", &nss.capacity())
.field("nss.length()", &nss.len());
}
f.finish()
}
}
impl fmt::UpperHex for Context {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut f = f.debug_set();
#[cfg(all(feature = "shared_ns", not(feature = "extra-platforms")))]
{
let nss = self.nss.lock().unwrap();
for item in nss.iter() {
f.entry(&(Arc::strong_count(&item) - 1, &*item));
}
}
f.finish()
}
}